一、反射
1.1、什么是反射
动态语言:未指定数据类型,执行时设定类型
静态语言:指定数据类型,定义时设定类型
python是一种动态语言,在程序运行过程中,可以“动态”’的(执行前)获取类型信息
1.2、为什么需要反射
提前知道对象的属性,判断己方是否拥有,避免报错
1.3、怎么使用反射
四种判断字符串属性的方法:
hasattr():判断字符串是否哟属性
getattr()得到字符串的属性
setattr()更改字符串的属性
delattr()删除字符串的属性
class People: def __init__(self,name,age): self.name=name self.age=age def say(self): print('<%s:%s>' %(self.name,self.age)) obj=People('辣白菜同学',18) # 实现反射机制的步骤 四个内置函数的使用:通过字符串来操作属性值 1、hasattr() #判断字符串有无属性,相当于obj.name print(hasattr(obj,'name')) print(hasattr(obj,'x')) 2、getattr() #得到字符串的属性 print(getattr(obj,'name')) 3、setattr() #更改字符串的属性 setattr(obj,'name','EGON') # obj.name='EGON' print(obj.name) 4、delattr() #删除字符串的属性 delattr(obj,'name') # del obj.name print(obj.__dict__) res1=getattr(obj,'say') # obj.say res2=getattr(People,'say') # People.say print(res1) print(res2)
二、内置方法
2.1、什么是内置方法
定义在类的内部,以__开头,并且以__结尾
在某种特定条件下会自动触发执行
2.2、为什么要内置方法
为了定制化:类或者对象
2.3、怎么使用内置方法
2.3.1、__str__:在打印对象的时候自动触发,将返回值(必须是字符串)当做本次打印的输出结果
class People: def __init__(self, name, age): self.name = name self.age = age def __str__(self): # print('运行了...') return "<%s:%s>" %(self.name,self.age) obj = People('辣白菜同学', 18) # print(obj.__str__()) print(obj) # <'辣白菜同学':18> # obj1=int(10) # print(obj1)
2.3.2、__del__:在清理对象的时候(对象运行结束后)自动触发,会先执行该方法
class People: def __init__(self, name, age): self.name = name self.age = age self.x = open('a.txt',mode='w') # self.x = 占据的是操作系统资源 def __del__(self): # print('run...') # 发起系统调用,告诉操作系统回收相关的系统资源 self.x.close() obj = People('辣白菜同学', 18) # del obj # obj.__del__() print('============>')
三、元类
3.1、什么是元类
源于一句话:python中一切皆对象
元类就是实例化产生的类
即 元类====》实例化====》类====》实例化====》对象
默认class产生的类都是基于type元类产生的类,对于元类来讲,类就是对象
3.2、class关键字创建类的步骤
3.2.1、类的三大特征
1.类名
2.类的基类
3.执行类体代码拿到类的空间名称
People=type(class_name,class_bases,class_dic)
3.2.2、调用元类
3.3、如何来自定义元类来控制类的产生
调用元类发生的三件事
1.先建一个空对象,调用类内的__new__方法
2.调用类内的__init__方法,完成初始化对象的操作
3.返回初始化号的对象
注:只要是调用类,就会调用类内的__init__以及__new__
class Mymeta(type): # 只有继承了type类的类才是元类 # 空对象,"People",(),{...} def __init__(self,x,y,z): print('run22222222222....') print(self) # print(x) # print(y) # print(z) # print(y) # if not x.istitle(): # raise NameError('类名的首字母必须大写啊!!!') # 当前所在的类,调用类时所传入的参数 def __new__(cls, *args, **kwargs): # 造Mymeta的对象 print('run1111111111.....') # print(cls,args,kwargs) # return super().__new__(cls,*args, **kwargs) return type.__new__(cls,*args, **kwargs)
3.4、__call__:如果想要让一个对象可以加上括号()调用,需要在对象的类内加一个方法__call__
该例题中:对象为:====》类内的__call
类()为====》自定义元素内的____call__
自定义元素为====》内置元素__call__
class Foo: def __init__(self,x,y): self.x=x self.y=y # obj,1,2,3,a=4,b=5,c=6 def __call__(self,*args,**kwargs): print('===>',args,kwargs) return 123 obj=Foo(111,222) # print(obj) # obj.__str__ res=obj(1,2,3,a=4,b=5,c=6) # res=obj.__call__() print(res)
3.5、从自定义元素控制类的调用====》类的对象的产生
class Mymeta(type): # 只有继承了type类的类才是元类 def __call__(self, *args, **kwargs): # 1、Mymeta.__call__函数内会先调用People内的__new__ people_obj=self.__new__(self) # 2、Mymeta.__call__函数内会调用People内的__init__ self.__init__(people_obj,*args, **kwargs) # print('people对象的属性:',people_obj.__dict__) people_obj.__dict__['xxxxx']=11111 # 3、Mymeta.__call__函数内会返回一个初始化好的对象 return people_obj # 类的产生 # People=Mymeta()=》type.__call__=>干了3件事 # 1、type.__call__函数内会先调用Mymeta内的__new__ # 2、type.__call__函数内会调用Mymeta内的__init__ # 3、type.__call__函数内会返回一个初始化好的对象 class People(metaclass=Mymeta): def __init__(self,name,age): self.name=name self.age=age def say(self): print('%s:%s' %(self.name,self.name)) def __new__(cls, *args, **kwargs): # 产生真正的对象 return object.__new__(cls) # 类的调用 # obj=People('egon',18) =》Mymeta.__call__=》干了3件事 # 1、Mymeta.__call__函数内会先调用People内的__new__ # 2、Mymeta.__call__函数内会调用People内的__init__ # 3、Mymeta.__call__函数内会返回一个初始化好的对象 obj1=People('egon',18) obj2=People('egon',18) # print(obj) print(obj1.__dict__) print(obj2.__dict__)
四、属性的查找
从对象出发的属性查找原则:对象====》类====》父类====》objck 父类不是元类
从类出发的属性查找原则:类====》父类====》objck====》元类====》type
class Mymeta(type): n=444 def __call__(self, *args, **kwargs): #self=<class '__main__.StanfordTeacher'> obj=self.__new__(self) # StanfordTeacher.__new__ # obj=object.__new__(self) print(self.__new__ is object.__new__) #True self.__init__(obj,*args,**kwargs) return obj class Bar(object): # n=333 # def __new__(cls, *args, **kwargs): # print('Bar.__new__') pass class Foo(Bar): # n=222 # def __new__(cls, *args, **kwargs): # print('Foo.__new__') pass class StanfordTeacher(Foo,metaclass=Mymeta): # n=111 def __init__(self,name,age): self.name=name self.age=age obj=StanfordTeacher('lili',18) print(obj.__dict__) # print(obj.n) #从对象出发 # print(StanfordTeacher.n) #从类出发