isinstance(obj,cls)判断obj是否是类 cls 的对象

class Foo(object):
    pass
 
obj = Foo()  
print(isinstance(obj, Foo))  #检查obj是否是类Foo的对象
--->True

isinstance(x,list)判断x是否是列表list

x=[]
print(isinstance(x,list))
--->True 

 

issubclass(sub, super)检查sub类是否是 super 类的派生类

class Foo(object):
    pass
 
class Bar(Foo):
    pass
 
print(issubclass(Bar, Foo))  #检查Bar类是否是Foo的派生类
--->True

 

二 反射

1 反射的概念

反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。这一概念的提出很快引发了计算机科学领

域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。

 

2 python面向对象中的反射:通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射) 

四个可以实现自省的函数

下列方法适用于类和对象(一切皆对象,类本身也是一个对象)

 

2.1 hasattr() 判断属性

hasattr(object,name)判断object中有没有一个name字符串对应的方法或属性

class People:
    country='China'
    def __init__(self,name):
        self.name=name

p=People('egon')
print(p.__dict__)
--->{'name': 'egon'}

print(hasattr(p,'name'))        #等同于print('name' in p.__dict__),检查对象p是否有“name”属性
--->True

print(hasattr(p,'name1213'))        #等同于print('name1213' in p.__dict__),检查对象p是否有“name1213”属性
--->False

print(hasattr(p,'country'))         #p.country,相当于查找p下是否有country
--->True

print(People.__dict__)
--->{'__module__': '__main__', 'country': 'China', '__init__': <function People.__init__ at 0x0000000002203A60>, '__dict__': <attribute '__dict__' of 'People' objects>, '__weakref__': <attribute '__weakref__' of 'People' objects>, '__doc__': None}

print(hasattr(People,'country'))     #People.country,相当于查找People下是否有country
--->True

print(hasattr(People,'__init__'))     #People.__init__,相当于查找People下是否有__init__
--->True

 

2.2 getattr() 获取属性

getattr(object, name, default=None) 获得对象object的‘name’的内存地址,name对应的方法或属性,结果返回object.name的值

当object.name不存在时,不会报错,自动返回第三个参数

class People:
    country='China'
    def __init__(self,name):
        self.name=name
    def walk(self):
        print('%s is walking' %self.name)

p=People('egon')
res=getattr(p,'country')     #相当于res=p.country
print(res)
--->China

f=getattr(p,'walk')     #相当于f=p.walk
print(f)
---><bound method People.walk of <__main__.People object at 0x00000000027CDC50>>

f1=getattr(People,'walk')    #相当于f1=People.walk
print(f1)
---><function People.walk at 0x00000000027CF048>

f()    #对象的绑定方法运行
--->egon is walking

f1(p)    #类的函数运行
--->egon is walking

print(p.xxxxxxx)    #输入不存在的数据属性或方法,报错
--->AttributeError: 'People' object has no attribute 'xxxxxxx'

print(getattr(p,'xxxxxxxx')) 
--->AttributeError: 'People' object has no attribute 'xxxxxxx'

print(getattr(p,'xxxxxxxx','这个属性确实不存在')) #属性不存在时,getattr自动返回第三个参数 
--->这个属性确实不存在

一般hasattr与getattr配合使用

class People:
    country='China'
    def __init__(self,name):
        self.name=name
    #def walk(self):
        #print('%s is walking' %self.name)

p=People('egon')

if hasattr(p, 'walf'):                #避免查找p下的绑定方法walk报错
    func = getattr(p,'walk')
    func()

 

2.3 setattr() 设置属性或方法

setattr(object, name, value) 用于新增加或者修改对象object属性(等同与object.name = value)

class People:
    country='China'
    def __init__(self,name):
        self.name=name

p=People('egon')
print(p.__dict__)
--->{'name': 'egon'}

p.sex='male'        #新增属性
print(p.sex)
--->male

print(p.__dict__)
--->{'name': 'egon', 'sex': 'male'}

用setattr来实现

class People:
    country='China'
    def __init__(self,name):
        self.name=name

p=People('egon')
print(p.__dict__)
--->{'name': 'egon'}

setattr(p,'age',18)       #新增p的属性,p.age=18 
print(p.__dict__)
--->{'name': 'egon', 'age': 18}

print(p.age)
--->18
#用getattr来实现
print(getattr(p,'age'))
--->18

 

2.4 delattr() 删除属性或方法

delattr(x, y) #删除对象属性(等同于del x.y)

class People:
    country='China'
    def __init__(self,name):
        self.name=name
    def walk(self):
        print('%s is walking' %self.name)

p=People('egon')
print(p.__dict__)
--->{'name': 'egon'}

del p.name
print(p.__dict__)
--->{}

#用delattar
print(p.__dict__)
--->{'name': 'egon'}

delattr(p,'name')
print(p.__dict__)
--->{}

 

以上反射的四种方法应用

四个方法的使用演示
class BlackMedium:
    feature='Ugly'
    def __init__(self,name,addr):
        self.name=name
        self.addr=addr

    def sell_house(self):
        print('%s 黑中介卖房子啦,傻逼才买呢,但是谁能证明自己不傻逼' %self.name)
    def rent_house(self):
        print('%s 黑中介租房子啦,傻逼才租呢' %self.name)

b1=BlackMedium('万成置地','回龙观天露园')

#检测是否含有某属性
print(hasattr(b1,'name'))
print(hasattr(b1,'sell_house'))

#获取属性
n=getattr(b1,'name')
print(n)
func=getattr(b1,'rent_house')
func()

# getattr(b1,'aaaaaaaa') #报错
print(getattr(b1,'aaaaaaaa','不存在啊'))

#设置属性
setattr(b1,'sb',True)
setattr(b1,'show_name',lambda self:self.name+'sb')
print(b1.__dict__)
print(b1.show_name(b1))

#删除属性
delattr(b1,'addr')
delattr(b1,'show_name')
delattr(b1,'show_name111')#不存在,则报错

print(b1.__dict__)

 

类也是对象,使用反射

class Foo(object):
 
    staticField = "old boy"
 
    def __init__(self):
        self.name = 'wupeiqi'
 
    def func(self):
        return 'func'
 
    @staticmethod
    def bar():
        return 'bar'
 
print getattr(Foo, 'staticField')    #获取类的'staticField'属性
--->old boy

print getattr(Foo, 'func')    #获取类的'func'属性
---><function Foo.func at 0x0000018156FBB950>

print getattr(Foo, 'bar')    #获取类的'bar'属性
---><function Foo.bar at 0x00000192D2AFB9D8>

 

class Foo:
    x=1
    def __init__(self,name):
        self.name=name

    def walk(self):
        print('walking......')

print(Foo.__dict__)
--->{'__module__': '__main__', 'x': 1, '__init__': <function Foo.__init__ at 0x0000000001E7F048>, 'walk': <function Foo.walk at 0x0000000001E7F2F0>, '__dict__': <attribute '__dict__' of 'Foo' objects>, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__doc__': None}

print('x' in Foo.__dict__)
--->True

print(hasattr(Foo,'x'))    #等同于print('x' in Foo.__dict__)
--->True

print(Foo.__dict__['x'] )    
--->1

print(getattr(Foo,'x'))    #等同于print(Foo.x)
--->1

print(Foo.x)
--->1

 

 

反射当前模块成员

#反射当前模块的属性
import sys

x=1111
class Foo:
    pass
def s1():
    print('s1')

def s2():
    print('s2')

print(__name__)     
--->__main__

this_module = sys.modules[__name__]
print(this_module)      #this_module = sys.modules[__name__]以上是被调用的模块内容,输出的结果是被调用模块的文件路径
---> <module '__main__' from 'E:/python教学视频/Python fullstack s4 基础篇-day31/day31/test.py'>

print(hasattr(this_module, 's1'))   
--->True

print(getattr(this_module, 's2'))       #等同于print(this_module.s2) 
---><function s2 at 0x00000000027EF048>

print(this_module.s2)                
---><function s2 at 0x0000000001E73A60>

print(this_module.s1)               
---><function s1 at 0x0000000001D28048>

  

反射的应用

#普通情况下
def add():
    print('add')

def change():
    print('change')

def search():
    print('search')

def delete():
    print('delete')

func_dic={
'add':add,
    'change':change,
    'search':search,
    'delete':delete
}

while True:
    cmd=input('>>:').strip()
    if not cmd:continue
    if cmd in func_dic:                 #hasattr()
        func=func_dic.get(cmd)     #func=getattr()
        func()    

 

#使用反射
import sys
def add():
    print('add')

def change():
    print('change')

def search():
    print('search')

def delete():
    print('delete')

this_module=sys.modules[__name__]

while True:
    cmd=input('>>:').strip()
    if not cmd:continue
    if hasattr(this_module,cmd):
        func=getattr(this_module,cmd)
        func()

#以上减少了代码func_dic字典的定义,直接可以使用函数add,change,search,delete的功能,减少了代码量,更加简单清晰

 

导入其他模块,利用反射查找该模块是否存在某个方法

导入test这个模块,在test1.py中查找test是否存在某些方法

 1 #反射当前模块的属性
 2 import sys
 3 
 4 x=1111
 5 class Foo:
 6     pass
 7 def s1():
 8     print('s1')
 9 
10 def s2():
11     print('s2')
12 
13 print(__name__)     
14 --->__main__
15 
16 this_module = sys.modules[__name__]
17 print(this_module)      #this_module = sys.modules[__name__]以上是被调用的模块内容,输出的结果是被调用模块的文件路径
18 ---> <module '__main__' from 'E:/python教学视频/Python fullstack s4 基础篇-day31/day31/test.py'>
19 
20 print(hasattr(this_module, 's1'))   
21 --->True
22 
23 print(getattr(this_module, 's2'))       #等同于print(this_module.s2) 
24 ---><function s2 at 0x00000000027EF048>
25 
26 print(this_module.s2)                
27 ---><function s2 at 0x0000000001E73A60>
28 
29 print(this_module.s1)               
30 ---><function s1 at 0x0000000001D28048>
test.py

相关文章: