元类(metaclass)是 Python 面试中的高级主题,主要考察候选人对类和对象底层机制的理解。以下是常见的 Python 元类面试题及详细解答:
1. 什么是元类?
回答:
元类是用于创建类的类。普通类的实例是对象,而元类的实例是类。默认的元类是 type
。
示例:
# 使用 type 创建一个类
MyClass = type('MyClass', (object,), {'attr': 42})
# 访问类属性
print(MyClass.attr) # 输出: 42
# 创建类的实例
obj = MyClass()
print(obj.attr) # 输出: 42
2. 如何定义和使用元类?
回答:
自定义元类需要继承 type
并重写 __new__
或 __init__
方法。
示例:
class MyMeta(type):
def __new__(cls, name, bases, dct):
print(f"Creating class {name}")
return super().__new__(cls, name, bases, dct)
# 使用元类创建类
class MyClass(metaclass=MyMeta):
pass
# 输出: Creating class MyClass
3. __new__
和 __init__
在元类中的作用?
回答:
__new__
:负责创建类对象,在类创建前执行。__init__
:负责初始化类对象,在类创建后执行。
示例:
class MyMeta(type):
def __new__(cls, name, bases, dct):
print(f"__new__ called for {name}")
return super().__new__(cls, name, bases, dct)
def __init__(cls, name, bases, dct):
print(f"__init__ called for {name}")
super().__init__(name, bases, dct)
class MyClass(metaclass=MyMeta):
pass
# 输出:
# __new__ called for MyClass
# __init__ called for MyClass
4. 元类的使用场景是什么?
回答:
元类通常用于控制类的行为或动态修改类。常见场景包括:
- 类属性验证:
验证类的定义是否满足特定规则。 - 动态添加方法或属性:
在类创建时添加额外功能。 - 框架开发:
Django 和 SQLAlchemy 等框架使用元类来处理 ORM 映射。
5. 如何在类中动态添加方法或属性?
示例:
class MyMeta(type):
def __new__(cls, name, bases, dct):
dct['new_attr'] = "I am dynamically added"
return super().__new__(cls, name, bases, dct)
class MyClass(metaclass=MyMeta):
pass
print(MyClass.new_attr) # 输出: I am dynamically added
6. 如何限制类的继承结构?
回答:
元类可以通过在 __new__
或 __init__
中检查 bases
参数,限制类的继承结构。
示例:
class SingletonMeta(type):
def __new__(cls, name, bases, dct):
if bases and Singleton in bases:
raise TypeError(f"{name} cannot inherit from Singleton")
return super().__new__(cls, name, bases, dct)
class Singleton(metaclass=SingletonMeta):
pass
# 不允许继承
class Subclass(Singleton): # 抛出 TypeError
pass
7. 实现一个单例模式的元类
示例:
class SingletonMeta(type):
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super().__call__(*args, **kwargs)
return cls._instances[cls]
class MyClass(metaclass=SingletonMeta):
pass
a = MyClass()
b = MyClass()
print(a is b) # 输出: True
8. type
和 object
的关系是什么?
回答:
type
是所有类的元类,包括object
本身。object
是所有类的基类。type
和object
的关系:type
是object
的类。object
是type
的实例。
示例:
print(type(object)) # 输出: <class 'type'>
print(type(type)) # 输出: <class 'type'>
9. 如何用元类控制类方法的行为?
回答:
通过在元类中修改类的方法,控制其行为。
示例:
class MyMeta(type):
def __new__(cls, name, bases, dct):
if 'greet' in dct:
original_method = dct['greet']
def new_method(*args, **kwargs):
print("Before greet")
result = original_method(*args, **kwargs)
print("After greet")
return result
dct['greet'] = new_method
return super().__new__(cls, name, bases, dct)
class MyClass(metaclass=MyMeta):
def greet(self):
print("Hello!")
obj = MyClass()
obj.greet()
# 输出:
# Before greet
# Hello!
# After greet
10. 什么是 ABCMeta
,它的用途是什么?
回答:
ABCMeta
是 Python 提供的一个内置元类,用于定义抽象基类(Abstract Base Class)。抽象基类可以定义必须被子类实现的方法。
示例:
from abc import ABC, abstractmethod
class MyAbstractClass(ABC):
@abstractmethod
def greet(self):
pass
class MyClass(MyAbstractClass):
def greet(self):
print("Hello!")
obj = MyClass() # 正常实例化
obj.greet() # 输出: Hello!
# 如果没有实现 greet 方法,将会报错:
# TypeError: Can't instantiate abstract class MyClass with abstract methods greet
11. 如何动态创建类?
回答:
通过 type
动态创建类。
示例:
# 动态创建类
MyClass = type('MyClass', (object,), {'greet': lambda self: print("Hello!")})
# 使用动态创建的类
obj = MyClass()
obj.greet() # 输出: Hello!
总结
Python 元类是一个高级主题,面试中经常考察以下方面:
- 基本概念(如
type
和object
的关系)。 - 自定义元类的实现方法(包括
__new__
和__init__
)。 - 元类的实际应用场景(如单例模式、类属性验证、框架设计等)。
- 动态类创建和控制类行为。
如果有更复杂的元类问题,可以进一步探讨!