38

我知道这段代码是正确的:

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__and getattr

4

3 回答 3

62

亚历克斯的回答很好,但是在您要求时为您提供了示例代码:)

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获取属性_ _

于 2009-12-22T07:26:49.667 回答
39

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

如果字符串名称是一个常数,比如说'foo'getattr(obj, 'foo')与 完全一样obj.foo

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

__getattr__是在类中定义的特殊方法,当请求该类的实例的某些属性时调用该方法,并且提供该属性的其他常规方法(通过实例的__dict__、槽、属性等)都失败了。例如,当您想将其他未定义的属性查找委托给其他对象时,您可以定义它。

所以你的第二个例子是错误的,因为内置getattr函数永远不能用单个参数调用。

第三个失败是因为您尝试从中“获取属性”的字典没有该属性-它具有items,当然它们与属性完全脱节。

于 2009-12-22T07:14:16.307 回答
19

__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__'"

糟糕,现在无法访问 av!

于 2009-12-22T07:28:59.153 回答