Python - Print method name whenever the methods of a class is called
每次调用特定类的方法时,我都需要执行某些操作(例如,记录方法名)。如何以通用的方式在Python中实现这一点?
从元类内修饰可调用属性:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | from functools import wraps def _log_method(val): @wraps(val) def wrapper(*a, **ka): print(val.__name__, 'is called') val(*a, **ka) return wrapper class LogMethodCalls(type): def __new__(cls, cls_name, bases, attrs): for name, attr in attrs.items(): if callable(attr): attrs[name] = _log_method(attr) return type.__new__(cls, cls_name, bases, attrs) class Foo(metaclass=LogMethodCalls): def my_method(self): pass Foo().my_method() # my_method is called |
警告:此代码仅适用于使用
对于类方法和静态方法,也可以使用以下方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | from functools import wraps def _log_method(val): @wraps(val) def wrapper(*a, **ka): print('calling', val.__name__) val(*a, **ka) return wrapper class LogMethodCalls(type): def __new__(cls, cls_name, bases, attrs): for name, attr in attrs.items(): if callable(attr): attrs[name] = _log_method(attr) elif isinstance(attr, (classmethod, staticmethod)): attrs[name] = type(attr)(_log_method(attr.__func__)) return type.__new__(cls, cls_name, bases, attrs) class Foo(metaclass=LogMethodCalls): def my_instance_method(self): pass @classmethod def my_class_method(cls): pass @staticmethod def my_static_method(): pass Foo().my_instance_method() # calling my_instance_method Foo.my_class_method() # calling my_class_method Foo.my_static_method() # calling my_static_method |
它们有我们可以装饰的
请注意,您需要使用
1 2 | class Foo(object): __metaclass__ = LogMethodCalls |
在Python 2中。
摘自这个答案。您可以使用
1 2 3 4 5 6 7 8 9 10 | import inspect def log_call(): print(inspect.stack()[1][3]) def my_func(): log_call() # do stuff my_func() |
这将打印
您可以实现一个修饰器:
1 2 3 4 5 6 7 8 | from functools import wraps def print_function_name(function): @wraps(function) def do_it(): print function.__name__ function() return do_it |
用途:
1 2 3 4 | class MyClass(object): @print_function_name def some_function(self): pass |
例如:
1 2 3 | >>> my_object = MyClass() >>> my_object.some_function() some_function |
使用
摘自https://stackoverflow.com/a/5103895/5270581:对象类的以下方法在每次访问对象的属性时调用,包括方法调用:
1 | __get_attribute__ |
所以我建议通过向内部的日志函数添加一个调用来覆盖它。代码示例请参见https://stackoverflow.com/a/5103895/5270581(转到最后一个答案)。