我试图理解什么时候定义__getattr__或__getattribute__。python文档提到__getattribute__适用于新样式的类。什么是新型类?
当前回答
我发现没有人提到这个区别:
__getattribute__有默认实现,但__getattr__没有。
class A:
pass
a = A()
a.__getattr__ # error
a.__getattribute__ # return a method-wrapper
这有一个明确的含义:因为__getattribute__有默认实现,而__getattr__没有,显然python鼓励用户实现__getattr__。
其他回答
新型类是直接或间接继承“object”的类。除了__init__之外,它们还有一个__new__类方法,并且有一些更合理的低级行为。
通常,你会想要重写__getattr__(如果你重写了其中任何一个),否则你将很难支持“self”。方法中的Foo语法。
额外信息:http://www.devx.com/opensource/Article/31482/0/page/4
让我们看一些__getattr__和__getattribute__神奇方法的简单例子。
__getattr__
每当你请求一个尚未定义的属性时,Python将调用__getattr__方法。在下面的例子中,我的类Count没有__getattr__方法。在main中,当我访问两个obj1时。Mymin和obj1。Mymax属性一切正常。但当我访问obj1时。` Count `对象没有属性` mycurrent `
class Count():
def __init__(self,mymin,mymax):
self.mymin=mymin
self.mymax=mymax
obj1 = Count(1,10)
print(obj1.mymin)
print(obj1.mymax)
print(obj1.mycurrent) --> AttributeError: 'Count' object has no attribute 'mycurrent'
现在我的类Count有__getattr__方法。当我访问obj1时。mycurrent属性——python返回我在__getattr__方法中实现的任何内容。在我的例子中,每当我试图调用一个不存在的属性时,python都会创建该属性并将其设置为整数值0。
class Count:
def __init__(self,mymin,mymax):
self.mymin=mymin
self.mymax=mymax
def __getattr__(self, item):
self.__dict__[item]=0
return 0
obj1 = Count(1,10)
print(obj1.mymin)
print(obj1.mymax)
print(obj1.mycurrent1)
__getattribute__
现在让我们看看__getattribute__方法。如果你的类中有__getattribute__方法,python会为每个属性调用这个方法,不管它是否存在。那么为什么我们需要__getattribute__方法呢?一个很好的理由是,您可以阻止对属性的访问,并使它们更加安全,如下面的示例所示。
每当有人试图访问以子字符串“cur”开头的属性时,python会引发AttributeError异常。否则它会返回该属性。
class Count:
def __init__(self,mymin,mymax):
self.mymin=mymin
self.mymax=mymax
self.current=None
def __getattribute__(self, item):
if item.startswith('cur'):
raise AttributeError
return object.__getattribute__(self,item)
# or you can use ---return super().__getattribute__(item)
obj1 = Count(1,10)
print(obj1.mymin)
print(obj1.mymax)
print(obj1.current)
重要提示:为了避免__getattribute__方法中的无限递归,它的实现应该始终调用具有相同名称的基类方法来访问所需的任何属性。例如:object。__getattribute__(self, name)或super().__getattribute__(item)而不是self.__dict__[item]
重要的
如果你的类同时包含getattr和getattribute魔法方法,那么__getattribute__将首先被调用。但是如果__getattribute__引发 AttributeError异常,则该异常将被忽略,并调用__getattr__方法。示例如下:
class Count(object):
def __init__(self,mymin,mymax):
self.mymin=mymin
self.mymax=mymax
self.current=None
def __getattr__(self, item):
self.__dict__[item]=0
return 0
def __getattribute__(self, item):
if item.startswith('cur'):
raise AttributeError
return object.__getattribute__(self,item)
# or you can use ---return super().__getattribute__(item)
# note this class subclass object
obj1 = Count(1,10)
print(obj1.mymin)
print(obj1.mymax)
print(obj1.current)
在阅读Beazley & Jones PCB时,我偶然发现了__getattr__的一个明确而实际的用例,它有助于回答OP问题的“何时”部分。摘自书中:
"The __getattr__() method is kind of like a catch-all for attribute lookup. It's a method that gets called if code tries to access an attribute that doesn't exist." We know this from the above answers, but in PCB recipe 8.15, this functionality is used to implement the delegation design pattern. If Object A has an attribute Object B that implements many methods that Object A wants to delegate to, rather than redefining all of Object B's methods in Object A just to call Object B's methods, define a __getattr__() method as follows:
def __getattr__(self, name):
return getattr(self._b, name)
其中_b是Object A的属性(Object B)的名称。当Object B上定义的方法在Object A上被调用时,__getattr__方法将在查找链的末尾被调用。这也会使代码更干净,因为您不需要为委托给另一个对象而定义一个方法列表。
我发现没有人提到这个区别:
__getattribute__有默认实现,但__getattr__没有。
class A:
pass
a = A()
a.__getattr__ # error
a.__getattribute__ # return a method-wrapper
这有一个明确的含义:因为__getattribute__有默认实现,而__getattr__没有,显然python鼓励用户实现__getattr__。
new -style类继承自object或另一个new -style类:
class SomeObject(object):
pass
class SubObject(SomeObject):
pass
老式的类没有:
class SomeObject:
pass
这只适用于python2 -在python3中,上述所有将创建新样式的类。
看到9。类(Python教程),NewClassVsClassicClass和Python中新旧风格类之间的区别是什么?获取详细信息。
推荐文章
- 证书验证失败:无法获得本地颁发者证书
- 当使用pip3安装包时,“Python中的ssl模块不可用”
- 无法切换Python与pyenv
- Python if not == vs if !=
- 如何从scikit-learn决策树中提取决策规则?
- 为什么在Mac OS X v10.9 (Mavericks)的终端中apt-get功能不起作用?
- 将旋转的xtick标签与各自的xtick对齐
- 为什么元组可以包含可变项?
- 如何合并字典的字典?
- 如何创建类属性?
- 不区分大小写的“in”
- 在Python中获取迭代器中的元素个数
- 解析日期字符串并更改格式
- 使用try和。Python中的if
- 如何在Python中获得所有直接子目录