Yar*_*rin 378 python getattr getattribute
我想知道何时使用__getattr__或__getattribute__.该文件提到了__getattribute__适用于新样式类.什么是新式课程?
Ned*_*der 455
__getattr__和之间的关键区别仅__getattribute__在于__getattr__找不到通常方式的属性时才会调用.这对于实现缺少属性的后备是有好处的,并且可能是您想要的两个中的一个.
__getattribute__在查看对象的实际属性之前调用,因此正确实现可能很棘手.您最终可以轻松地进行无限递归.
新式类派生自object,旧式类是Python 2.x中没有明确基类的类.但旧式和新式的类之间的区别并不之间进行选择时的重要的__getattr__和__getattribute__.
你几乎肯定想要__getattr__.
N R*_*awa 114
让我们看一下两个简单的例子__getattr__和__getattribute__魔术方法.
__getattr____getattr__每当您请求尚未定义的属性时,Python都会调用 方法.在以下示例中,我的类Count没有__getattr__方法.现在,在主,当我试图同时访问obj1.mymin和obj1.mymax属性,一切工作正常.但是当我尝试访问obj1.mycurrent属性时 - Python给了我AttributeError: 'Count' object has no attribute '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'
Run Code Online (Sandbox Code Playgroud)
现在我的类计数有__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)
Run Code Online (Sandbox Code Playgroud)
__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)
Run Code Online (Sandbox Code Playgroud)
要点:为了避免__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)
Run Code Online (Sandbox Code Playgroud)
Sam*_*lan 15
新样式类继承object自另一个新样式类:
class SomeObject(object):
pass
class SubObject(SomeObject):
pass
Run Code Online (Sandbox Code Playgroud)
旧式课不:
class SomeObject:
pass
Run Code Online (Sandbox Code Playgroud)
这仅适用于Python 2 - 在Python 3中,以上所有内容都将创建新式类.
请参阅9.类(Python教程),NewClassVsClassicClass以及Python中旧样式和新样式类之间的区别是什么?详情.
Sim*_*4ya 14
这只是基于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')
Run Code Online (Sandbox Code Playgroud)
如果使用相同的示例,__getattribute__您将获得>>>RuntimeError: maximum recursion depth exceeded while calling a Python object
新式类是"对象"(直接或间接)的子类.它们除了具有__new__类方法,__init__并且具有更合理的低级行为.
通常,你会想要覆盖__getattr__(如果你要覆盖它们),否则你将很难在你的方法中支持"self.foo"语法.
额外信息:http://www.devx.com/opensource/Article/31482/0/page/4
小智 6
回到__getattribute__函数;如果默认实现未被覆盖;执行该方法时会进行以下检查:
\n这是实际的实现 of the object.__getattribute__ method:
\n\n\n.. c:function:: PyObject* PyObject_GenericGetAttr(PyObject *o,\nPyObject *name) 通用属性 getter 函数,用于\n放入类型对象的 tp_getattro 槽中。它在对象的 MRO 中的类字典中查找描述符,并在对象的 :attr:~object 中查找属性。词典 (if\npresent). As outlined in :ref:descriptors, data descriptors take\npreference over instance attributes, while non-data descriptors\ndon't. Otherwise, an :exc:AttributeError is raised.
\n
我发现没有人提到这个区别:
__getattribute__有一个默认实现,但__getattr__没有。
class A:
pass
a = A()
a.__getattr__ # error
a.__getattribute__ # return a method-wrapper
Run Code Online (Sandbox Code Playgroud)
这有一个明确的含义:既然__getattribute__有默认实现,而__getattr__没有,显然 python 鼓励用户实现__getattr__.
在阅读 Beazley & Jones PCB 时,我偶然发现了一个明确且实用的用例,它__getattr__有助于回答 OP 问题的“何时”部分。摘自书中:
“该__getattr__()方法有点像属性查找的包罗万象。如果代码尝试访问不存在的属性,就会调用该方法。” 我们从上面的答案中知道了这一点,但在 PCB 配方 8.15 中,此功能用于实现委托设计模式。如果对象A有一个属性对象B实现了对象A想要委托的很多方法,那么与其在对象A中重新定义对象B的所有方法只是为了调用对象B的方法,不如定义一个方法如下__getattr__():
def __getattr__(self, name):
return getattr(self._b, name)
Run Code Online (Sandbox Code Playgroud)
其中 _b 是对象 A 的属性名称,该属性是对象 B。当在对象 A 上调用对象 B 上定义的方法时,__getattr__将在查找链的末尾调用该方法。这也会使代码更清晰,因为您没有仅为委托给另一个对象而定义的方法列表。
| 归档时间: |
|
| 查看次数: |
115446 次 |
| 最近记录: |