获取带有装饰器的函数的父 class 名称
Get the parent class name of a function with a decorator
让 class 具有以下功能:
class Tester:
@Logger()
def __init__(self):
print(__class__)
@Logger()
def func(self, num):
return num**2
其中Logger是一个装饰器,大致定义为:
from typing import Optional, Any
from logging import getLogger
class Logger:
def __init__(self):
self.logger = getLogger()
self.logging_function = getattr(self, 'function')
def __call__(self, decorator: callable):
def f(*args, **kwargs):
return self.logging_function(decorator, *args, **kwargs)
return f
def function(self, func: callable, *args: Optional[Any], **kwargs: Optional[Any]):
func_name = Logger.get_name(func)
self.logger.info(f"Starting: {func_name}.")
return func(*args, **kwargs)
@staticmethod
def get_name(func):
return f'__init__ {func.__class__.__name__}' if func.__name__ == '__init__' else func.__name__
我们如何编辑 Logger get_name
函数,这样如果函数 运行 是一个 class __init__
返回的名称是 __init__ Tester
,但是如果函数被命名为别的东西它只是 returns 函数 __name__
?
(又名)预期输出:
>>> test = Tester()
INFO: Starting __init__ Tester.
<class '__main__.Tester'>
>>> test.func(3)
INFO: Starting func.
9
当前输出:
>>> test = Tester()
INFO: Starting __init__ function.
<class '__main__.Tester'>
>>> test.func(3)
INFO: Starting func.
9
您可以像这样使用 qualified name:
@staticmethod
def get_name(func):
return func.__qualname__
这会给你这样的东西:
>>> test = Tester()
INFO:Starting: Tester.__init__.
<class '__main__.Tester'>
>>> test.func(3)
INFO:Starting: Tester.func.
9
您可能还对 standard LogRecord
attribute funcName
感兴趣,它在 函数中执行类似的操作。一个基本的演示:
import logging
logging.basicConfig(
level=logging.INFO,
format="%(levelname)s (%(funcName)s) %(message)s",
)
log = logging.getLogger()
class A:
def my_method(self):
log.info("hello")
def bar():
log.info("world")
A().my_method()
bar()
输出这个:
INFO (my_method) hello
INFO (bar) world
从 Python 3.3 开始,您应该可以使用 func.__qualname__
到达那里。
为了保持一致性,我个人会保持简单:
@staticmethod
def get_name(func):
return func.__qualname__
但为了完全符合您的预期输出,我相信这会起作用:
@staticmethod
def get_name(func):
if '.__init__' in func.__qualname__:
class_name = func.__qualname__.split('.')[-2] # this prints the innermost type in case of nested classes
return f'__init__ {class_name}'
return func.__name__
您可以使用以下函数获取函数名称。
get_name
生成您想要的输出的代码片段:
@staticmethod
def get_name(func):
func_name = func.__qualname__.split('.') if '__init__' in func.__qualname__ else func.__name__
func_name = ' '.join(func_name[::-1]) if isinstance(func_name, list) else func_name
return func_name
输出:
Starting: __init__ Tester.
<class '__main__.Tester'>
Starting: func.
如果你想要更通用,那么你可以使用下面的函数。
get_name
通用代码片段:
@staticmethod
def get_name(func):
func_name = func.__qualname__.split('.') if '.' in func.__qualname__ else func.__name__
func_name = ' '.join(func_name[::-1]) if isinstance(func_name, list) else func_name
return func_name
输出:
Starting: __init__ Tester.
<class '__main__.Tester'>
Starting: func Tester.
按您的意愿完成工作代码:
from typing import Optional, Any
from logging import getLogger
class Logger:
def __init__(self):
self.logger = getLogger()
self.logging_function = getattr(self, 'function')
def __call__(self, decorator: callable):
def f(*args, **kwargs):
return self.logging_function(decorator, *args, **kwargs)
return f
def function(self, func: callable, *args: Optional[Any], **kwargs: Optional[Any]):
func_name = Logger.get_name(func)
self.logger.info(f"Starting: {func_name}.")
return func(*args, **kwargs)
@staticmethod
def get_name(func):
func_name = func.__qualname__.split('.') if '__init__' in func.__qualname__ else func.__name__
func_name = ' '.join(func_name[::-1]) if isinstance(func_name, list) else func_name
return func_name
class Tester:
@Logger()
def __init__(self):
print(__class__)
@Logger()
def func(self, num):
return num**2
test = Tester()
test.func(3)
输出:
Starting: __init__ Tester.
<class '__main__.Tester'>
Starting: func.
让 class 具有以下功能:
class Tester:
@Logger()
def __init__(self):
print(__class__)
@Logger()
def func(self, num):
return num**2
其中Logger是一个装饰器,大致定义为:
from typing import Optional, Any
from logging import getLogger
class Logger:
def __init__(self):
self.logger = getLogger()
self.logging_function = getattr(self, 'function')
def __call__(self, decorator: callable):
def f(*args, **kwargs):
return self.logging_function(decorator, *args, **kwargs)
return f
def function(self, func: callable, *args: Optional[Any], **kwargs: Optional[Any]):
func_name = Logger.get_name(func)
self.logger.info(f"Starting: {func_name}.")
return func(*args, **kwargs)
@staticmethod
def get_name(func):
return f'__init__ {func.__class__.__name__}' if func.__name__ == '__init__' else func.__name__
我们如何编辑 Logger get_name
函数,这样如果函数 运行 是一个 class __init__
返回的名称是 __init__ Tester
,但是如果函数被命名为别的东西它只是 returns 函数 __name__
?
(又名)预期输出:
>>> test = Tester()
INFO: Starting __init__ Tester.
<class '__main__.Tester'>
>>> test.func(3)
INFO: Starting func.
9
当前输出:
>>> test = Tester()
INFO: Starting __init__ function.
<class '__main__.Tester'>
>>> test.func(3)
INFO: Starting func.
9
您可以像这样使用 qualified name:
@staticmethod
def get_name(func):
return func.__qualname__
这会给你这样的东西:
>>> test = Tester()
INFO:Starting: Tester.__init__.
<class '__main__.Tester'>
>>> test.func(3)
INFO:Starting: Tester.func.
9
您可能还对 standard LogRecord
attribute funcName
感兴趣,它在 函数中执行类似的操作。一个基本的演示:
import logging
logging.basicConfig(
level=logging.INFO,
format="%(levelname)s (%(funcName)s) %(message)s",
)
log = logging.getLogger()
class A:
def my_method(self):
log.info("hello")
def bar():
log.info("world")
A().my_method()
bar()
输出这个:
INFO (my_method) hello
INFO (bar) world
从 Python 3.3 开始,您应该可以使用 func.__qualname__
到达那里。
为了保持一致性,我个人会保持简单:
@staticmethod
def get_name(func):
return func.__qualname__
但为了完全符合您的预期输出,我相信这会起作用:
@staticmethod
def get_name(func):
if '.__init__' in func.__qualname__:
class_name = func.__qualname__.split('.')[-2] # this prints the innermost type in case of nested classes
return f'__init__ {class_name}'
return func.__name__
您可以使用以下函数获取函数名称。
get_name
生成您想要的输出的代码片段:
@staticmethod
def get_name(func):
func_name = func.__qualname__.split('.') if '__init__' in func.__qualname__ else func.__name__
func_name = ' '.join(func_name[::-1]) if isinstance(func_name, list) else func_name
return func_name
输出:
Starting: __init__ Tester.
<class '__main__.Tester'>
Starting: func.
如果你想要更通用,那么你可以使用下面的函数。
get_name
通用代码片段:
@staticmethod
def get_name(func):
func_name = func.__qualname__.split('.') if '.' in func.__qualname__ else func.__name__
func_name = ' '.join(func_name[::-1]) if isinstance(func_name, list) else func_name
return func_name
输出:
Starting: __init__ Tester.
<class '__main__.Tester'>
Starting: func Tester.
按您的意愿完成工作代码:
from typing import Optional, Any
from logging import getLogger
class Logger:
def __init__(self):
self.logger = getLogger()
self.logging_function = getattr(self, 'function')
def __call__(self, decorator: callable):
def f(*args, **kwargs):
return self.logging_function(decorator, *args, **kwargs)
return f
def function(self, func: callable, *args: Optional[Any], **kwargs: Optional[Any]):
func_name = Logger.get_name(func)
self.logger.info(f"Starting: {func_name}.")
return func(*args, **kwargs)
@staticmethod
def get_name(func):
func_name = func.__qualname__.split('.') if '__init__' in func.__qualname__ else func.__name__
func_name = ' '.join(func_name[::-1]) if isinstance(func_name, list) else func_name
return func_name
class Tester:
@Logger()
def __init__(self):
print(__class__)
@Logger()
def func(self, num):
return num**2
test = Tester()
test.func(3)
输出:
Starting: __init__ Tester.
<class '__main__.Tester'>
Starting: func.