A tutorial on dynamically retrieving properties and methods of objects in Python

Source: Internet
Author: User
Let's start with an example to look at the objects and related concepts that may be used in this article.

#coding: UTF-8 Import sys # module, sys points to this Module object import inspect def foo (): Pass # function, Foo points to this function object  class Cat (Object): # class, Cat finger To this class object Def __init__ (self, name= ' Kitty '): self.name = name def sayhi (self): # instance method, Sayhi point to this method object, use class or instance. Sayhi Access print self. Name, ' says hi! ' # accesses the field named name, using the instance. Name access to  cat = Cat () # cat is an instance object of the Cat class  print Cat.sayhi # When accessing an instance method using the class name, the method is unbound (Unbo und) Print Cat.sayhi # When accessing an instance method using an instance, the method is bound (bound)

Sometimes we encounter the need to execute a method of an object, or to assign a value to a field of an object, and the method name or field name cannot be determined when coding the code, and it needs to be entered in the form of a parameter pass string. As a concrete example: when we need to implement a generic dbm framework, we may need to assign values to the fields of the data object, but we cannot predict what fields the data objects used in this framework have, in other words, we need some mechanism to access unknown properties when we write the framework.

This mechanism is called reflection (which in turn allows the object to tell us what he is), or introspection (let the object tell us what he is, ok I admit I made up my mind in parentheses--#), used to implement information that gets unknown objects at run time. Reflection is a frightening noun, sounding inscrutable, in general programming language reflection is slightly more complex than other concepts, generally speaking as a high-level theme, but in Python it is very simple to use and almost feel different from other code, The functions and methods obtained by using reflection can be called directly as usual, and the instance can be constructed directly after the class is obtained, but the obtained field cannot be directly assigned because it is actually another reference to the same place, and the assignment can only change the current reference.
1. Accessing the properties of an object

Several built-in methods are listed below that can be used to check or access the properties of an object. These methods can be used for any object, not just the cat instance object in the example, and everything in Python is an object.

Cat = Cat (' Kitty ')  print Cat.name # Access Instance Properties Cat.sayhi () # Call instance method  print Dir (cat) # Gets the property name of the instance, returning if hasattr as a list (Cat, ' Name '): # Check if instance has this attribute setattr (cat, ' name ', ' Tiger ') # same as:a.name = ' Tiger ' Print getattr (cat, ' name ') # same AS:PRI NT A.name  getattr (cat, ' Sayhi ') () # same as:cat.sayHi ()

Dir ([obj]):
Calling this method returns a list containing most of the property names of obj (some special attributes are not included). The default value of obj is the current module object.
Hasattr (obj, attr):
This method is used to check if obj has a property named attr value, and returns a Boolean value.
GetAttr (obj, attr):
Calling this method returns the value of the property named attr value in obj, such as Obj.bar if attr is ' bar '.
SetAttr (obj, attr, val):
Calling this method assigns a value of Val to the property of obj named attr. For example, if attr is ' bar ', it is equivalent to Obj.bar = val.

2. Accessing the metadata of an object

When you use Dir () on an object that you construct, you may find that many of the attributes in the list are not defined by you. These properties generally hold the object's metadata, such as the class's __name__ property, which holds the class name. Most of these properties can be modified, but the meaning of changing them is not very large; modifying some of these properties, such as Function.func_code, can also lead to problems that are difficult to spot, so change the name or whatever, and other properties don't change without knowing the consequences.

Next, you'll list some special properties for a particular object. In addition, Python's documentation mentions that some of the properties may not always be available, and the following will be marked with a red asterisk *, which you can turn on before using the interpreter.
2.0. Preparation: Determining the type of object

All Python built-in types are defined in the types module, and the specific type of the object can be determined with the built-in method Isinstance ().

Isinstance (object, ClassInfo):
Check that object is not a type listed in ClassInfo and returns a Boolean value. ClassInfo can be a specific type, or it can be a tuple or list of more than one type.

The types module only defines the type, and the inspect module encapsulates a number of methods for checking the type, which is easier than using the types module directly, so there is no more introduction to types, and you can view the document description of the types module directly if necessary. The inspect module is described in section 3rd of this article.
2.1. Modules (module)

__DOC__: Document String. If the module does not have a document, this value is none.
*__NAME__: The module name is always defined, even if you use import. As it takes an alias, or assigns another variable name.
*__DICT__: Contains a dictionary of the property names-attributes available in the module; The object that can be accessed by using the module name. Property name.
__FILE__: Contains the file path for the module. It is important to note that the built-in module does not have this property, and accessing it throws an exception!

Import Fnmatch as M print M.__doc__.splitlines () [0] # Filename matching with shell patterns. Print m.__name__ # fnmatch print m.__file__ #/USR/LIB/PYTHON2.6/FNMATCH.PYC print m.__dict__.items () [0] # (' Fnmatchcase ' , 
 
  
   
  )
 
  

