01 补充内置函数
isinstance(obj,cls)检查是否obj是否是类 cls 的对象
1 class Foo(object):
2 pass
3
4 obj = Foo()
5
6 isinstance(obj, Foo)
在python3中统一类与类型的概念
d={'x':1}#d=dict('x':1)
print(type(d) is dict)
print(isinstance(d,dict))
issubclass(sub, super)检查sub类是否是 super 类的派生类
1 class Foo(object):
2 pass
3
4 class Bar(Foo):
5 pass
6
7 issubclass(Bar, Foo)
02 反射
1.什么是反射
通过字符串来操作类或者对象的属性
2.如何用
hasattr:检查对象是否拥有某个属性
getattr:获取文件属性
setattr:将对象中的属性设置为新的属性
delattr:删除对象中的属性
class People:
country='China'
def __init__(self,name):
self.name=name
def eat(seflf):
print('%s is eating'%self.name)
peo1=People('egon')
print(hasattr(peo1,'eat')) #peo1.eat#结果:True
print(getattr(peo1,'eat'))#peo1.eat
print(getattr(peo1,'xxxx',None))#如果xxxx存在则返回该值,如果不存在得返回None(默认设置为None可更改)
setattr(peo1,'age',18)#peo1.age=18,注意age为字符串类型
print(peo1,age) #结果:18
print(peo1.__dict)#结果:{'name': 'egon'}
delattr(peo1.'name')#del peo1.name
print(peo1.__dict__) #结果:{}
反射练习:
class People:
def __init__(self,name,age):
self.name=name
self.age=age
def get(self):
print('get')
def put(self):
print('put')
def run(self):
while True:
choice=input('>>>: ').strip()
if hasattr(self,choice):
method=getattr(self,choice)
method ()
else:
print('输入的指令不存在')
peo1=People('egon',18)
peo1.run()
交互界面:
>>>: #输入 put,get会打印相应提示,否则就打印输入的指令不存在
03 自定义内置方法来定制类的功能
1.__str__方法(改变对象字符串显示):
class People
def __init__(self,name,age)
self.name=name
self.age=age
在对象被打印时,自动触发,应该在该方法内采集与对象self有关的信息,然后拼成字符串返回
def __str__(self):
#print('======>')
return '<name:%s age:%s>' %(self.name,self.age)
obj=People('egon',18)
obj1=People('alex',78)
print(obj) #obj.__str__() 结果:<name:egon age:18>
print(obj1) #obj1.__str__() 结果:<name:alex age:18>
1、__del__析构方法
__del__会在对象被删除之前自动触发
class People:
def __init__(self,name,age)
self.name=name
self.age=age
self.f=open('a.txt','r',encoding='utf-8')
def __del__(self):
self.f.close() #回收操作系统中的资源, 做回收系统资源相关的事情
peo1=People('egon',18)
print('主')#只要进行打印就会触发__del__,
04 元类
1、什么是元类
在python中一切皆对象,那么我们用class关键字定义的类本身也是一个对象
负责产生该对象的类称之为元类,即元类可以简称为类的类
class Foo: #Foo=元类()
pass
2、为何要用元类
元类是负责产生类的,所以我们学习元类或者自定义元类的目的
是为了控制类的产生过程,还可以控制对象的产生过程
一、储备知识 :内置函数exec的用法
cmd="""
x=1
def func(self):
pass
"""
class_dic={}
exec(cmd,{},class_dic) #exec(object,globals,locals)
print(class_dic)
结果:{'x': 1, 'func': <function func at 0x008BA618>}
二、创建类的方法有两种
大前提:如果说类也是对象的话,那么用class关键字的去创建类的过程也是一个实例化的过程
该实例化的目的是为了得到一个类,调用的是元类
2.1:用的默认的元类type
2.1.1创建类的3个要素:类名、基类、类的名称空间
该实例化的目的是为了得到一个类,调用的是元类
2.1:用的默认的元类type
class People: #People=type(...)
country='China'
def __init__(self,name,age):
self.name=name
self.age=age
def eat(self):
print('%s is eating'%self.name)
print(type(People)) #结果:<class 'type'>
class_name='People'
class_bases=(object,)
class_dic={}
class_body="""
country='China'
def __init__(self,name,age):
self.name=name
self.age=age
def eat(self):
print('%s is eating'%self.name)
exec(class_body,{},class_dic)
准备好创建类的三发素
print('class_name')
print('class_bases')
print('class_dic')
People=type(类名、基类、类的名称空间)
People1=type(class_name,class_bases,class_dic)
print(Peo) #结果:<class '__main__.People'>
People=type(class_name,class_bases,class_dic)
obj.eat() 结果:egon is eating
2.2 方式二:用的自定义的元类
class Mymeta(type): #只有继承了type类的才能称之为一个元类,否则就是一个普通的自定义类
def __init__(self,class_name,class_bases,class_dic):
print(self)
print(class_name)
print(class_bases)
print(class_dic)
super(Mymeta,self).__init__(class_name,class_bases,class_dic) #重用父类的功能
#分析用class自定义的运行原理(而非元类的运行原理):
1、拿到一个字符串格式的类名class_name='People'
2、拿到一个类的基类们class_bases=(object,)
3、执行类体代码,拿到一个类的名称空间class_dic={...}
4、调用People=type(class_name,class_bases,class_dic)
class People(object,metaclass=Mymeta): People=Mymeta(类名,基类们,类的名称空间)
country='China'
def __init__(self,name,age):
self.name=name
self.age=age
def eat(self):
print('%s is eating'%self.name)
应用:自定义元类控制类的产生过程,类的产生过程其实就是元类的调用过程
class Mymeta(type):#只有继承了type类才能称之为一个元类,否则就是一个普通的自定义类
def __init__(self,class_name,class_bases,class_dic):
if class_dic.get('__doc__') is None or len(class_dic.get('__doc__').strip()) == 0:
raise TypeError('类中必须有文档注释,并且文档注释不能为空')
if not class_name.istitle():
raise TypeError('类名首字母必须大写')
super(Mymeta,self).__init__(class_name,class_bases,class_dic) #重用父类的功能
class People(object,metaclass=Mymeta): #People=Mymeta('People',(object,),{....})
"""这是People类"""
country='China'
def __init__(self,name,age):
self.name=name
self.age=age
def eat(self):
print('%s is eating' %self.name)
3.储备知识:call
class Foo:
def __call__(self,*args,**kwargs):
print(self)
print(args)
print(kwargs)
obj=Foo()
要想让obj这个对象变成一个可调用的对象,需要在该对象的类中定义一个方法__call__方法
该方法会在调用对象时自动触发
obj(1,2,3,x=1,y=2)
4、自定义元类来控制类的调用的过程,即类的实例化过程
class Mymeta(type):
def __call__(self,*args,**kwargs):
print(self) #self是People
print(args)
print(kwargs)
return123
1、先造出一个People的空对象
obj=self.__new__(self)
2、为该空对象初始化独有的属性
print(args,kwargs)
self.__init__(obj,*args,**kwargs)
3、返回一个初始化的对象
return obj
class People(object,metaclass=Mymeta):
country='China'
def __init__(self,name,age):
self.name=name
self.age=age
def eat(self):
print('%s is eating'%self.name)
def __new__(cls,*args,**kwargs):
print(cls)
#cls.__new__(cls) # 错误
obj=super(People,cls).__new__(cls)
return obj
分析:调用People的目的
1、先造出一个People的空对象
2、为该对空对象初始化独有的属性
obj1=People('egon1',age=18)
obj2=People('egon2',age=18)
print(obj1)
print(obj2)
# obj=People('egon',age=18)
# print(obj.__dict__)
# print(obj.name)
# obj.eat()