Python : 反射


  Java是一門面向對象的語言。 每一個Class,可以有instance,可以有Class對象。Instance的作用是調用方法、獲取屬性的,而Class對象則是獲取類有哪些屬性、方法的。Class對象與instance結合,也可以完成對instance方法的調用等。Java中的絕大部分框架,都離不開發射。那么在Python中,是否也有類似機制呢?

 

1、根據instance獲取Class對象

  對於一個Class的instance,想要獲取所屬Class對象,可以這樣:instance.__class__。 該方式也只是用於 Class。對於不是Class的instance的情況下,如果獲取到它們的所屬類型呢?

 

2、使用type(obj)獲取某個對象的類型

  該函數用於獲取任意一個Python對象的類型。

參數

返回值

XxxClass instance

<class ‘XxxClass’>

XxxClass object

<type ‘type’>

XxxClass.instancemthod

<type ‘instancemethod’>

XxxClass.staticMethod

<type ‘function’>

XxxModule

<type ‘module’>

Len,min

<type ‘builtin_function_or_method’>

 

3isinstance(obj, class)

  可以用isinstance(obj, class)來判斷實例與class的關系。如果返回True,代表obj是 class或者其子類的實例。

  在Python中,一切都是對象,例如package,module,class,function,instance都是對象。在上面使用type可以獲取判定是哪種類型的,但是如果我們程序中只是想要判定一個對象是否是哪種類型的,使用type並不方便。而使用isinstance則可以快速判定了。

 

例如:

import types
isinstance(obj, types.ModuleType)  # 判定是否是module
isinstance(obj, (types.ClassType,types.TypeType)) #判定是類

 

4、利用反射來獲取屬性、調用方法

  利用反射來訪問instance的屬性,方法,前提是已知instance、要訪問的屬性或者方法的名稱(name)。在Python中,這一切就變得簡單了,通過內置函數getattr(obj,name) 就可以獲取到一個Python對象任意屬性方法。如果要獲取一個屬性,獲取的就是屬性值;如果要獲取方法,獲取到的是方法對象。要獲取的方法、屬性,如果沒有會從父類找的。

 

  就拿之前的一個例子來說明問題:

 

#!python
#-*- coding: utf-8 -*-

class Person(object):
    id=''
    name = ''
    age = 3
    
    # 等同於Java中的<init>,即構造器
    def __init__(self, id, name, age):
        print("init a Person instance")
        self.id = id
        self.name = name
        self.age = age

    def show(this):
        print(this)
    #    print(this.toString())

#    def toString(self):        
#        return "id:{}, name:{}, age:{}".format(self.id, self.name, self.age)
    
    # 等同於Java中的toString
    def __str__(self):
#        return self.toString()
        return "id:{}, name:{}, age:{}".format(self.id, self.name, self.age)
    

    # 等同於Java中的finalize方法,del 實例時調用
    def __del__(self):
        print("finally a Person instance")
        self.id = None
        self.name = None
        self.age = None
        self = None

    def __get__(self, name):
        print("invoke in __get__")
        print(self.__dict__)
        return 1111

    def __getattr__(self, name):
        print("invoke in __getattr__")
        return 1111
'''
    def __getattribute__(self, name):
        print("invoke in __getattribute__")
        print(object.__getattribute__(self, name))
        print("after invoke in __getattribute__")
        return object.__getattribute__(self, name)
'''

class Student(Person):
    def __init__(self, id, name, age,email):
        print("invoke in Student __init__")
        super(Student, self).__init__(id, name, age) # invoke Person#__init__
        self.email = email


    def __getitem__(self, name):
        return self.__dict__[name] + "_suffix"


    def show(self):
        print("show in ......")
        print("__dict__:{}".format(self.__dict__))
        print("__class__:{}".format(self.__class__))
        print("isinstance(self, __class__):{}".format(isinstance(self, self.__class__)))
        print("type:{}".format(type(self)))
        print("show out ......")
    
    @staticmethod
    def s_show(o):
        o.show();

下面是反射測試: 

#!python
#-*- coding: utf-8 -*-

'''
from model import Person
print(dir(Person))
p1 = Person('0001', 'fjn', 20)
print(p1)
p1.show()
print(p1.name)
print(p1.xx)
del p1
'''
import model
Student = model.Student
s = Student('0001', 'fjn', 20, 'fs1194361820@163.com')
s.show()
print(s["email"])

'''
print(type(model))
print(type(Student))
print(type(Student.show))
print(type(Student.s_show))
print(type(len))

print(dir(Student))

print(isinstance(type(Student),type))
print(isinstance(type(model),type))
'''

showMethod = getattr(s,"show") #get show method object from object s
if(showMethod!=None):
    #apply(showMethod)  # use apply invoke show method
    showMethod()        # invoke show method direct

print(getattr(s,"age"))

import types
print(isinstance(Student, (types.TypeType,types.ClassType)))
print(isinstance(s, types.InstanceType))
import inspect
print(inspect.isclass(Student))

 


5
Python的反射工具:inspect 

  Python提供了一個inspect模塊,它封裝了上面的所有功能。官方文檔參見:https://docs.python.org/2/library/inspect.html#。也可以通過pydoc來查看該模塊。

  這個工具提供了對象類型判定,成員獲取,源碼位置,運行時Stack,異常trace等功能,應該成為Python編程的強大助手。而這些功能大多數就是由上面的那些函數組合完成的。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM