每次在 class 中调用函数的最佳方式是什么?

What is the best way to perhaps call a function, every time, inside a class?

我有一个 class,它有一个 可选 函数作为参数。有时我会用一个函数创建这个 class 的实例,有时不会。

每次调用实例的某些方法时都会调用该函数。当然,如果没有给出函数,那里什么也不会发生。

我的问题是,实现此目标的最佳方法是什么?我尝试了几件事。你能根据性能、可扩展性和可读性来判断我的解决方案吗?你有更好的解决方案吗?

class 看起来像这样

class MyClass(...):
    def __init__(self, function=None):
        self.function = function

    def method_a(self, ...)
        ...
        self.function(a,b,c)
        ...

    def method_b(self, ...)
        ...
        self.function(a,b,c)
        ...

    def method_c(self, ...)
        ...
        #not every method bothers with the function
        ...

当然这会产生

TypeError: 'NoneType' object is not callable

最天真的解决方案是用防御性 ifs 或试验来改变 class 本身:

class MyClass(...):
    def __init__(self, function=None):
        self.function = function

    def method_a(self, ...)
        ...
        if self.function:
            self.function(a,b,c)
        ...

    def method_b(self, ...)
        ...
        if self.function:
            self.function(a,b,c)
        ...

第二个解决方案是创建一个什么都不做的函数,并可能将其存储在 self.function:

def do_nothing(*x):
    pass

class MyClass(...):
    def __init__(self, function=None):
        if function is None:
            function = do_nothing
        self.function = function

    def method_a(self, ...)
        ...
        self.function(a,b,c)
        ...

    def method_b(self, ...)
        ...
        self.function(a,b,c)
        ...

第三个解决方案是创建一个函数包装器,其中包含防御性 ifs:

class Maybe(object):
    def __init__(self, function=None):
        self.function = function

    def __call__(self, *args):
        if self.function is None:
            return
        # else
        return self.function(args)

class MyClass(...):
    def __init__(self, function=None):
        self.function = Maybe(function)

    def method_a(self, ...)
        ...
        self.function(a,b,c)
        ...

    def method_b(self, ...)
        ...
        self.function(a,b,c)
        ...

每个人都会告诉您性能不应影响您的代码设计,除非您找到瓶颈并可以对其进行衡量。不过,重要的是代码的可读性。

在每个调用之前添加一个 if 条件是可读但重复的。重复的任务通常被封装到一个简单的函数中,那么为什么不这样做呢?

class MyClass(object):
    def __init__(self, function=None):
        self._function = function

    def method(self):
        self._callFunction("Charlie")

    def _callFunction(self, *args, **kwargs):
        if self._function:
            self._function(*args, **kwargs)

def myFunction(name):
    print("Je suis %s" % name)

instance = MyClass(myFunction)
instance.method()