元类
元类
【一】什么是元类
- 产生已知类的类就叫元类
def func():
# ...
print(type(func)) # <class 'function'>
data_dict={'name':'hope'}
print(type(data_dict))
#<class 'dict'>
【二】产生类的两种方式
【1】使用关键字创建
class Person(object):
...
print(Person) #<class '__main__.Person'>
【2】使用type创建
print(type('Person', (object,), {}))
#<class '__main__.Person'>
【3】type的参数
- type(类的名字,类想要继承的父类,当前类内部的数据属性,实例化类的名称空间)
使用关键字
class Person(object):
name='人类'
def run(self):
...
print(Person)
print(Person.__bases__)
print(Person.__dict__)
#<class '__main__.Person'>
#(<class 'object'>,)
#{'__module__': '__main__', 'name': '人类', 'run': <function Person.run at 0x0000018A4279EF80>, '__dict__': <attribute '__dict__' of 'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__doc__': None}
使用type
PersonType=type('Person',(object,), {'name':'人类','run':run})
print(PersonType)
print(PersonType.__bases__)
print(PersonType.__dict__)
#<class '__main__.Person'>
#(<class 'object'>,)
#{'__module__': '__main__', 'name': '人类', 'run': <function Person.run at 0x0000018A4279EF80>, '__dict__': <attribute '__dict__' of 'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__doc__': None}
【3】总结type语法
- 类名=type(类名,(父类1,父类2...),{类里面的数据属性})
【三】为什么要使用元类
- 更高的定制我们的类的具体行为
- 就相当于我们已经知道了具体的制作过程,我们可以在中间加点料
【四】如何使用元类
【1】需求
- 定义一个类的时候,我这个类的名字只能大写字母开头,小写不行
# 【1】创建一个元类
# 【2】重写 type的 __init__ 方法
# 【3】类的名字、类的父类、类的名称空间
# 【4】对类的名字进行校验 调用父类 type 里面的 __init__ 方法 将需要的参数全都传进去
# 【5】创建一个自己的类 , metaclass=元类名字
【2】案例1:类的名字必须大写
class MyType(type):
def __init__(cls, class_name, class_bases, class_dict):
super().__init__(class_name, class_bases, class_dict)
print(f'这是 MyMeta 中的init方法被触发了')
def __call__(self, *args, **kwargs):
print('这是 MyMeta 中的 __call__ 方法被触发了')
print(f'这是 MyMeta 中的{args}')
print(f'这是 MyMeta 中的{kwargs}')
obj=super().__call__(*args, **kwargs)
return obj
class MyClass(object,metaclass=MyType):
def __init__(self,name):
print('这是 MyClass 中的 init 方法被触发了')
self.name=name
def __call__(self, *args, **kwargs):
print('这是 MyClass 中的 __call__ 方法被触发了')
print(f'这是 MyClass 中的{args}')
print(f'这是 MyClass 中的{kwargs}')
my_class=MyClass(name='hope')
print(my_class)
my_class()
#这是 MyMeta 中的init方法被触发了
#这是 MyMeta 中的 __call__ 方法被触发了
#这是 MyMeta 中的()
#这是 MyMeta 中的{'name': 'hope'}
#这是 MyClass 中的 init 方法被触发了
#<__main__.MyClass object at 0x000002E41C16C3D0>
#这是 MyClass 中的 __call__ 方法被触发了
#这是 MyClass 中的()
#这是 MyClass 中的{}
class_name = 'Myclass'
if not class_name.istitle():
raise Exception("类的名字必须大写!")
else:
class_name = type(class_name, (), {})
print(class_name)
案例2:参数只能按关键字传参
# 需求:定制初始化类的时候传参数必须是按照关键字传参,不能按位置传参
# 【1】写一个类 继承元类 type
# 【2】重写 type 的 __call__
# 【3】拦截到 __call__ 带的位置参数和关键字参数
# 【4】限制你的不定长未知参数为空即可
# 【5】继承给 想使用的类
class MyType(type):
def __init__(cls, class_name, class_bases, class_dict):
super().__init__(class_name, class_bases, class_dict)
print(f'这是 MyMeta 中的init方法被触发了')
def __call__(self, *args, **kwargs):
print('这是 MyMeta 中的 __call__ 方法被触发了')
print(f'这是 MyMeta 中的{args}')
print(f'这是 MyMeta 中的{kwargs}')
if args:
raise Exception(f'参数只能按照关键字传参')
print(f'这是 MyMeta 中的 {kwargs}')
obj=super().__call__(*args, **kwargs)
return obj
class MyClass(object,metaclass=MyType):
def __init__(self,name):
print('这是 MyClass 中的 init 方法被触发了')
self.name=name
def __call__(self, *args, **kwargs):
print('这是 MyClass 中的 __call__ 方法被触发了')
print(f'这是 MyClass 中的{args}')
print(f'这是 MyClass 中的{kwargs}')
my_class=MyClass(name='hope')
print(my_class)
my_class()
合集:
python高级
, python 面向对象
标签:
Python 面向对象
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异