python中的__call__这个魔法方法是什么以及能用来做什么

1.魔法方法__call__是什么

不妨先看下面一个例子:

def foo1():
    print('hello python')

print(dir(foo1))

dir()内置函数不多说,结果如下:

['__call__', '__class__', '__closure__', '__code__', '__defaults__',.....省略]

注意这里第一个就是本文的主题,说明了该对像foo1是一个可调用对象,也就是报错时可能常见的callable object。
再举个例子如下:

class foo(object):
    def __init__(self):
        self.name = 'python'

    def foo1(self):
        print('hello%s'%self.name)

print(dir(foo))

结果如下:

['__class__', '__delattr__', '__dict__', '__doc__',省略]

发现没有__call__()方法,说明当前的foo对象不是可以调用的,强制调用会出现如下错误

instance = foo()
instance()
>>Traceback (most recent call last):
    instance()
TypeError: 'foo' object is not callable

这也是函数和类的一个区别,为了使得类/实例能够像函数一样使用,成为可调用对象,call()魔法方法出现了。
将类中定义一个__call__()方法如下:

class foo(object):
    def __init__(self):
        self.name = 'python'

    def __call__(self, *args, **kwargs):
        print('hello%s'%self.name)

instance = foo()
instance()
a = instance
print dir(a)

输出结果如下:

hellopython
['__call__', '__class__', '__delattr__', '__dict__',太长省略]

说明了该魔法方法能够使得一个实例变得可调用,像函数一样。

2.有什么用

看到这里,很多人觉得没什么实际用途啊,对于一个类,我单纯的实例化,然后通过实例对象调用类中的方法不就可以吗,定义个__call__然后使他可调用有什么用?
其实,对于简单的程序或者项目有些画蛇添足,但是,该方法最重要的用途就是将类/实例对象变成函数,变成可调用对象,函数相对于类/实例对象的方便之处就在于不需要实例化,随时只要传参就能使用。而__call__方法就是将类的实例对象变成函数
看下面的例子:

class Pipe(object):
    def __init__(self, fn):
        self.fn = fn

    def __ror__(self, other):
        return self.fn(other)

    def __call__(self, *args, **kwargs):
        op = Pipe(lambda x: self.fn(x, *args, **kwargs))
        return op

可以这样使用

@Pipe
def sort(data, cmp=None, key=None, reverse=False):
    return sorted(data, cmp=cmp, key=None, reverse=reverse)
    
[{'score': 1}, {'score': 3}, {'score': 2}] | sort(key=lambda x: x['score'])

在这里类 Pipe 被当作一个装饰器使用,众所周知,装饰器本身是一个函数,这里一个类作为了装饰器,那么就需要将其变为函数的可调用形式,那么__call__方法就起作用了。
所以 sort 函数的原始定义被传递给 Pipe中的__init__魔法方法,构造出一个 Pipe 实例,该实例在__call__方法作用下变为了一个函数,所以这个类能够作为函数来被装饰sort 函数,这里python管道符请移步自行学习。
除此之外,在一些 ORM 框架或者项目中,__call__方法很重要,经常查看源码的同学应该经常能够看到该方法。举个例子,在需要实例化且全局单例的情况下,通过直接导入该实例对象,就可以在其他程序中减少携带的参数,并且无需再实例化操作,变得和函数一样方便使用。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: __call__方法Python的一个特殊方法,它允许一个类的实例像函数一样被调用。当一个对象被调用时,Python会自动调用该对象的__call__方法。例如,我们可以定义一个类,并在其实现__call__方法,使得该类的实例可以像函数一样被调用: ``` class MyClass: def __init__(self, x): self.x = x def __call__(self, y): return self.x + y my_obj = MyClass(10) result = my_obj(5) print(result) # 输出 15 ``` 在上面的例子,我们定义了一个名为MyClass的类,并在其实现了__call__方法。该方法接受一个参数y,并返回self.x + y的结果。我们创建了一个MyClass的实例my_obj,并将其初始化为10。然后,我们将my_obj作为函数一样调用,并传入参数5。最终,我们得到了15作为结果。 ### 回答2: 在Python,每个类都可以定义一个特殊的方法`__call__`。`__call__`方法允许一个实例对象像函数一样被调用,这意味着可以将实例对象当作函数一样使用,并通过括号直接调用它。 举个例子,考虑一个简单的类`Person`,该类有一个`__call__`方法: ```python class Person: def __init__(self, name): self.name = name def __call__(self, greeting): print(f"{greeting}, {self.name}!") person = Person("Alice") person("Hello") # 输出:Hello, Alice! ``` 在上面的例子,我们创建了一个`Person`类,它接受一个参数`name`并保存在实例变量。我们定义了`__call__`方法,该方法接受一个参数`greeting`并将其与`name`一起打印出来。 当我们创建了一个名为`person`的`Person`实例后,我们可以像调用函数一样使用它。通过将括号跟在`person`后面并传递一个参数`"Hello"`,`__call__`方法将被调用,并输出`"Hello, Alice!"`。 可以将`__call__`方法用于各种目的。通过定制`__call__`方法,可以使得对象更具函数的行为,从而提供更多的灵活性和方便性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值