1、getattr:当你访问一个对象的属性,而该属性在对象中不存在时,Python 会调用 getattr 方法。注意,这个方法只会在属性不存在时被调用。
class MyClass:
def init(self):
self.existing_attribute = "I exist!"
def getattr(self, name):
return f"Attribute '{name}' not found!"
创建类的实例
obj = MyClass()
访问存在的属性
print(obj.existing_attribute) # 输出: I exist!
访问不存在的属性
print(obj.some_missing_attribute) # 输出: Attribute 'some_missing_attribute' not found!
2、getattribute: 无论属性是否存在,都会被调用。通常不建议直接重写,除非你有特殊需求。
class InfiniteLoop:
def getattr(self, name):
return self.some_missing_attribute # 这将导致无限递归
当你访问一个对象的属性时,Python 会首先调用 getattribute 方法。
如果 getattribute 没有显式地抛出 AttributeError,则不会调用 getattr。
这意味着 getattribute 可以控制所有的属性访问,包括那些存在的属性。
注意事项1.必须调用 super().getattribute: 如果你重写了 getattribute,通常需要调用 super().getattribute(name) 来实际获取属性的值。否则,你可能无法访问对象的任何属性。
2.性能影响: 因为 getattribute 在每次属性访问时都会被调用,所以不当的实现可能会导致性能问题。
3.避免无限递归: 在 getattribute 中,如果你直接访问对象的属性而不通过 super(),可能会导致无限递归。例如:
class InfiniteLoop:
def getattribute(self, name):
return self.some_attribute # 这将导致无限递归
class SafeAccess:
def getattribute(self, name):
return super().getattribute(name)
4.与 getattr 的区别: getattribute 总是被调用,而 getattr 只有在属性不存在时才被调用。如果你同时定义了这两个方法,getattribute 会优先被调用。
5 高级用法: 由于 getattribute 能够拦截所有的属性访问,它可以用于实现代理模式、跟踪属性访问、调试等高级功能。