day04.11
面向对象的双下方法
__str__:
对象被执行打印(print、前端展示)操作的时候自动触发,该方法必须返回字符串类型的数据,很多时候用来更加精准的描述对象!!!
class Myclass(object): def __init__(self,name): self.name = name def __str__(self): print('到底什么时候触发') return '对象:%s'%self.name obj = Myclass('kkk') print(obj) # <__main__.Myclass object at 0x0000016B0DE4E240> 不使用__str__方法的时候 print(obj) # 返回一个__str__的返回值 对象:kkk print(Myclass) # 对类并不适用,只适用于对象
__del__:
对象被执行(被动、主动)删除操作之后自动执行!!!
class Myclass(object): def __init__(self,name): self.name = name def __del__(self):
'''对象被执行(被动、主动)删除操作之后自动执行''' print('del什么时候执行') obj = Myclass('kkk') del obj # del什么时候执行>>>hhh 先执行删除操作,直接调用了__del__方法 print('hhh') # hhh>>>del什么时候执行 删除操作后,自动执行__del__
__getattr__:
对象查找不存在名字的时候自动触发!!!类似于异常处理的情况,避免代码报错。
class Myclass(object): def __init__(self,name): self.name = name def __getattr__(self, item): '''对象查找不存在的名字的时候自动触发''' print('__getattr__方法',item) # item就是指对象想要查找的名字,它的类型是str return '查找不到%s名字'%item obj = Myclass('kkk') print(obj.name) # 不触发 print(obj.age) # 触发 __getattr__方法 age
__setattr__:
对象在执行添加属性操作(操作名称空间的时候)的时候自动触发!!!
class Myclass(object): def __init__(self,name): self.name = name def __setattr__(self, key, value): '''对象在执行添加属性操作的时候自动触发>>>相当于obj.变量名 = 变量值''' # print('__setattr__方法') # __setattr__方法 # print(key,value) # name kkk if key == 'gender': # 可以用来筛选和限制一些对象的功能 raise Exception('没有gender这个对象') if not key.islower(): raise Exception('只能使用小写') obj = Myclass('kkk') print(obj.__dict__) # {}
__call__:
对象被加括号调用的时候自动触发!!!并且该方法返回什么,对象加括号就会返回什么。
class Myclass(object): def __init__(self,name): self.name = name def __call__(self, *args, **kwargs): '''对象被添加括号调用的时候自动触发''' print('__call__方法',args,kwargs) return '__call__使得对象也有类似于类的功能' obj = Myclass('KKK') print(123,444) # __call__方法 (123, 444) {}
__enter__和__exit__:
__enter__:对象被执行with语法时开始自动触发,该方法返回什么as后面的变量名就会得到什么!!!
__exit__:对象被执行with语法结束之后自动触发!!!
class Myclass(object): def __init__(self,name): self.name = name def __enter__(self): '''对象被执行with上下文管理语法开始自动触发 ''' print('__enter__方法') def __exit__(self,exc_type,exc_val,exc_tb): '''对象被执行with上下文管理语法结束之后自动触''' print('__exit__方法') obj = Myclass('KKK') with obj as f: print(123) print(321) ''' __enter__方法 123 __exit__方法 321 '''
__getattribute__:
只要对象查找名字,无论名字是否存在都会执行该方法!!!如果类中有__getattribute__方法,那么就不会去执行__getattr__方法。
class Myclass(object): def __init__(self, name): self.name = name def __getattribute__(self,item): '''只要对象查找名字无论名字是否存在都会执行该方法''' print('__getattribute__方法',item) return 'xxxx' obj = Myclass('zzz') print(obj.name)
元类
元类简介:
引入:
# type功能查看的其实是当前对象所属的类名称 print(type(123)) # <class 'int'> print(type([12, 33, 44])) # <class 'list'> print(type({'name':'jason','pwd':123})) # <class 'dict'>
type就是所有类默认的元类!!!
# 一切皆对象!!! class MyClass(object): pass obj = MyClass() print(type(obj)) # 返回当前对象所属的类 <class '__main__.MyClass'> print(type(MyClass)) # 返回当前类所属的类 <class 'type'> # type就是所有类默认的元类!!! class Student: pass print(type(Student)) # <class 'type'>
产生类的两种表现形式
这两种表现形式的本质都是一样的。
方式1:class关键字
class C1(object): pass print(C1) # <class '__main__.C1'>
方式2:type元类
# 元类创建的语法结构>>>:type(类名,父类,类的名称空间) res = type('C1', (), {}) print(res) # <class '__main__.C1'>
元类的使用场景
元类能够控制类的创建,这就为我们提供了一种可以高度自定义控制类的一种方式!!!就可以在类的制定过程中添加自己想要的功能。
参考类产生对象的__init__方法>>>:在"继承"元类的基础上修改功能。
元类是不能通过继承的方式直接指定的,修改的过程不单单是继承方法,还需要使用关键字metaclass!!!
元类的使用方法
# 需要通过关键字参数的形式修改 class MyTypeClass(type): pass # class C1(MyTypeClass): # pass # print(C1) # print(type(C1)) # <class 'type'> class C1(metaclass=MyTypeClass): pass print(type(C1)) # <class '__main__.MyTypeClass'>
eg:
class MyTypeClass(type): def __init__(cls, cls_name, cls_bases, cls_dict): # print(cls, cls_name, cls_bases, cls_dict) if not cls_name.istitle(): raise Exception("类名的首字母必须大写") super().__init__(cls_name, cls_bases, cls_dict) class C1(metaclass=MyTypeClass): school = '清华大学' # 无法定义会报错 # class a(metaclass=MyTypeClass): # school = '清华大学'
元类的进阶
类加括号
类加括号会执行元类的里面的__call__,该方法返回什么,其实类加括号就会得到什么!!!
# 类加括号会执行元类的里面的__call__,该方法返回什么,其实类加括号就会得到什么 class MyTypeClass(type): def __call__(self, *args, **kwargs): print('__call__ run') # __call__ run return 123 # super().__call__(*args, **kwargs) class MyClass(metaclass=MyTypeClass): def __init__(self, name): print('__init__ run') # __init__ run self.name = name obj = MyClass('jason') print(obj) # 123
元类定制对象的产生过程
类在实例化产生对象的时候,对象的独有数据必须采用关键字参数>>>:obj = MyClass(name='jason')
# 定制对象的产生过程 class MyTypeClass(type): def __call__(self, *args, **kwargs): # print('__call__ run') # print(args,kwargs) if args: raise Exception('必须全部采用关键字参数') super().__call__(*args, **kwargs) class MyClass(metaclass=MyTypeClass): def __init__(self, name): # print('__init__ run') self.name = name # obj = MyClass('jason') # 报错,没有采用关键字参数 obj2 = MyClass(name='jason')
总结:
如果你想高度定制类的产生过程,那么编写元类里面的__init__方法!!!
如果你想高度定制对象的产生过程,那么编写元类里面的__call__方法!!!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?