第二十七天反射和面向对像中的内置函数
1.isinstance判断类和对象之间的关系如果存在类对象关系返回True否则返回False
class Person: def func(self): pass a=Person() b=1 print(isinstance(a,Person)) #左边对象右边类 print(isinstance(b,Person)) 结果为 True False
2。issubclass判断是否是子类和父类之间的关系:
class Person: def func(self): pass class Son(Person): pass b=Person() print(issubclass(Son,Person)) #左边子类右边父类(超类、基类) 结果为 True
3.反射就是用字符串形式的名字去操作变量进行操作:
3.1我们前面也学过用字符串进行变量的操作:
name=123 print(eval('name')) 结果为 123
使用这个存在安全隐患:因为这种操作是得到别人写好的代码直接执行,你也不知道别人的代码是否有代码病毒。
3.2使用反射可以解决这一个问题,使用反射式使用一段写好的代码,然后执行里面的属性和方法。
4.反射类里面的属性
class Person: def func(self): print('哈哈哈') a=Person()#实例化 a.name='alex'#给对象中添加一个元素 Person.name='123' ret=getattr(a,'name') print(ret) print(a.__dict__)#显示对象中所有的属性信息并以字典的形式返回 print(Person.__dict__) 结果为 alex {'name': 'alex'} {'__module__': '__main__', 'func': <function Person.func at 0x0000024D5EFF5730>, '__dict__': <attribute '__dict__' of 'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__doc__': None, 'name': '123'}
5.反射使用类里面的方法:
class Person: def func(self): print('哈哈哈') a=Person()#实例化 a.name='alex'#给对象中添加一个元素 ret=getattr(a,'func') #这一步得到方法的地址(和函数差不多) ret() 结果为 哈哈哈
6那么反射有什么用:简单小例子用户通过输入想要查看某个对象的属性:
class Person: def func(self): print('哈哈哈') a=Person()#实例化 a.name='alex'#给对象中添加一个元素 a.age=16 name=input('输入你想查看的属性;') ret=getattr(a,name) print(ret) 结果为 输入你想查看的属性;name alex
还有一种方法也是可以通过字符串得到类中的属性:
class Person: def func(self): print('哈哈哈') a=Person()#实例化 a.name='alex'#给对象中添加一个元素 a.age=16 name=input('输入你想查看的属性;') ret=a.__dict__[name] print(ret) 结果为 输入你想查看的属性;name alex
7但是这种方法没有办法得到类中的方法,还是只能使用反射:
class Person: __key=123 @staticmethod def func(): print('哈哈哈') @classmethod def func1(cls): return cls.__key a=Person()#实例化 a.name='alex'#给对象中添加一个元素 a.age=16 name=input('输入你像调用的方法;') ret=getattr(Person,name) ret() 结果为 输入你像调用的方法;func 哈哈哈
还有一中使用反射得到方法的使用方法:
class Person: __key=123 @staticmethod def func(): print('哈哈哈') @classmethod def func1(cls): return cls.__key a=Person()#实例化 a.name='alex'#给对象中添加一个元素 a.age=16 name=input('输入你像调用的方法;') print(getattr(Person,name)()) 结果为 输入你像调用的方法;func1 123
8.模块里的反射方法:
import mile #调用mile模块 print(getattr(mile,'day')) #使用模块中day的属性 结果为 123
9.调用模块中的方法:
import mile #调用mile模块 print(getattr(mile,'day')) #使用模块中day的属性 getattr(mile,'func')() #调用模块中func方法 结果为 123 哇哈哈
10内置模块也可以使用反射方法:
import time print((getattr(time,'time'))()) 结果为 1582943294.4412374
11.为什么random就不能使用getattr
import random print(getattr(random,'randint(1,10))')) 结果为 Traceback (most recent call last): File "D:/python练习程序/第二十七天/practise.py", line 48, in <module> print(getattr(random,'randint(1,10))')) AttributeError: module 'random' has no attribute 'randint(1,10))
import random print(getattr(random,'randint')(1,10)) 结果为 6
12.那么python中是否可以反射自己的模块:
year=2020 import sys name=input('请输入>>>') print(getattr(sys.modules[__name__],name)) 结果为 请输入>>>year 2020
13要反射函数怎么办:
import time print(time.strftime('%Y-%m-%d %H:%M:%S')) print(getattr(time,'strftime')('%Y-%m-%d %H:%M:%S')) 结果为 2020-02-29 10:49:45 2020-02-29 10:49:45
14.有时候我在在使用getattr时如果没有会报错:
import time getattr(time,'fjdfj') 结果为 Traceback (most recent call last): File "D:/python练习程序/第二十七天/practise.py", line 55, in <module> getattr(time,'fjdfj') AttributeError: module 'time' has no attribute 'fjdfj'
怎么解决报错的问题:
import time if hasattr(time,'fjdfj'): #如果为真执行下面如果为假不执行 getattr(time,'fjdfj')#两个括号里要写的一致 else: print('上面的指令有误') 结果为 上面的指令有误
15对类的变量进行设置修改:
class A: def func(self): print('修改成功') a=A() a.name='alex' print(a.name) print(a.func()) setattr(a,'name','subin') #对属性进行修改 print(a.name) setattr(a,'func','func1') #无法对方法进行修改 print(a.func1()) 结果为 File "D:/python练习程序/第二十七天/practise.py", line 69, in <module> alex print(a.func1()) AttributeError: 'A' object has no attribute 'func1' 修改成功 None subin
class A: def func(self): print('修改成功') a=A() a.name='alex' print(a.name) print(a.func()) delattr(a,'name') #对属性进行修改 print(a.name) 结果为 Traceback (most recent call last): File "D:/python练习程序/第二十七天/practise.py", line 78, in <module> print(a.name) AttributeError: 'A' object has no attribute 'name' alex 修改成功 None
16.内置函数和内置方法之间有着千丝万缕的关系:
17.__str__方法:
class A: pass a=A() print(str(a)) #object里面有一个__str__方法,一但被调用,就返回这个方法对象的 #内存地址 结果为 <__main__.A object at 0x000001BCFA6FB080>
18.
class A: def __str__(self): return '执行了str功能' a=A() print(a) #打印一个对象的时候就会调用a.__str__先从自己这里找如果没有再去找父类 结果为 执行了str功能
19.
l=[1,5,6]#进行实例化 print(l)
显示这个原因是找到列表中的__str__方法如果找不到就是用备胎:__repr__
20在python中只要使用了str、%s、print都是要调用__str__方法:
class A: def __str__(self): return '执行了str功能' a=A() #进行实例化 print(a) #打印一个对象的时候就会调用a.__str__先从自己这里找如果没有再去找父类 print('%s'%a) 结果为 执行了str功能 执行了str功能
21。__repr__方法:(使用repr和%都调用,如果调用str时没有也会调用这一个)(repr是str的备胎,但是str不是repr的备胎)
class A: def __str__(self): return '执行了str功能' def __repr__(self): return '执行里repr功能' a=A() #进行实例化 print(repr(a)) print('%r'%a) 结果为 执行里repr功能 执行里repr功能
class A: def __repr__(self): return '执行里repr功能' a=A() #进行实例化 print(a) #如果没有str,可以调用__repr__ print('%r'%a) 结果为 执行里repr功能 执行里repr功能
22.总结;print(obj)、%s、str(obj)实际上就是调用了obj.__str__方法,如果str有方法,就返回的是一个字符串入股没有__str__方法,就会找本类中的__repr__方法,在没有才会去找
父类中的__str__方法
23:内置方法很多但并不是所有的内置方法都有内置函数:
class A: def __repr__(self): return '执行里repr功能' a=A() #进行实例化 print(len(a)) 结果为 File "D:/python练习程序/第二十七天/practise.py", line 93, in <module> print(len(a)) TypeError: object of type 'A' has no len
24.
class A: def __init__(self,name): self.name=name self.student=[] def __len__(self): return len(self.student) a=A('jfkdj') #进行实例化 a.student.append('天逛') a.student.append('西斯') print(len(a)) 结果为 2
25.__del__方法:
析构方法:当对象在内存中被释放时,自动触发执行。此方法无需定义,因为python是一门高级语言,程序元在使用时无需关心内存的释放和分配,这种工作基本上交给ptyhon解释
来执行,所以析构的调用是由解释器进行垃圾的回收时自动执行触发的
class A: def __del__(self): print('执行我了:') a=A() print(a) del a print(a) 结果为 <__main__.A object at 0x0000024E10C6B080> Traceback (most recent call last): File "D:/python练习程序/第二十七天/practise.py", line 96, in <module> print(a) NameError: name 'a' is not defined 执行我了:
26当一个指令执行结束以后就会执行此语句:
class A: def __del__(self): print('执行我了:') a=A() import time time.sleep(2)#当这个程序执行结束之后python内部会把这个内存进行回收即执行del 结果为 执行我了:
class A: def __del__(self): self.close()#执行此语句的时候就会把文件进行关闭了 a=A() a.f=open() del a.f #这样虽然会把文件删了但是内存还在占用使用del限制性def的del在执行内部del 结果为
27.内置call方法的使用:
class A: def __call__(self): print('执行内部的call方法了') a=A()()#在对象后面加括号就是执行call方法: b=A() b() 结果为 执行内部的call方法了 执行内部的call方法了