我试图理解什么时候定义__getattr__或__getattribute__。python文档提到__getattribute__适用于新样式的类。什么是新型类?
当前回答
__getattr__和__getattribute__之间的一个关键区别是,__getattr__只在没有以通常的方式找到属性时才会被调用。它很适合为缺失的属性实现回退,并且可能是您想要的两种方法之一。
__getattribute__是在查看对象上的实际属性之前调用的,因此正确实现可能很棘手。你可以很容易地得到无限递归。
新类型的类派生于object,旧类型的类是Python 2中的类。没有显式基类的X。但是在__getattr__和__getattribute__之间进行选择时,旧风格和新风格类之间的区别并不是重要的一个。
你几乎肯定想要__getattr__。
其他回答
让我们看一些__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)
这只是一个基于Ned Batchelder解释的例子。
__getattr__例子:
class Foo(object):
def __getattr__(self, attr):
print "looking up", attr
value = 42
self.__dict__[attr] = value
return value
f = Foo()
print f.x
#output >>> looking up x 42
f.x = 3
print f.x
#output >>> 3
print ('__getattr__ sets a default value if undefeined OR __getattr__ to define how to handle attributes that are not found')
如果同样的例子使用__getattribute__,你会得到>>> RuntimeError:调用Python对象时超过最大递归深度
__getattr__和__getattribute__之间的一个关键区别是,__getattr__只在没有以通常的方式找到属性时才会被调用。它很适合为缺失的属性实现回退,并且可能是您想要的两种方法之一。
__getattribute__是在查看对象上的实际属性之前调用的,因此正确实现可能很棘手。你可以很容易地得到无限递归。
新类型的类派生于object,旧类型的类是Python 2中的类。没有显式基类的X。但是在__getattr__和__getattribute__之间进行选择时,旧风格和新风格类之间的区别并不是重要的一个。
你几乎肯定想要__getattr__。
new -style类继承自object或另一个new -style类:
class SomeObject(object):
pass
class SubObject(SomeObject):
pass
老式的类没有:
class SomeObject:
pass
这只适用于python2 -在python3中,上述所有将创建新样式的类。
看到9。类(Python教程),NewClassVsClassicClass和Python中新旧风格类之间的区别是什么?获取详细信息。
我发现没有人提到这个区别:
__getattribute__有默认实现,但__getattr__没有。
class A:
pass
a = A()
a.__getattr__ # error
a.__getattribute__ # return a method-wrapper
这有一个明确的含义:因为__getattribute__有默认实现,而__getattr__没有,显然python鼓励用户实现__getattr__。
推荐文章
- 如何在Flask-SQLAlchemy中按id删除记录
- 在Python中插入列表的第一个位置
- Python Pandas只合并某些列
- 如何在一行中连接两个集而不使用“|”
- 从字符串中移除前缀
- 代码结束时发出警报
- 如何在Python中按字母顺序排序字符串中的字母
- 在matplotlib中将y轴标签添加到次要y轴
- 如何消除数独方块的凹凸缺陷?
- 为什么出现这个UnboundLocalError(闭包)?
- 使用Python请求的异步请求
- 如何检查一个对象是否是python中的生成器对象?
- 如何从Python包内读取(静态)文件?
- 如何计算一个逻辑sigmoid函数在Python?
- python: SyntaxError: EOL扫描字符串文字