35 Python __call__

如果一个对象定义了__call__(slef, [,*args [,**kwargs]]),则该对象可以模拟函数的行为,像函数一样使用它(相当于重载了括号运算符…)。

x(*args,**kwargs)等同于调用了x.__call__(*args,**kwargs)

所以如果想将一个类实例变成一个可调用对象,只需实现__call__()方法即可。

#!/usr/bin/python
# -*- coding: utf-8 -*-
class Foo(object):
    def __call__(self, x):
        print "__call__ x  = %s"%x

f = Foo()
f(1)            #__call__ x  = 1

class Next:
  List = []
  def __init__(self,low,high):
    for i in range(low,high):
      self.List.append(i)

  def __call__(self,x):
    if x < len(self.List):
        return self.List[x]
    return 'index out of range'

b = Next(1,7)   #[1, 4, 9, 16, 25, 36]
print b(2)      #3
print b(10)     #index out of range

problem,为什么a()a.__call__ ()的结果不一样?

class A(object):
    def __call__(self):
        print("__call__ from A!")
a = A()
a()                    #__call__ from A
a.__call__ = lambda : "__call__ from lambda"
print a.__call__()     #__call__ from lambda 
a()                    #__call__ from A

原因在于,在Python中,新式类的内嵌特殊方法和实例的属性字典是相互隔离的…

官网解释

For new - style classes , implicit invocations of special methods are only guaranteed to work correctly if defined on an object ‘s type , not in the object ’ s instance dictionary. That behaviour is the reason why the following code raises an exception(unlike the equivalent example with old - style classes)

当执行a.__call__ = lambda :"__call__ from lambda "时,在a.__dict__中新增了key为'__call__'的成员,但是当执行a()时,因为涉及特殊方法的调用,不会从 a.__dict__中寻找属性,而是从type(a).__dict__中寻找属性。
因此,就会出现如上所述的情况。

验证

a = A()
print a.__dict__       #{}
a()                    #__call__ from A
a.__call__ = lambda : "__call__ from lambda"
print a.__dict__       #{'__call__': <function <lambda> at 0x0000000002F6E908>},相当于实例方法
print a.__call__()     #__call__ from lambda,从实例字典中查找的 
a()                    #__call__ from A,从类字典中查找的

转载请标明出处,原文地址(http://blog.csdn.net/lis_12/article/details/54631368).

如果觉得本文对您有帮助,请点击‘顶’支持一下,您的支持是我写作最大的动力,谢谢。

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值