簡體   English   中英

如何在Python class中得到class function object?

[英]How to get class function object in Python class?

我想在調用 function 之前做一些准備操作(例如日志記錄)。

例如,

class Test(object):
  def float(self, target):
    logging.info('Call float() function')
    return float(target)

  def int(self, target):
    logging.info('Call int() function')
    return int(target)

t = Test()
a = t.float('123')
b = t.int('123')

但是,現在我有大約 20 個函數需要做同樣的事情。 有什么辦法可以使用 1 function 來適應所有這些嗎? 就像是,

class Test(object):
  def __getattr__(self, name):
    def wrapper(args):
      return func(args) # is there any built-in funciton can get function object?
    logging.info('Call %s() function' % name)
    return wrapper

您可以使用裝飾器,在繼續調用method之前打印出方法的名稱:

def namer(var):
    def wrapper(*args, **kwargs):
        print(f'Call {var.__name__}() method')
        return var(*args, **kwargs)
    return wrapper

class Test(object):
    @namer
    def float(self, target):
        return float(target)

    @namer
    def int(self, target):
        return int(target)

t = Test()
a = t.float('123')
b = t.int('123')
print(a, b)

Output:

Call float() method
Call int() method
123.0 123

這就是您想要的(並且您不需要為每個函數添加decorator ):

class Test(object):
    def float(self, target):
        return float(target)

    def int(self, target):
        return int(target)

    def __getattribute__(self, name):
      attr = super().__getattribute__(name)
      print(f'Call {attr.__name__}() method')
      return attr

t = Test()
a = t.float('123')
b = t.int('123')
print(a, b)

Output:

Call float() method
Call int() method
123.0 123

這將包括在方法的日志記錄中使用的 arguments。

from functools import wraps

def logit(function):
    @wraps(function)
    def traced_func(self, *args, **kwargs):
        sargs = list(args)
        sargs += ["{farg}={fval!r}".format(farg=farg, fval=fval) for farg, fval in kwargs.items()]
        print('Call {}({})'.format(function.__name__, ", ".join(map(str,sargs))))
        rt = function(self, *args, **kwargs)
        return rt
    return traced_func

class Something(object):
    @logit
    def float(self, target, arg=None):
        return float(target)
    
    @logit
    def int(self, target):
        return int(target)


t = Something()

x = t.float(4, arg=9)
z = t.float(5)
y = t.int(8)

output

Call float(4, arg=9)
Call float(5)
Call int(8)

一般來說,我會建議將裝飾器放在每個方法之上,這樣更謹慎和可讀。 但是,您確實問過是否有辦法避免這樣做......

在 class 上使用裝飾器的裝飾器。

# use the same decorator as the above example along with this
def decorate_methods(decorator):
    def traced_func(cls):
        for attr in cls.__dict__:
            if callable(getattr(cls, attr)):
                setattr(cls, attr, decorator(getattr(cls, attr)))
        return cls
    return traced_func

@decorate_methods(logit)
class Test(object):
    def float(self, target):
        return float(target)

    def int(self, target):
        return int(target)

你可以做func = eval(name) 它不是很優雅,也不是很安全,但可以完成您想要的工作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM