在 Python 中,方法只是 属性,碰巧是可调用的*。您必须连接到设置的属性才能看到添加到类的新方法。
您必须使用metaclass 来拦截添加到类中的新属性:
import types
class NewMethodAlerter(type):
def __setattr__(self, name, obj):
if isinstance(obj, types.FunctionType):
print(f'New method {name} added!')
super().__setattr__(name, obj)
class Demo(metaclass=NewMethodAlerter):
def existing_method(self):
pass
def new_method(self): pass
Demo.new_method = new_method
然后看起来像这样:
>>> class Demo(metaclass=NewMethodAlerter):
... def existing_method(self):
... pass
...
>>> def new_method(self): pass
>>> Demo.new_method = new_method
New method new_method added!
如果您想了解 initial 属性集,即执行 class 主体的结果,那么您有两个选择:使用元类,或者在 Python 3.6 及更高版本中, __init_subclass__ method。任何一个都被调用来创建新类,并可用于检查属性:
class InitialMethodAlerter(type):
def __new__(typ, name, bases, attrs):
for name, obj in attrs.items():
if isinstance(obj, types.FunctionType):
print(f'Method {name} defined!')
return super().__new__(typ, name, bases, attrs)
class Demo(metaclass=InitialMethodAlerter):
def existing_method(self):
pass
或__init_subclass__ 方法:
class InitialMethodAlerter:
@classmethod
def __init_subclass__(cls, **kwargs):
for name, obj in vars(cls).items():
if isinstance(obj, types.FunctionType):
print(f'Method {name} defined!')
class Demo(InitialMethodAlerter):
def existing_method(self):
pass
你可能想在What is a metaclass in Python?阅读元类
*其实属性就是函数。函数是descriptor objects,这会导致它们在通过实例访问时被绑定。该绑定过程会生成一个方法对象,该对象在被调用时会获取原始函数并传入它所绑定的实例。