python反射与自省getattr入门篇
getattr是python内置函数中的一个。其就在用方法是:getattr(object,“attribution”,None) ,一般情况我们这么用getattr(object,name)。一般来说这里的object是对象,name传的是字符串。对象又是什么呢?可以简单的理解为:在import 引入模块时,通过dir可查询的目标就是对像,而查询得到的结果就是属性,属性就是getattr用法中name部分传入的值。
一、getattr交互式理解
便于理解,我们先交互式的示例看下getattr的用法:
1>>> class test:
2... cal=1
3...
4>>> getattr(test,"cal")
51
6>>> test.cal
上面这个结果很容易理解,cal是test类的一个属性。而如何理解对象呢?这里就用到了dir命令,具体如下:
1>>> dir(test)
2['__doc__', '__module__', 'cal']
3>>> getattr(test,__doc__)
4Traceback (most recent call last):
5 File "<stdin>", line 1, in <module>
6TypeError: getattr(): attribute name must be string
7>>> getattr(test,'__doc__')
上例中test是对象,可以传入的属性有查询到的三个结果。再看一个例子:
1>>> t = {}
2>>> t['a'] = "hello"
3>>> t['b'] = "world"
4>>> getattr(t,"a")
5Traceback (most recent call last):
6 File "<stdin>", line 1, in <module>
7AttributeError: 'dict' object has no attribute 'a'
上面t是一个字典,为什么传入a不行呢?因为a不是t的属性。t的属性有哪些呢?看下面:
1>>> dir(t)
2['__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']
看到了吧,这里面没有“a”, __str__是t的属性。我们试下
1>>> getattr(t,"__str__")
2<method-wrapper '__str__' of dict object at 0x1bbb230>
3>>> getattr(t,"__str__")()
4"{'a': 'hello', 'b': 'world'}"
5>>> t.__str__()
6"{'a': 'hello', 'b': 'world'}"
因为__str__ 是一个函数,所以在通过getattr调用出来执行后是一个内存地址,显示结果需要像调用函数一样加上括号。
二、__getattr__ 方法
在python中以开头,并以结尾的方法我们称之为魔术方法或专用方法,同样也存在一个getattr 方法。该方法是仅当属性不能在实例的dict或它的类(类的dict),或父类其dict中找到时,才被调用。一般在代码中包含一个对getattr()內建函数的调用。
每一个类都会用一个字典,把它包含的属性放到自己的字典里(这是内建的)。接着上面的例子,我们使用__dict__ 查看下返回值:
1>>> test.__dict__
2{'__module__': '__main__', '__doc__': None, 'cal': 1}
还是上面的test类,这里三个对象都以键值对的形式显示出来了。
再来个示例:
1#!/usr/bin/env python
2## site: www.361way.com
3## desc: getattr and __getattr
4class WrapMe(object):
5 def __init__(self,obj):
6 print "I am in init"
7 self.__data = obj
8 def get(self):
9 print "I am in get"
10 return self.__data
11 def __repr__(self):
12 print "I am in repr"
13 return 'self.__data'
14 def __str__(self):
15 print "I am in str"
16 return str(self.__data)
17 def __getattr__(self, attr):
18 print "I am in getattr"
19 return getattr(self.__data, attr)
20if __name__ == "__main__":
21 wcomplex = WrapMe(3.5+4.2j)
22 print wcomplex
23 print wcomplex.real
24 print wcomplex.get()
执行该脚本后输出结果如下:
1I am in init
2I am in str
3(3.5+4.2j)
4I am in getattr
53.5
6I am in get
7(3.5+4.2j)
执行过程分析如下:
1、wcomplex = WrapMe(3.5+4.2j)该包执行时,会运行__init__将类实例化,会输出I am in init;
2、执行print wcomplex语句时调用的是__str__ 函数,此时输出I am in str (3.5+4.2j),后面的对象输出是因为调用了return str(self.__data);
3、real 属性由于不存在,所以执行时,这里便返回了__getattr__ 方法的内容。返回结果应该也不难猜到吧;
4、get方法更不用解释了。因为存在,按类中的get方法输出即可。
捐赠本站(Donate)
如您感觉文章有用,可扫码捐赠本站!(If the article useful, you can scan the QR code to donate))
- Author: shisekong
- Link: https://blog.361way.com/python-reflex-getattr/5006.html
- License: This work is under a 知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议. Kindly fulfill the requirements of the aforementioned License when adapting or creating a derivative of this work.