__getattr__和getattr之间有什么关系?

时间:2009-12-22 07:04:19

标签: python getattr

我知道这段代码是对的:

class A:   
    def __init__(self):
        self.a = 'a'  
    def method(self):   
        print "method print"  

a = A()   
print getattr(a, 'a', 'default')   
print getattr(a, 'b', 'default')  
print getattr(a, 'method', 'default') 
getattr(a, 'method', 'default')()   

这是错误的:

# will __getattr__ affect the getattr?

class a(object):
    def __getattr__(self,name):
        return 'xxx'

print getattr(a)

这也是错误的:

a={'aa':'aaaa'}
print getattr(a,'aa')

我们应该在哪里使用__getattr__getattr

3 个答案:

答案 0 :(得分:51)

亚历克斯的答案很好,但是在你提出要求后为你提供示例代码:)

class foo:
    def __init__(self):
        self.a = "a"
    def __getattr__(self, attribute):
        return "You asked for %s, but I'm giving you default" % attribute


>>> bar = foo()
>>> bar.a
'a'
>>> bar.b
"You asked for b, but I'm giving you default"
>>> getattr(bar, "a")
'a'
>>> getattr(bar, "b")
"You asked for b, but I'm giving you default"

所以简短的回答是

您使用

__getattr__定义如何处理找不到的属性

getattr 获取 属性

答案 1 :(得分:37)

getattr是一个带有(至少)两个参数的内置函数:从中获取属性的对象,以及属性的字符串名称。

如果字符串名称是常量,例如'foo'getattr(obj, 'foo') obj.foo完全相同

因此,内置函数getattr的主要用例是当您没有将属性名称作为常量,而是作为变量。第二个重要的用例是当你传递三个参数而不是两个时:在这种情况下,如果对象中没有该属性,getattr将返回第三个“默认”参数,而不是异常。

__getattr__是一个特殊的方法,在类中定义,在请求该类的实例的某个属性时调用,以及提供该属性的其他常规方法(通过实例的__dict__全部失败,插槽,属性等等。您可以定义它,例如,当您要将其他未定义的属性查找委托给其他对象时。

所以你的第二个例子是错误的,因为内置getattr可以从不用一个参数调用。

第三个失败是因为您尝试“获取属性”的字典没有该属性 - 它具有,当然这与属性完全不相交。

答案 2 :(得分:17)

__getattr__()是您可以定义的特殊方法函数。当成员查找失败时,将调用此函数。

getattr()是您可以调用以尝试成员查找的函数。如果查找成功,则获取成员(可能是方法函数对象,或者可能是数据属性对象)。在查找失败的情况下,getattr()也可以返回默认值。

如果你宣布一个__getattr__()成员函数,你可以让它有时成功,或者你可以每次都成功。

class A(object):
    def __getattr__(self, name):
        return "I pretend I have an attribute called '%s'" % name

a = A()

print a.foo # prints "I pretend I have an attribute called 'foo'"

Python也有__getattribute__(),每次查找都会始终调用。这非常危险,因为它无法正常访问成员。

class A(object):
    def __init__(self, value):
        self.v = value
    def __getattribute__(self, name):
        return "I pretend I have an attribute called '%s'" % name

a = A(42)

print a.v # prints "I pretend I have an attribute called 'v'"
print a.__dict__["v"] # prints "I pretend I have an attribute called '__dict__'"

糟糕,现在无法访问a.v!