📅  最后修改于: 2023-12-03 15:19:31.578000             🧑  作者: Mango
__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__()
是一种非常强大的技巧,可以使基于类的实例像函数一样被调用。这种方法可以用来实现一些高级技术,例如包装器或可调用的类。如果您的类需要以这种方式使用,请考虑使用这个方法。