2.2. Classes (Class)

__DOC__: Document String. If the class does not have a document, this value is none.
*__NAME__: is always the name of the class at the time of definition.
*__DICT__: Contains a dictionary of the property names-Properties available in the class; The object that can be accessed by using the class name. Property name.
__MODULE__: The module name that contains the definition of the class; It is important to note that the module name is in string form instead of the module object.
*__bases__: The tuple of the immediate parent class object, but does not contain other classes in the upper layer of the inheritance tree, such as the parent class of the parent class.

Print cat.__doc__ # None print cat.__name__ # Cat print cat.__module__ # __main__ Print cat.__bases__ # (
 
  
   
  ,) Print cat.__dict__ # {' __module__ ': ' __main__ ', ...}
 
  

2.3. Example (instance)

An instance is an object that is later instantiated by a class.

*__DICT__: Contains a dictionary of available property names-Properties.
*__CLASS__: The class object for the instance. For class cat,cat.__class__ = = Cat is True.

Print cat.__dict__ print cat.__class__ print cat.__class__ = = Cat # True

2.4. Built-in functions and methods (built-in functions and methods)

By definition, the built-in (built-in) module refers to a module written in C, which can be viewed through the Sys module's builtin_module_names field to see which modules are built-in. The functions and methods in these modules can use fewer properties, but generally do not need to view their information in code.

__DOC__: A document for a function or method.
__NAME__: The name of the function or method definition.
__self__: The method is available only, and if it is bound (bound), it is none for the class that called the method (if it is a class method) or an instance (if it is an instance method).
*__MODULE__: The name of the module in which the function or method resides.

2.5. Functions (function)

This is specifically a non-built function. Note that defining a method with Def in a class is a different concept, although methods and functions have similar behavior.

__DOC__: A document for a function, or a property name to Func_doc.
__NAME__: The function name when the functions are defined, or Func_name with the property name.
*__MODULE__: The module name that contains the function definition, as well as the module name and not the module object.
*__DICT__: The available properties of a function, or it can be func_dict with the property name.
Do not forget that functions are also objects, you can use functions. property name access to the property (if the property does not exist when it is assigned), or by using the built-in function has/get/setattr () access. However, it is not very important to save the property in a function.
Func_defaults: This property holds the parameter default value tuple for the function, because the default value is always the last parameter, so the form that does not use the dictionary can also correspond to the parameter.
Func_code: This property points to a code object that corresponds to the function, and the code object defines some other special properties, which are described separately below.
Func_globals: This property points to the current global namespace instead of the global namespace when the function is defined, and is not very useful and is read-only.
*func_closure: This property is valid only if the function is a closure, pointing to a tuple of the variable cell that holds the referenced external function, or none if the function is not an intrinsic function. This property is also read-only.

The following code demonstrates the Func_closure:

#coding: UTF-8 def foo (): n = 1 def bar (): Print n # refers to a non-global external variable n, constructs a closure n = 2 return bar  closure = foo () print closure . Func_closure # using Dir () to learn that the Cell object has a Cell_contents property to get the value print Closure.func_closure[0].cell_contents # 2

As can be seen from this example, encountering unknown objects using Dir () is a good idea:)
2.6. Methods (method)

The method is not a function, but it can be understood to add a layer of shell outside the function, and after getting the actual function in the method, you can use the properties of section 2.5.

