每次看到Python元类相关的讨论,脑袋就嗡嗡的。这玩意儿看着高大上,用的时候又糊里糊涂。其实元类就是个创建类的模板,说白了就是类的类。听着绕口?别急,一点点来捋这事儿。
类也是对象?没毛病!
Python里啥都是对象,类也不例外:
class Dog:
def bark(self):
print("汪汪汪!")
# 类也能当变量用
animal = Dog
pet = animal() # 和 Dog() 一个意思
pet.bark() # 输出:汪汪汪!
温馨提示:类对象和类的实例是两码事,弄混了就要踩坑。
type不光能查类型,还能造类
平时都拿type查类型,其实它还有个绝活:
# 普通的类定义
class Cat:
def meow(self):
print("喵喵喵~")
# type创建的类,一样能用
Dog = type('Dog', (), {'bark': lambda self: print("汪汪汪!")})
kitty = Cat()
doggy = Dog()
kitty.meow() # 输出:喵喵喵~
doggy.bark() # 输出:汪汪汪!
看明白了不?type接受三个参数:类名、父类元组(为空就是没有父类)、属性字典。
元类就是个类工厂
元类说白了就是个类生产车间,能批量产出各种类:
class AnimalMeta(type):
def __new__(cls, name, bases, attrs):
# 给所有动物类加个叫声
attrs['make_sound'] = lambda self: print(f"我是{name}, 我会叫!")
return super().__new__(cls, name, bases, attrs)
# 用元类造类
class Dog(metaclass=AnimalMeta):
pass
class Cat(metaclass=AnimalMeta):
pass
dog = Dog()
cat = Cat()
dog.make_sound() # 输出:我是Dog, 我会叫!
cat.make_sound() # 输出:我是Cat, 我会叫!
温馨提示:__new__方法比__init__还要早,它负责创建类对象,而__init__只是初始化。
元类能干啥用?
光说不练假把式,来点实在的:
class ValidatorMeta(type):
def __new__(cls, name, bases, attrs):
# 检查所有方法名是否符合规范
for key, value in attrs.items():
if callable(value) and not key.startswith('_'):
if not key.islower():
raise NameError(f'方法名{key}必须全小写!')
return super().__new__(cls, name, bases, attrs)
class MyClass(metaclass=ValidatorMeta):
def good_method(self): # 这个方法名没问题
pass
def BadMethod(self): # 这个方法名会报错
pass
瞧见没?元类能在类创建时就把不规范的代码揪出来,省得上线了再改。
继承也能玩出花
元类还能跟继承组合在一起耍:
class Base(metaclass=ValidatorMeta):
pass
class Child(Base): # 继承了Base,也会被ValidatorMeta检查
def GoodMethod(self): # 照样会报错
pass
温馨提示:Python3中,元类是可以继承的,不过继承链有点复杂,用的时候多查查文档。
元类就像个严格的保姆,替你看着类的一举一动。不过也别滥用,普通的开发基本用不着,除非你想写个框架或者搞点黑魔法。写代码图省事,但该严格的地方还得严格,不然等出了问题再找bug那才叫闹心呢。
领取专属 10元无门槛券
私享最新 技术干货