Python class 具有默认属性工厂
Python class with default attribute factory
我想创建一个 python class,只要访问不存在的属性,它就会执行特定的方法。最终目标是创建一个对象,如果尚未加载属性,则从文件系统加载属性。
我目前的想法是用 defaultdict
替换 __dict__
属性,并用访问 __dict__
属性的方法覆盖 __getattr__
方法。这看起来像这样:
class MyClass():
def __init__(self):
self.__dict__ = defaultdict(lambda: "Now we would load and return the object...",
self.__dict__)
self.attribute = "An attribute"
def __getattr__(self, *args, **kwargs):
return self.__dict__.__getitem__(*args, **kwargs)
期望的行为如下:
>>> a = MyClass()
>>> a.attribute
'An attribute'
>>> a.non_existent_attribute
'Now we would load and return the object...'
据我所知,这是可行的。我现在想知道这个过程的隐藏成本是什么,是否有更优雅的方法来实现它。
- 覆盖
__getattr__
是否会对计算性能产生重大影响?
- 是否有可能的实现仅在因属性不存在而引发错误时跳入? (那么当访问现有属性时,对象的行为不会有所不同。)
- 现在是否会在访问属性时考虑 defaultdict 还是有其他方法可以访问我错过的属性? (如果替换普通对象,此实现会导致错误吗?)
- 我可能错过了与此方法相关的风险吗?
一个更简单的定义,不需要更改 self.__dict__
的值:
class MyClass():
def _load_attribute(self, name):
"""Load value for attribute <name> from disk"""
def __getattr__(self, name):
value = self._load_attribute(name)
setattr(self, name, value)
return value
m = MyClass()
print(m.foo) # Calls m._load_attribute("foo") from m.__getattr_ to set m.foo
print(m.foo) # Accesses m.foo directly, without calling m.__getattr__
__getattr__
仅针对通过正常查找算法找不到的属性调用;一旦 setattr
被调用,属性 将 被正常找到,因此 __getattr__
每个属性只会被调用一次。
我想创建一个 python class,只要访问不存在的属性,它就会执行特定的方法。最终目标是创建一个对象,如果尚未加载属性,则从文件系统加载属性。
我目前的想法是用 defaultdict
替换 __dict__
属性,并用访问 __dict__
属性的方法覆盖 __getattr__
方法。这看起来像这样:
class MyClass():
def __init__(self):
self.__dict__ = defaultdict(lambda: "Now we would load and return the object...",
self.__dict__)
self.attribute = "An attribute"
def __getattr__(self, *args, **kwargs):
return self.__dict__.__getitem__(*args, **kwargs)
期望的行为如下:
>>> a = MyClass()
>>> a.attribute
'An attribute'
>>> a.non_existent_attribute
'Now we would load and return the object...'
据我所知,这是可行的。我现在想知道这个过程的隐藏成本是什么,是否有更优雅的方法来实现它。
- 覆盖
__getattr__
是否会对计算性能产生重大影响? - 是否有可能的实现仅在因属性不存在而引发错误时跳入? (那么当访问现有属性时,对象的行为不会有所不同。)
- 现在是否会在访问属性时考虑 defaultdict 还是有其他方法可以访问我错过的属性? (如果替换普通对象,此实现会导致错误吗?)
- 我可能错过了与此方法相关的风险吗?
一个更简单的定义,不需要更改 self.__dict__
的值:
class MyClass():
def _load_attribute(self, name):
"""Load value for attribute <name> from disk"""
def __getattr__(self, name):
value = self._load_attribute(name)
setattr(self, name, value)
return value
m = MyClass()
print(m.foo) # Calls m._load_attribute("foo") from m.__getattr_ to set m.foo
print(m.foo) # Accesses m.foo directly, without calling m.__getattr__
__getattr__
仅针对通过正常查找算法找不到的属性调用;一旦 setattr
被调用,属性 将 被正常找到,因此 __getattr__
每个属性只会被调用一次。