反射/内置方法
反射/内置方法
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