Python中的getattr()和__getattr__方法

在看python核心编程时,看到了getattr()内建函数和__getattr__,但不太理解,就仔细的看了下并查阅了一些资料,大致了解了它们是做什么的。

getattr()
先在python解释器看下getattr()的帮助
Help on built-in function getattr in module __builtin__:

getattr(...)
    getattr(object, name[, default]) -> value
    
    Get a named attribute from an object; getattr(x, 'y') is equivalent to x.y.
    When a default argument is given, it is returned when the attribute doesn't
    exist; without it, an exception is raised in that case.
(END)

getattr(),顾名思义就是获取对象的属性,getattr(x, 'y')等价于 x.y。 第三个参数可有可无,当给getattr()第三个参数时,如果对应的属性不存在,它会作为返回值返回。
看下面代码:

class Test(object):
     val = 1
 
>>> Test.val
1
>>> getattr(Test, 'val')
1
>>> getattr(Test, 'va', 5)
5


因为val是Test的属性,所以通过getattr可以获取到val的值,而va则不是Test的属性,但我们传进了第三个参数5,所以返回5。


使用 内建函数dir()可以查看一个对象的属性,如下
>>> dir(Test)
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'val']

再看看下面的例子:
dir1 = {}
dir1['a'] = 1
dir2['b'] = 2
>>> getattr(dir1, 'a')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>

AttributeError: 'dict' object has no attribute 'a'


但为什么通过getattr获取不了dir1['a']的值呢?根据解释器的错误信息就可以看出dir1没有名为‘a'的属性。

再使用dir(dir1)来看下

>>> dir(dir1)

['__class__', '__cmp__', '__contains__', '__delattr__', '__delitem__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'clear', 'copy', 'fromkeys', 'get', 'has_key', 'items', 'iteritems', 'iterkeys', 'itervalues', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values', 'viewitems', 'viewkeys', 'viewvalues']


dir1的确没有'a'这个属性,但是有__str__这个属性

>>> getattr(dir1, '__str__')()
"{'a': 1, 'b': 2}"
>>> dir1.__str__()
"{'a': 1, 'b': 2}"


在调用getattr(obj,name)时,如果实例obj没有name属性,则会去调用类中的__getattr__

__getattr__
__getattr__()是仅当属性不能在实例的__dict__或它的类(类的__dict__),或父类的__dict__中找到时,才被调用。一般在代码中包含一个对getattr()內建函数的调用

每一个类都会用一个字典,把它包含的属性放到自己的字典里。


>>> Test.__dict__

dict_proxy({'__dict__': <attribute '__dict__' of 'Test' objects>, '__module__': '__main__', '__weakref__': <attribute '__weakref__' of 'Test' objects>, '__doc__': None, 'val': 1})


看下面的示例代码
#!/usr/bin/env python


class Test1(object):


    def __init__(self, obj):
        print "In __init__"
        self.data = obj


    def __str__(self):
        print "In __str__"
        return str(self.data)


    __repr__ = __str__


    def get_attr(self):
        print "In getattr"
        return self.data


    def __getattr__(self, attr):
        print "In __getattr__"
        return getattr(self.data, attr)


if __name__ == '__main__':
    myString = Test1('hello')
    print myString
    print myString.upper()
    print myString.get_attr()


看下输出结果
cullen@cullen--machine:~/python$ ./getattr.py 
In __init__
In __str__
hello
In __getattr__
HELLO
In getattr
hello


下面对结果进行简要的分析
myString = Test1('hello')
//输出结果In __init__, 不用解释了吧
print myString
//输出结果
//In __str__
//hello

print myString.upper()
//输出结果
//In __getattr__
//HELLO

重点就在这里,我们的实例myString并没有upper()这个属性,所以myString.upper()等价于getattr(myString.data, upper)()
print myString.get_attr()
//输出结果,因为gets_attr()是myString的属性,所以没有调用__getattr__。
//In getattr
//hello



                                       







你可能感兴趣的:(编程,python,对象,Class,实例)