我想知道,如果我有这样的课程
class Test(object):
def __init__(self):
self.a = 20
self.b = 30
obj = Test()
当我做obj.a
时,那么先叫它?
__getattr__
或getattr
或在__dict__['a']
与setattr
对象。 __ getattr __ (自我,名称)
当属性查找未在通常位置找到属性时调用(即,它不是实例属性,也不是在类树中找到自己)。 name是属性名称。此方法应返回(计算的)属性值或引发AttributeError异常。
它说在通常的地方找不到。什么是平常的地方。我想知道什么时候叫它
此object.__getattribute__(self, name)
任何人都可以举例说明所有的使用方法
答案 0 :(得分:38)
这有点复杂。以下是Python请求对象属性时的检查顺序。
首先,Python将检查对象的类是否具有__getattribute__
方法。如果它没有定义,它将继承object.__getattribute__
,它实现了查找属性值的其他方法。
下一项检查是在对象的班级__dict__
中。但是,即使在那里找到了值,也可能不是属性查找的结果!如果在此处找到,则只有“数据描述符”优先。最常见的数据描述符是property
对象,它是每次访问属性时将调用的函数的包装器。您可以使用装饰器创建属性:
class foo(object):
@property
def myAttr(self):
return 2
在这个类中,myAttr
是一个数据描述符。这只是意味着它通过同时使用__get__
和__set__
方法来实现描述符协议。 property
是数据描述符。
如果该类在其__dict__
中没有包含所请求名称的任何内容,object.__getattribute__
将搜索其基类(在MRO之后)以查看是否继承了该类。继承的数据描述符就像对象类中的一样。
如果找到数据描述符,则调用它的__get__
方法,返回值成为属性查找的值。如果找到一个不是数据描述符的对象,它会暂时保留,但暂不返回。
接下来,检查对象自己的__dict__
的属性。这是找到大多数正常成员变量的地方。
如果对象的__dict__
没有任何内容,但是通过类(或基类)的早期搜索发现了除数据描述符之外的其他内容,那么它将具有下一个优先级。将简单地返回一个普通的类变量,但“非数据描述符”将获得更多的处理。
非数据描述符是具有__get__
方法但没有__set__
方法的对象。最常见的非数据描述符类型是函数,当从对象作为非数据描述符进行访问时,它们成为绑定方法(这就是Python可以自动将对象作为第一个参数传递的方式)。将调用描述符的__get__
方法,它的返回值将是属性查找的结果。
最后,如果之前的检查都没有成功,将调用__getattr__
(如果存在)。
以下是一些使用稳定增加的优先级属性访问机制来覆盖其父类行为的类:
class O1(object):
def __getattr__(self, name):
return "__getattr__ has the lowest priority to find {}".format(name)
class O2(O1):
var = "Class variables and non-data descriptors are low priority"
def method(self): # functions are non-data descriptors
return self.var
class O3(O2):
def __init__(self):
self.var = "instance variables have medium priority"
self.method = lambda: self.var # doesn't recieve self as arg
class O4(O3):
@property # this decorator makes this instancevar into a data descriptor
def var(self):
return "Data descriptors (such as properties) are high priority"
@var.setter # I'll let O3's constructor set a value in __dict__
def var(self, value):
self.__dict__["var"] = value # but I know it will be ignored
class O5(O4):
def __getattribute__(self, name):
if name in ("magic", "method", "__dict__"): # for a few names
return super(O5, self).__getattribute__(name) # use normal access
return "__getattribute__ has the highest priority for {}".format(name)
并且,演示了这些课程:
O1(__getattr__
):
>>> o1 = O1()
>>> o1.var
'__getattr__ has the lowest priority to find var'
O2(类变量和非数据描述符):
>>> o2 = O2()
>>> o2.var
Class variables and non-data descriptors are low priority'
>>> o2.method
<bound method O2.method of <__main__.O2 object at 0x000000000338CD30>>
>>> o2.method()
'Class variables and non-data descriptors are low priority'
O3(实例变量,包括本地重写的方法):
>>> o3 = O3()
>>> o3.method
<function O3.__init__.<locals>.<lambda> at 0x00000000034AAEA0>
>>> o3.method()
'instance variables have medium priority'
>>> o3.var
'instance variables have medium priority'
O4(数据描述符,使用property
装饰器):
>>> o4 = O4()
>>> o4.method()
'Data descriptors (such as properties) are high priority'
>>> o4.var
'Data descriptors (such as properties) are high priority'
>>> o4.__dict__["var"]
'instance variables have medium priority'
O5(__getattribute__
):
>>> o5 = O5()
>>> o5.method
<function O3.__init__.<locals>.<lambda> at 0x0000000003428EA0>
>>> o5.method()
'__getattribute__ has the highest priority for var'
>>> o5.__dict__["var"]
'instance variables have medium priority'
>>> o5.magic
'__getattr__ has the lowest priority to find magic'
答案 1 :(得分:1)
class test():
def __init__(self):
self.a = 1
def __getattribute__(self, attr):
print 'Getattribute:',attr
def __getattr__(self, attr):
print 'GetAttr:',attr
def __dict__(self, attr):
print 'Dict:',attr
def __call__(self, args=None):
print 'Called:',args
def __getitem__(self, attr):
print 'GetItem:',attr
def __get__(self, instance, owner):
print 'Get:',instance,owner
def __int__(self):
print 'Int'
x = test()
print x.a
以上都不会被称为..
[root@faparch doxid]# python -m trace --trace test_dict.py
--- modulename: test_dict, funcname: <module>
test_dict.py(1): class test():
--- modulename: test_dict, funcname: test
test_dict.py(1): class test():
test_dict.py(2): def __init__(self):
test_dict.py(5): def __getattribute__(self, attr):
test_dict.py(8): def __getattr__(self, attr):
test_dict.py(11): def __dict__(self, attr):
test_dict.py(14): def __call__(self, args=None):
test_dict.py(17): def __getitem__(self, attr):
test_dict.py(20): def __get__(self, instance, owner):
test_dict.py(23): def __int__(self):
test_dict.py(28): x = test()
--- modulename: test_dict, funcname: __init__
test_dict.py(3): self.a = 1
test_dict.py(29): print x.a
1
--- modulename: trace, funcname: _unsettrace
trace.py(80): sys.settrace(None)
您可能需要查看:http://docs.python.org/2/library/numbers.html#numbers.Number 很可能你需要实现一个处理数字类函数的嵌套类,以抢夺例如示例中的调用。或者,至少这是一种做法..
['__abs__', '__add__', '__and__', '__class__', '__cmp__', '__coerce__', '__delattr__', '__div__', '__divmod__', '__doc__', '__float__', '__floordiv__', '__format__', '__getattribute__', '__getnewargs__', '__hash__', '__hex__', '__index__', '__init__', '__int__', '__invert__', '__long__', '__lshift__', '__mod__', '__mul__', '__neg__', '__new__', '__nonzero__', '__oct__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdiv__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', '__xor__', 'bit_length', 'conjugate', 'denominator', 'imag', 'numerator', 'real']
答案 2 :(得分:0)
首先调用命名空间字典(__dict__
)。
来自docs
:
一个类实例有一个名称实现为字典的名称空间 搜索属性引用的第一个位置。当一个 在那里找不到属性,并且实例的类有一个 通过该名称的属性,搜索继续使用类属性 如果没有找到类属性,并且对象的类有一个 调用
__getattr__()
方法来满足查找。
无条件调用以实现实例的属性访问 班上的。如果该类也定义
__getattr__()
,后者将定义 除非__getattribute__()
明确地或者明确地调用它,否则不会被调用 提出AttributeError
。这个方法应该返回(计算) 属性值或引发AttributeError
例外。
object.__getattr__(self, name)
上的文档:
如果通过正常机制找到该属性,
__getattr__()
不被称为。
答案 3 :(得分:0)
来自the docs:
...例如,obj.d查找d in 对象词典如果d定义方法
__get__()
,那么 根据列出的优先规则调用d.__get__(obj)
下方。... 对于物体,机器在
object.__getattribute__()
中 将b.x
转换为type(b).__dict__['x'].__get__(b, type(b))
。该 实现通过提供数据的优先级链来工作 描述符优先于实例变量,实例变量 优先于非数据描述符,并为其分配最低优先级__getattr__()
如果提供的话。
即,obj.a
调用__getattribute__()
,默认使用__dict__
。 __getattr__()
被称为最后的手段。其余的描述描述符,例如property
或普通方法行为。
d
如何定义方法__get__()
import random
class C(object):
@property
def d(self):
return random.random()
c = C()
print(c.d)