📜  Python中的魔杖函数()函数(1)

📅  最后修改于: 2023-12-03 15:19:31.578000             🧑  作者: Mango

Python中的魔杖函数(__call__)函数

在Python中,一些特殊的函数被称为魔法函数或者特殊方法,因为它们在特定情况下会被Python解析器隐式调用。其中一个特殊方法是__call__() ,该方法允许类的实例像调用函数一样被调用。

为什么要使用__call__()

通常,如果您想使一个对象像函数一样被调用,则需要使用封装函数的方式,但这可能会使代码多余。因此,魔术方法提供了一种更有效的方式来实现这种实例化的方式。

例如,下面的代码创建了一个类MyClass,该类中含有方法__call__(),该方法使得该类的实例可以像函数一样被调用:

class MyClass:
    def __call__(self, *args, **kwargs):
        print('I am being called like a function')

mc = MyClass()
mc()

在上面的代码中,我们定义了一个类MyClass,并在其中定义了一个名为__call__()的方法。当我们创建类的实例并像函数一样使用它时,__call__()方法将被调用。在上面的示例中,我们将“我被像一个函数一样被调用”打印到控制台中。

用途
可调用的类

使用__call__()方法可以使类的实例像函数一样被调用,而不需要额外的封装函数。这使得类的设计更为灵活,并可以使代码更为优雅。

class NamedString:
    def __init__(self, name):
        self.name = name

    def __call__(self, c):
        return "Name: {}, Character: {}".format(self.name, c)

name_string = NamedString("Hermione")
print(name_string('H')) # Output: Name: Hermione, Character: H

在上面的示例中,我们创建了一个类NamedString,并在其中定义了一个__call__()方法。这个方法接受一个参数,将类实例的名称和传递的字符都转换为一个格式化字符串并返回。当我们创建一个NamedString类的实例时,我们可以使用该实例来获取该实例的格式化字符串。注意,在这个例子中,实例对象本身就像函数一样被调用。

包装器

我们可以使用__call__()方法来定义一个对成员函数的包装器。

def wrapper(func):
    def inner(*args, **kwargs):
        print("wrapper starts")
        func(*args, **kwargs)
        print("wrapper ends")
    return inner

class Decorator:
    def __init__(self, func):
        self.func = func

    def __call__(self, *args, **kwargs):
        print('calling instance:')
        return self.func(*args, **kwargs)

@wrapper
def myfunc():
    print('hello!')

dec = Decorator(myfunc)
dec()

在上面的示例中,我们定义了一个装饰函数wrapper,该函数可以将另一个函数装饰成一个新的函数。我们还定义了一个包装器类Decorator,它接受一个函数并将其存储为类变量。当我们创建一个Decorator对象并像函数一样使用它时,它将调用存储的函数并执行该类的__call__()方法。在上面的示例中,我们创建了一个Decortor对象dec并将它作为wrapper函数的参数传递,然后我们调用dec()来执行包装后的myfunc()函数。

总结

__call__()是一种非常强大的技巧,可以使基于类的实例像函数一样被调用。这种方法可以用来实现一些高级技术,例如包装器或可调用的类。如果您的类需要以这种方式使用,请考虑使用这个方法。