Python:动态分配实例方法作为实例属性有什么问题

时间:2011-08-18 00:36:46

标签: oop python

我想出了以下代码来使用需要实例本身作为参数的装饰器来装饰实例方法:

from functools import wraps

def logging_decorator(tricky_instance):
    def wrapper(fn):
        @wraps(fn)
        def wrapped(*a, **kw):
            if tricky_instance.log:
                print("Calling %s.." % fn.__name__)
            return fn(*a, **kw)
        return wrapped
    return wrapper     

class Tricky(object):
    def __init__(self, log):
        self.log = log
        self.say_hi = logging_decorator(self)(self.say_hi)

    def say_hi(self):
       print("Hello, world!")


i1 = Tricky(log=True)
i2 = Tricky(log=False)

i1.say_hi()
i2.say_hi()

这似乎很有效,但我担心我可能忽略了这个技巧的一些无意识的副作用。我是要在脚下拍自己,还是这样安全?

请注意,我实际上并不想使用它进行日志记录,这只是我能提出的最有意义的例子。

2 个答案:

答案 0 :(得分:4)

我不清楚为什么你会想要这样做。如果要动态分配新方法类型,请使用types

import types

class Tricky(object):
    def __init__(self):
        def method(self):
            print('Hello')
        self.method = types.MethodType(method, self)

如果您想对实例执行某些操作,请使用__init__方法执行此操作。如果您只想访问装饰器中方法的实例,可以使用im_self属性:

def decorator(tricky_instance):
    def wrapper(meth):
        print(meth.im_self == tricky_instance)
        return meth
    return wrapper

就我个人而言,我认为这正在转向别人 - 我不应该使用装饰者的土地。

答案 1 :(得分:2)

我认为我试图变得不必要聪明。似乎有一个令人尴尬的简单解决方案:

from functools import wraps

def logging_decorator(fn):
    @wraps(fn)
    def wrapped(self, *a, **kw):
        if self.log:
            print("Calling %s.." % fn.__name__)
        return fn(self, *a, **kw)
    return wrapped

class Tricky(object):
    def __init__(self, log):
        self.log = log

    @logging_decorator
    def say_hi(self):
       print("Hello, world!")

i1 = Tricky(log=True)
i2 = Tricky(log=False)

i1.say_hi()
i2.say_hi()