反射/内置方法

反射/内置方法

issubclass和ininstance

# 判断第一个类是不是第二个类的子类,返回true或者false
class Foo:    
	pass
class Bar(Foo):    
	pass
class Tt(Bar):    
	pass

print(Bar.__bases__) # (<class '__main__.Foo'>,)
print(issubclass(Bar,Foo)) # True
print(issubclass(Tt,object)) # True
# 判断第一个参数是不是第二个参数的对象,返回true或者false
class Foo:
    pass
class Tt():
    pass
f=Foo()

print(isinstance(f,Foo)) # True
print(isinstance(f,Tt)) # False

反射

反射就是通过字符串来操作类或者对象的属性

  • 反射本质就是在使用内置函数,其中反射有以下四个内置函数:

    1. hasattr:判断一个方法是否存在与这个类中
    2. getattr:根据字符串去获取obj对象里的对应的方法的内存地址,加"()"括号即可执行
    3. setattr:通过setattr将外部的一个函数绑定到实例中
    4. delattr:删除一个实例或者类中的方法
    
class Foo:
    def run(self):
        print('run')
    def speak(self):
        print('speak')
p=Foo()

# 输入字符串,执行字符串对应的方法
choice = input('请输入执行命令:')
if hasattr(p,choice):
    run = getattr(p,choice)
    run()
else:
	print('该命令不存在!') 
    
# 通过用户输入key和value往对象中赋值
key=input('请输入key:')
value=input('输入value:')
setattr(p,key,value)
print(p.age)  # 默认用户输入age关键字
'''
请输入key:age
输入value:12
12
'''

#动态的往对象中放方法
def test():
    print(1)
    
print(p.__dict__)
setattr(p,'test',test)
print(p.__dict__)

p.test()
'''
{}
{'test': <function test at 0x02D907C8>}
1
'''

# 动态删除p中属性为变量a的属性
p.name='lqz'
p.age=18
p.sex='male'
a=input('请输入要删除的属性:')
print(p.__dict__)
delattr(p,a)
print(p.__dict__)
'''
请输入要删除的属性:age
{'name': 'lqz', 'age': 18, 'sex': 'male'}
{'name': 'lqz', 'sex': 'male'}
'''

# 直接p.a是不对的
del p.a

内置方法

#__str__:如果不重写__str__   print打印会打印出内存地址
class Foo:
    def __init__(self,name):
        self.name=name
print(Foo('nick')) # <__main__.Foo object at 0x0078DFD0>

# __str__如果重写了,就会打印__str__方法返回的内容
class Foo:
    def __init__(self,name):
        self.name=name
    def __str__(self):
        return '['+self.name+']'

print(Foo('nick')) # [nick]

#__repr__ 跟str类似,在交互式命令下直接写变量名,会执行__repr__
#__setattr__,__delattr__,__getattr__(重要)
# 点拦截方法
#如果去对象中取属性,一旦取不到,会进入到__getattr__
#如果去对象中赋值属性,一旦取不到,会进入到__setattr__
#如果删除对象中的属性,会进入__delattr__

class Foo:
    def __init__(self,name):
        self.name=name
    def __getattr__(self, item):
        return '你傻逼啊,没有这个字段'
    
f=Foo('nick')
print(f.age) # 你傻逼啊,没有这个字段


class Foo:
    def __init__(self,name):
        self.name=name
    def __setattr__(self, key, value):
        print('6666')
f=Foo('nick')
f.sex='male' # 666


class Foo:
    def __init__(self,name):
        self.name=name
    def __delattr__(self, item):
        print('你想删除啥?')
f=Foo('nick')
del f.name
print(f.__dict__) # name属性并没有被删除
'''
你想删除啥?
{'name': 'nick'}
'''
# 写一个类继承字典,让它可以 . 取值,也可以中括号取值
class Mydict(dict):
    def __init__(self,**kwargs):
        super().__init__(**kwargs) # 继承了原dict的方法

    def __getattr__(self, item):
        return self[item]

    def __setattr__(self, key, value):
        self[key]=value
        
di=Mydict(name='lqz',age=18)
print(di['name'])
print(di.age)
di.sex='male'
di['sex']='male'
di.hobby = ['baskerball']
print(di.sex)
print(di['hobby'])
'''
lqz
18
male
['baskerball']
'''
# __item__系列  对象通过[] 中括号取值,赋值,删除值的时候,会调用
__setitem__:中括号赋值时触发
__getitem__:中括号取值时触发
__delitem__:中括号删除时触发
__delattr__:.删除时触发
    
class Foo:
    def __init__(self, name):
        self.name = name

    def __getitem__(self, item):
        print('getitem执行', self.__dict__[item])

    def __setitem__(self, key, value):
        print('setitem执行')
        self.__dict__[key] = value

    def __delitem__(self, key):
        print('del obj[key]时,delitem执行')
        self.__dict__.pop(key)

    def __delattr__(self, item):
        print('del obj.key时,delattr执行')
        self.__dict__.pop(item)

f1 = Foo('sb')

f1['age'] = 18       # setitem执行
f1['name'] = 'tank'  # setitem执行

f1['age']   # getitem执行 

del f1.age     # del obj.key时,delattr执行
del f1['age']   # del obj[key]时,delitem执行

print(f1.__dict__)   # {'name': 'tank'}
#__call__   对象加括号会调用它
class Foo:
    def __call__(self):
        print('xxxx')
        
f=Foo()
f()   # xxxx
posted @ 2019-09-02 19:56  SweetJack  阅读(117)  评论(0编辑  收藏  举报