面向对象微讲解(四)
面向对象微讲解(四)
面向对象双下方法
1.__str__:对象被执行打印(print、前端展示)操作的时候自动触发,该方法必须返回字符串类型的数据,很多时候用来更
加精准的描述对象。
class Student:
def __init__(self,name):
self.name = name
def __str__(self):
print('什么时候打印我')
return '这是一个对象%s'%self.name
obj = Student('oscar')
print(obj) # 当我们执行打印语句的时候,__str__会自动执行
2.__del__:对象被执行(被动、主动)删除操作之后自己执行。(相当于我们只讲过的垃圾回收机制)
class Student:
def __init__(self,name):
self.name = name
def __del__(self):
print('什么时候打印我')
obj = Student('oscar')
# del obj # 这是主动执行,可以指定执行的地方
print(obj.name) # 先输出的打印语句,然后自动执行的__del__方法
3.__getattr__:对象查找不存在的名字的时候自动触发。
class Student:
def __init__(self,name):
self.name = name
def __getattr__(self, item):
print('什么时候打印我')
return '%s不存在'%item
obj = Student('oscar')
print(obj.name) # 打印oscar,不执行__getattr__方法
print(obj.age) # 执行__getattr__方法
4.__getattribute__:只要对象查找名字,无论名字是否存在都会执行该方法,如果类中有__getattribute__方法就不会
执行__getattr__方法。
class Student:
def __init__(self,name):
self.name = name
def __getattribute__(self, item):
print('无论什么时候打印我')
return item
obj = Student('oscar')
print(obj.name) # 都会执行打印,不会报错
print(obj.age) # 都会执行打印,不会报错
5.__setattr__:在对象执行添加属性操作的时候触发。
class Student:
def __setattr__(self, key, value):
print('你添加了键值对k:%s v:%s'%(key,value))
obj = Student()
obj.name = 'oscar' # 执行这一句的时候自动执行__setattr__方法
6.__call__:对象被加括号调用的时候自动执行。
class Student:
def __init__(self,name):
self.name = name
def __call__(self, *args, **kwargs):
print('什么时候打印我')
return 123
obj = Student('oscar')
print(obj()) # 对象是不能直接加括号调用的,加了__call__方法就可以,返回值后面跟什么就返回什么
7.__enter__:对象被执行with语法的时候自动执行,该方法返回什么as后面的变量名就会得到什么。
__exit__:对象被执行with语法结束的时候自动执行。
class Student:
def __init__(self,name):
self.name = name
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
pass
obj = Student('oscar')
with obj as f:
res = f.name
print(res) # oscar
元类
1.元类简介
1.元类即原始的类,产生类的类。
2.学习元类的目的:元类能够控制类的创建,也就意味着我们可以高度定制类的行为。
# print(type(123)) # <class 'int'>
# print(type([123,11,'oscar'])) #<class 'list'>
# print(type('oscar')) # <class 'str'>
'''我们type关键字查看数据类型的时候,会返回数据的类型,
我们会发现前面有一个class,实质数据类型也是一个类,那我们
能不能type一个类,来看看产生类的类是什么
'''
class Student:
pass
print(type(Student)) # <class 'type'>
class Teacher(Student):
pass
print(type(Teacher)) # <class 'type'>
'''
我们会发现都是type,所以type就是所有类默认的元类
'''
2.产生类的两种变现形式
1.class关键字
class 类名:
类体代码
2.type元类
# type(类名,父类,类的名称空间)
res = type('Student',(),{})
print(res) # <class '__main__.Student'>
3.元类的基本使用
1.元类是不能够通过继承的方式直接指定的,需要通过关键字'metaclass'参数的形式修改。
# 修改元类的方法,创建类的时候首字母必须大写,否则就报错
class Student(type):
def __init__(cls,cls_name,cls_bases,cls_dict):
if not cls_name.istitle():
raise Exception('创建类的时候类名首字母必须大写!!')
super().__init__(cls_name,cls_bases,cls_dict)
class Teacher(metaclass=Student): # 通过关键字'metaclass'参数的形式修改。
name = 'oscar'
# class teacher(metaclass=Student):
# name = 'oscar'
4.元类进阶操作
1.我们之前讲__call__方法的时候,对象加括号会自动执行产生该对象的类里面的__call__,并且该方法返回什么对象加
括号就会得到什么,那我们就可以推导类加括号会执行元类的里面的__call__,该方法返回什么类加括号就会得到什么。
2.类里面的__init__和元类的__call__执行的先后顺序。
class Student(type):
def __call__(self, *args, **kwargs):
print('我是__call__')
super().__call__(*args, **kwargs)
class Teacher(metaclass=Student):
def __init__(self,name):
print('我是__init__')
self.name = name
obj = Teacher('oscar')
'''
我是__call__
我是__init__
先执性元类的__call__方法,然后在执行类的__init__方法
'''
3.定制对象的产生过程
class Student(type):
def __call__(self, *args, **kwargs):
if args:
raise Exception('必须全部采用关键字参数')
super().__call__(*args, **kwargs)
class Teacher(metaclass=Student):
def __init__(self,name):
self.name = name
obj = Teacher(name = 'oscar')
'''
如果你想高度定制类的产生过程:就编写元类里面的__init__方法。
如果你想高度定制对象的产生过程:就编写元类里面的__call__方法。
'''
5.双下new方法
__new__用于产生空对象(类)
__init__用于实例化对象(类)
# 并不是所有的地方都可以直接调用__new__,该方法过于底层。
1.如果是在元类的__new__里面可以直接调用
class Student(type):
def __call__(cls, *args, **kwargs):
obj = type.__new__(cls,*args,**kwargs)
return obj
2.如果在元类的__call__里面需要间接调用
class Student(type):
def __call__(self, *args, **kwargs):
obj = type.__new__(self) # 创建一个空对象
self.__init__(obj,*args,**kwargs) # 让对象去初始化
return obj
这里是IT小白陆禄绯,欢迎各位大佬的指点!!!