__DOC__: Same as function.
__NAME__: Same as function.
*__MODULE__: Same as function.
Im_func: Use this property to get a reference to the actual function object in the method. In addition, if the version is more than 2.6, you can also use the property name __func__.
Im_self: If it is a bound (bound), it points to the class that called the method (if it is a class method) or an instance (if it is an instance method), otherwise none. If the version is more than 2.6, you can also use the property name __self__.
Im_class: The class that actually calls the method, or the instance that actually calls the method. Note the class that is not the definition of the method, if there is an inheritance relationship.

im = Cat.sayhi print im.im_func print im.im_self # cat print Im.im_class # cat

The general example method is discussed here, and there are two special methods, the class method (Classmethod) and the static method (Staticmethod), respectively. A class method is still a method, but because it needs to be called with a class name, he is always bound, whereas a static method can be thought of as a function in the namespace of a class (a function called by the class name), which can only use the properties of the function, not the properties of the method.
2.7. Generator (Generator)

The generator is an object returned by calling a generator function (generator functions), and is used more iteratively for collection objects.

__ITER__: is just an iterative marker.
Gi_code: The code object that corresponds to the generator.
Gi_frame: The frame object that the generator corresponds to.
Gi_running: Whether the generator function is executing. The generator function is in the frozen state after yield, before the next line of code that executes yield, at which point the value of this property is 0.
Next|close|send|throw: This is a few callable methods that do not contain metadata information, and how to use related documents that can view the generator.

Def Gen (): For N in Xrange (5): yield n g = gen () print G # 
 
  
   
   Print G.gi_code # 
  
    print g.gi_frame #  print g.gi_running # 0 print g.next() # 0 print g.next() # 1 for n in g: print n, # 2 3 4
 
  

接下来讨论的是几个不常用到的内置对象类型。这些类型在正常的编码过程中应该很少接触,除非你正在自己实现一个解释器或开发环境之类。所以这里只列出一部分属性,如果需要一份完整的属性表或想进一步了解,可以查看文末列出的参考文档。
2.8. 代码块(code)

代码块可以由类源代码、函数源代码或是一个简单的语句代码编译得到。这里我们只考虑它指代一个函数时的情况;2.5节中我们曾提到可以使用函数的func_code属性获取到它。code的属性全部是只读的。

co_argcount: 普通参数的总数,不包括*参数和**参数。
co_names: 所有的参数名(包括*参数和**参数)和局部变量名的元组。
co_varnames: 所有的局部变量名的元组。
co_filename: 源代码所在的文件名。
co_flags: 这是一个数值,每一个二进制位都包含了特定信息。较关注的是0b100(0×4)和0b1000(0×8),如果co_flags & 0b100 != 0,说明使用了*args参数;如果co_flags & 0b1000 != 0,说明使用了**kwargs参数。另外,如果co_flags & 0b100000(0×20) != 0,则说明这是一个生成器函数(generator function)。

 co = cat.sayHi.func_code print co.co_argcount # 1 print co.co_names # ('name',) print co.co_varnames # ('self',) print co.co_flags & 0b100 # 0

2.9. 栈帧(frame)

栈帧表示程序运行时函数调用栈中的某一帧。函数没有属性可以获取它,因为它在函数调用时才会产生,而生成器则是由函数调用返回的,所以有属性指向栈帧。想要获得某个函数相关的栈帧,则必须在调用这个函数且这个函数尚未返回时获取。你可以使用sys模块的_getframe()函数、或inspect模块的currentframe()函数获取当前栈帧。这里列出来的属性全部是只读的。

f_back: 调用栈的前一帧。
f_code: 栈帧对应的code对象。
f_locals: 用在当前栈帧时与内建函数locals()相同,但你可以先获取其他帧然后使用这个属性获取那个帧的locals()。
f_globals: 用在当前栈帧时与内建函数globals()相同,但你可以先获取其他帧……。

 def add(x, y=1): f = inspect.currentframe() print f.f_locals # same as locals() print f.f_back #  return x+y add(2)

2.10. 追踪(traceback)

追踪是在出现异常时用于回溯的对象,与栈帧相反。由于异常时才会构建,而异常未捕获时会一直向外层栈帧抛出,所以需要使用try才能见到这个对象。你可以使用sys模块的exc_info()函数获得它,这个函数返回一个元组,元素分别是异常类型、异常对象、追踪。traceback的属性全部是只读的。

tb_next: 追踪的下一个追踪对象。
tb_frame: 当前追踪对应的栈帧。
tb_lineno: 当前追踪的行号。

 def div(x, y): try: return x/y except: tb = sys.exc_info()[2] # return (exc_type, exc_value, traceback) print tb print tb.tb_lineno # "return x/y" 的行号 div(1, 0)

3. 使用inspect模块

inspect模块提供了一系列函数用于帮助使用自省。下面仅列出较常用的一些函数,想获得全部的函数资料可以查看inspect模块的文档。
3.1. 检查对象类型

is{module|class|function|method|builtin}(obj):
检查对象是否为模块、类、函数、方法、内建函数或方法。
isroutine(obj):
用于检查对象是否为函数、方法、内建函数或方法等等可调用类型。用这个方法会比多个is*()更方便,不过它的实现仍然是用了多个is*()。

 im = cat.sayHi if inspect.isroutine(im): im()


对于实现了__call__的类实例,这个方法会返回False。如果目的是只要可以直接调用就需要是True的话,不妨使用isinstance(obj, collections.Callable)这种形式。我也不知道为什么Callable会在collections模块中,抱歉!我猜大概是因为collections模块中包含了很多其他的ABC(Abstract Base Class)的缘故吧:)

3.2. 获取对象信息

GetMembers (object[, predicate]):
This method is an extended version of Dir () that will have Dir () The corresponding property of the found name is returned with a shape such as [(name, Value), ...]. In addition, predicate is a reference to a method that, if specified, should accept value as a parameter and return a Boolean value, if False, the corresponding property will not be returned. Use is* as the second parameter to filter out properties of the specified type.
GetModule (object):
also regret that the __module__ property in section 2nd only returns a string? This method is sure to satisfy you, which returns the module object where the definition of object is located.
Get{file|sourcefile} (object):
Gets the file name of the module in which the definition of object is located | The source code file name (none if none is returned). TypeError exceptions are thrown when used on built-in objects (built-in modules, classes, functions, methods).
Get{source|sourcelines} (object):
Gets the source code for the definition of object, returned as a string | string list. The IOError exception is thrown when the code is unreachable. Can only be used with Module/class/function/method/code/frame/traceack objects.
Getargspec (func):
is used only for methods, gets the parameters of a method declaration, returns a tuple, respectively (a list of common parameter names, * parameter name, * * Parameter name, default value tuple). If there is no value, it will be an empty list and 3 none. In the case of more than 2.6, a named tuple (Named Tuple) is returned, that is, the element in the tuple can be accessed in addition to the index by using the property name.

 def add(x, y=1, *z): return x + y + sum(z) print inspect.getargspec(add) #ArgSpec(args=['x', 'y'], varargs='z', keywords=None, defaults=(1,))

getargvalues(frame):
仅用于栈帧,获取栈帧中保存的该次函数调用的参数值,返回元组,分别是(普通参数名的列表, *参数名, **参数名, 帧的locals())。如果是2.6以上版本,将返回一个命名元组(Named Tuple),即除了索引外还可以使用属性名访问元组中的元素。

 def add(x, y=1, *z): print inspect.getargvalues(inspect.currentframe()) return x + y + sum(z) add(2) #ArgInfo(args=['x', 'y'], varargs='z', keywords=None, locals={'y': 1, 'x': 2, 'z': ()})

getcallargs(func[, *args][, **kwds]):
返回使用args和kwds调用该方法时各参数对应的值的字典。这个方法仅在2.7版本中才有。
getmro(cls):
返回一个类型元组,查找类属性时按照这个元组中的顺序。如果是新式类,与cls.__mro__结果一样。但旧式类没有__mro__这个属性,直接使用这个属性会报异常,所以这个方法还是有它的价值的。

 print inspect.getmro(Cat) #(
  
   
    
   , 
   
    
     
    ) print Cat.__mro__ #(
    
     
      
     , 
     
      
       
      )
     
      
    
     
   
    
  
   
  • Related Article

    Contact Us

    The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

    If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.