class lazy:
# 告訴 Python 不要建立物件的 __dict__,而是隻給一個固定集合的屬性分配空間。
__slots__ = ['func']
def __init__(self, func):
self.func = func
def __get__(self, instance, owner):
name = self.func.__name__
# 如果 func 不為 None 則賦值給 owner (這裡是 `MyClass`) 的 `name` 屬性,
# 此後 owner 的 name() 不再是裝飾器方法,而是實實在在的 func() 方法返回值!
if (v := self.func(owner)) is not None:
setattr(owner, name, v)
return owner.__dict__.get(name) if v else None
class MyClass:
@lazy
def name(self) -> str:
print("debug: name(self)")
return "get name"
if __name__ == '__main__':
name = MyClass.name # output: 'debug: name(self)'
print(f'[{name}]', type(name)) # => [get name] <class 'str'>
print(f'[{MyClass.name}]') # => [get name]
第一次呼叫 MyClass.name
時會進入到裝飾器的 __get__
方法中返回值,我們在 __get__
方法的內部再重新把裝飾器的 func
返回值賦值給 owner
( 這裡是 MyClass
) 的 name
屬性,從而達到 替換值 的概念。
本作品採用《CC 協議》,轉載必須註明作者和本文連結