元类是什么?
在 Python 中,一切皆为对象。每个对象都是一个类的实例,而这个类本身也是一个对象。元类就是用来创建这些类(对象)的“类”。简单来说,元类是用来控制类创建行为的一种机制。
使用示例
- 首先,我们来定义一个简单的类:
class MyClass:
pass
- 然后我们可以使用 type() 函数来动态地创建一个类:
MyNewClass = type('MyNewClass', (), {
})
上面这段代码中,第一个参数表示新建类的名称,第二个参数表示新建类的父类,第三个参数是一个空字典,用于存储类的属性和方法。这里创建了一个空白的类 MyNewClass,与我们通常定义类的方式产生的结果相同。
- 接下来我们来尝试用一个元类来创建一个新类:
class MyMetaClass(type):
def __new__(cls, name, bases, attrs):
print(f"Creating class {name} with bases {bases}...")
return super().__new__(cls, name, bases, attrs)
MyNewClass = MyMetaClass('MyNewClass', (), {
})
上述代码中,我们定义了一个名为 MyMetaClass 的元类,它是 type 的子类,然后我们重载了该元类的 new() 方法。这个方法会在新类被创建时被调用。我们可以看到,new() 方法的第一个参数是 cls(表示当前的元类),第二个参数是新建类的名称,第三个参数是新建类的父类,第四个参数是一个字典,用于存储类的属性和方法。
当 MyMetaClass() 函数被调用时,它会去触发 MyMetaClass 的 new() 方法,然后返回一个新的类对象。运行上述代码,输出如下所示:
Creating class MyNewClass with bases ()...
这表明,在使用元类来创建新类时,我们可以轻松地控制和自定义类的创建过程,并对其进行一些必要的验证、修改等操作。
综合示例
最后,我们来看一个综合示例,它还包括了一些其他的概念,例如属性描述符和装饰器等:
class UpperAttrMetaclass(type):
def __new__(cls, name, bases, attrs):
upper_attrs = {
}
for attr_name, attr_value in attrs.items():
if not callable(attr_value) and not attr_name.startswith("__"):
upper_attrs[attr_name.upper()] = attr_value
else:
upper_attrs[attr_name] = attr_value
return super().__new__(cls, name, bases, upper_attrs)
class RevealAccess:
def __init__(self, varName):
self.varName = varName
def __get__(self, obj, objType=None):
print(f"Accessing {self.varName}...")
return getattr(obj, self.varName)
def __set__(self, obj, value):
print(f"Setting {self.varName}...")
setattr(obj, self.varName, value)
class MyClass(metaclass=UpperAttrMetaclass):
x = 1
y = RevealAccess("y")
def __init__(self):
self.z = 3
my_obj = MyClass()
print(dir(my_obj))