双下方法,元类,new方法
1. 面向对象的双下方法
1. __str__方法
class MyClass(object): def __init__(self, name): self.name = name print(self.name) def __str__(self): """ 对象被执行打印(print、前端展示)操作的时候自动触发 该方法必须返回字符串类型的数据 很多时候用来更加精准的描述对象 """ print('我到底什么时候触发') return '对象:%s' % self.name obj = MyClass('dragon') print(obj)
2. __del__方法
class MyClass(object): def __init__(self, name): self.name = name print(self.name) def __del__(self): """对象被执行(被动、主动)删除操作之后自动执行""" print("del啥时候执行") pass obj = MyClass('dragon') del obj
3. __getattr__方法
class MyClass(object): def __init__(self, name): self.name = name print(self.name) def __getattr__(self, item): """对象查找不存在名字的时候自动触发""" print('__getattr__方法', item) return '不好意思 没有%s这个名字' % item obj = MyClass('dragon') print(obj.age)
4. __setattr
class MyClass(object): def __init__(self, name): self.name = name print(self.name) def __setattr__(self, key, value): """对象在执行添加属性操作的时候自动触发>>>obj.变量名=变量值""" print('__setattr__方法') print(key, value) if key == 'age': raise Exception('你没有资格拥有age') if not key.islower(): raise Exception('名字只能小写') super().__setattr__(key, value) obj = MyClass('dragon') obj.age = 18
5.__call__方法
class MyClass(object): def __init__(self, name): self.name = name print(self.name) def __call__(self, *args, **kwargs): """对象被加括号调用的时候自动触发""" print('__call__方法', args, kwargs) return '嘿嘿嘿' obj = MyClass('dragon') obj(123, age=123)
6.__enter__与__exit__方法
class MyClass(object): def __init__(self, name): self.name = name print(self.name) def __enter__(self): """对象被执行with上下文管理语法自动触发""" print('__enter__方法') def __exit__(self, exc_type, exc_val, exc_tb): """对象被执行with上下文管理语法结束之后自动触发""" print('__exit__方法') obj = MyClass('dragon') with obj as f: print(222)
8.__getattribute__
class MyClass(object): def __init__(self, name): self.name = name print(self.name) def __getattribute__(self, item): """ 只要对象查找名字无论名字是否存在都会执行该方法 如果类中有__getattribute__方法 那么就不会去执行__getattr__方法 """ print('__getattribute__方法', item) return item obj = MyClass('dragon') print(obj.name) print(obj.age)
2. 笔试题讲解
补全下列代码 使其运行不报错 """ class Context: pass with Context() as ctx: ctx.do_something() """ 1. 使用到with方法,那么类中必须有__enter__此方法 2. 使用到__enter__方法就需要配套使用__exit__方法 class Context: def __enter__(self): return self def __exit__(self, exc_type, exc_val, exc_tb): pass with Context() as ctx: ctx.do_something() 运行:报错 错误信息: Traceback (most recent call last): File "D:/pycharm project/pythonProject/1.py", line 11, in <module> ctx.do_something() AttributeError: 'Context' object has no attribute 'do_something' 查看错误信息发现,对象中没有do_something方法,那么我们就需要增加do_something方法 最后结果为 class Context(): def __enter__(self): return self def __exit__(self, exc_type, exc_val, exc_tb): pass def do_something(self): pass with Context() as ctx: ctx.do_something()
3.
# 元类 # 元类其实就是产生类的类 print(type(123)) print(type([12, 33, 44])) print(type({'name': 'jason', 'pwd': 123})) # type查看的其实是当前对象所属的类名称 class MyClass(object): pass obj = MyClass() print(type(obj)) print(type(MyClass)) class Student: pass print(type(Student)) class Teacher(MyClass): pass print(type(Teacher)) '''type就是所有类默认的元类!!!'''
# 1.class关键字 class C1(object): pass print(C1) # 2.type元类 # type(类名, 父类, 类的名称空间) res = type('C2', (), {}) print(res) """ 学习元类的目的 元类能够控制类的创建 也就意味着我们可以高度定制类的行为 类的产生过程目前还比较懵 元类里面的__init__方法 对象的产生过程呢 类里面的__init__方法 """
5. 元类的基本使用
"""元类是不能通过继承的方式直接指定的""" # 需要通过关键字参数的形式修改 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("类名的首字母必须大写 你个SD") super().__init__(cls_name, cls_bases, cls_dict) class School1(metaclass=MyTypeClass): school = '清华大学' class School2(metaclass=MyTypeClass): school = '清华大学'
# 1.回想__call__方法 # 对象加括号会自动执行产生该对象的类里面的__call__,并且该方法返回什么对象加括号就会得到什么 # 推导:类加括号会执行元类的里面的__call__该方法返回什么其实类加括号就会得到什么 """类里面的__init__方法和元类里面的__call__方法执行的先后顺序""" # 定制对象的产生过程 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 """强制规定:类在实例化产生对象的时候 对象的独有数据必须采用关键字参数""" obj1 = MyClass('dragon') obj2 = MyClass(name='dragon') """ 如果你想高度定制类的产生过程 那么编写元类里面的__init__方法 如果你想高度定制对象的产生过程 那么编写元类里面的__call__方法 """
__new__用于产生空对象(类) 骨架 __init__用于实例化对象(类) 血肉 """ 注意:并不是所有的地方都可以直接调用__new__ 该方法过于底层 如果是在元类的__new__里面 可以直接调用 class Meta(type): def __new__(cls, *args, **kwargs): obj = type.__new__(cls,*args,**kwargs) return obj 如果是在元类的__call__里面 需要间接调用 class Mate(type): def __call__(self, *args, **kwargs): obj = object.__new__(self) # 创建一个空对象 self.__init__(obj,*args,**kwargs) # 让对象去初始化 return obj """
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· .NET Core 中如何实现缓存的预热?
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统