一直很奇怪自省和反射的区别,搞不清楚它们的区别,我想,python中的自省就是java中的反射吧。
反射的作用就是列出对象的所有属性和方法,反射就是告诉我们,这个对象到底是什么,提供了什么功能 。
举个例子:
>>> import json >>> dir(json) ['JSONDecoder', 'JSONEncoder', '__all__', '__author__', '__builtins__', '__doc__', '__file__', '__name__', '__package__', '__path__', '__version__', '_default_decoder', '_default_encoder', 'decoder', 'dump', 'dumps', 'encoder', 'load', 'loads', 'scanner'] >>>如上所看,dir 是一个内置的 反射函数 ,可以列出对象的属性和方法。
再看另外一个内置的方法 :getattr
>>> getattr(json,'encoder') <module 'json.encoder' from '/usr/lib/python2.7/json/encoder.pyc'> >>> getattr(json,'load') <function load at 0x7f66af736140> >>>可以取出指定属性
再看另外一个方法 :callable
>>> callable(getattr(json,'load')) True >>> callable(getattr(json,'encoder')) False >>>检查属性是否是可以调用的函数 。
了解基础之后,就需要考虑,它存在的价值在哪里了?
考虑一个应用的场景:IDE的自动补全。
在IDE中可以这样做:
>>> methodList = [attr for attr in dir(json) if callable(getattr(json,attr))] >>> methodList ['JSONDecoder', 'JSONEncoder', 'dump', 'dumps', 'load', 'loads'] >>>
>>> getattr(json,'load').__doc__ 'Deserialize ``fp`` (a ``.read()``-supporting file-like object containing\n a JSON document) to a Python object.\n\n If the contents of ``fp`` is encoded with an ASCII based encoding other\n than utf-8 (e.g. latin-1), then an appropriate ``encoding`` name must\n be specified. Encodings that are not ASCII based (such as UCS-2) are\n not allowed, and should be wrapped with\n ``codecs.getreader(fp)(encoding)``, or simply decoded to a ``unicode``\n object and passed to ``loads()``\n\n ``object_hook`` is an optional function that will be called with the\n result of any object literal decode (a ``dict``). The return value of\n ``object_hook`` will be used instead of the ``dict``. This feature\n can be used to implement custom decoders (e.g. JSON-RPC class hinting).\n\n ``object_pairs_hook`` is an optional function that will be called with the\n result of any object literal decoded with an ordered list of pairs. The\n return value of ``object_pairs_hook`` will be used instead of the ``dict``.\n This feature can be used to implement custom decoders that rely on the\n order that the key and value pairs are decoded (for example,\n collections.OrderedDict will remember the order of insertion). If\n ``object_hook`` is also defined, the ``object_pairs_hook`` takes priority.\n\n To use a custom ``JSONDecoder`` subclass, specify it with the ``cls``\n kwarg; otherwise ``JSONDecoder`` is used.\n\n ' >>>大概就明白了 反射的功能了。
#-*- coding:utf8 -*- class Obj : """ An object that use reflection """ def __init__(self,name): """ 构造函数 """ self.name = name def echo_methods(self): """ 输出类中所有的方法,以及doc 文档 """ print "\n Method List: " for attrName in dir(self): attr = getattr(self,attrName) if callable(attr): print attrName,"():",attr.__doc__ def echo_attributes(self): print "\n Attributes" for name in dit(self): attr = getattr(self,attr) if not callable(attr): print name,":",attr obj = Obj("testObject") obj.echo_methods()
ubuntu@yee:/tmp$ python ref.py Method List: __init__ (): 构造函数 echo_attributes (): None echo_methods (): 输出类中所有的方法,以及doc 文档可以看到,通过反射,我们可以知道类中所有的方法以及方法的属性和注释文档信息。