欢迎各位兄弟 发布技术文章

这里的技术是共享的

You are here

python __call__ 方法 函数

shiping1 的头像

python __call__ 函数

 

 __call__

Python中有一个有趣的语法,只要定义类型的时候,实现__call__函数,这个类型就成为可调用的。

换句话说,我们可以把这个类型的对象当作函数来使用,相当于 重载了括号运算符。

class g_dpm(object):

def __init__(self, g):

self.g = g

def __call__(self, t):

return (self.g*t**2)/2

计算地球场景的时候,我们就可以令e_dpm = g_dpm(9.8)s = e_dpm(t)

 

    1. class Animal(object):
    2. def __init__(self, name, legs):
    3. self.name = name
    4. self.legs = legs
    5. self.stomach = []
    6.  
    7. def __call__(self,food):
    8. self.stomach.append(food)
    9.  
    10. def poop(self):
    11. if len(self.stomach) > 0:
    12. return self.stomach.pop(0)
    13.  
    14. def __str__(self):
    15. return 'A animal named %s' % (self.name)
    16.  
    17. cow = Animal('king', 4) #We make a cow
    18. dog = Animal('flopp', 4) #We can make many animals
    19. print 'We have 2 animales a cow name %s and dog named %s,both have %s legs' % (cow.name, dog.name, cow.legs)
    20. print cow #here __str__ metod work
    21.  
    22. #We give food to cow
    23. cow('gras')
    24. print cow.stomach
    25.  
    26. #We give food to dog
    27. dog('bone')
    28. dog('beef')
    29. print dog.stomach
    30.  
    31. #What comes inn most come out
    32. print cow.poop()
    33. print cow.stomach #Empty stomach
    34.  
    35. '''-->output
    36. We have 2 animales a cow name king and dog named flopp,both have 4 legs
    37. A animal named king
    38. ['gras']
    39. ['bone', 'beef']
    40. gras
    41. []
    42. '''

来自 http://www.cnblogs.com/lovemo1314/archive/2011/04/29/2032871.html
 




Python可调用对象__call__方法的用法分析

最近有许多朋友私信问我,Python的可调用对象到底有什么用处,为什么要费事的重载括号而不是直接绑定类的普通方法。下面就来为大家分享__call__可调用对象的一些感悟。

精简代码,方便接口调用的“约定俗成”

[python] view plaincopy
  1. class route(object):  
  2.   
  3.     def __init__(self, res)  
  4.         self.resource = res  
  5.      
  6.     @classmethod  
  7.     def factory(cls):  
  8.         print 'factory'  
  9.         return cls()  
  10.      
  11.     @webob.dec.wsgify  
  12.     def __call__(self,req):  
  13.         print 'route __call__'  
  14.         return self.resource()  
  15.   
  16. class resource(object):  
  17.  
  18.     @webob.dec.wsgify  
  19.     def __call__(self,req):  
  20.         print 'resource __call__'  
  21.   
  22. class API(route):  
  23.     def __init__(self):  
  24.         res = resource()  
  25.         super(API, self).__init__(res)  
  26.       
  27. wsgi.server(eventlet.listen((''80)), API.factory())  
上面的代码是一个典型的WSGI服务的节选,如果不用__call__,那么我们各组件之间可能要约定或规范一个接口,比如下面,大家都叫notcall()。。。
[python] view plaincopy
  1. class route(object):  
  2.   
  3.     def __init__(self, res)  
  4.         self.resource = res  
  5.      
  6.     @classmethod  
  7.     def factory(cls):  
  8.         print 'factory'  
  9.         return cls()  
  10.      
  11.     @webob.dec.wsgify  
  12.     def notcall(self,req):  
  13.         print 'route notcall'  
  14.         return self.resource.notcall()  
  15.   
  16. class resource(object):  
  17.  
  18.     @webob.dec.wsgify  
  19.     def notcall(self,req):  
  20.         print 'resource notcall'  
  21.   
  22. class API(route):  
  23.     def __init__(self):  
  24.         res = resource()  
  25.         super(API, self).__init__(res)  
  26.       
  27. wsgi.server(eventlet.listen((''80)), API.factory().notcall())  
这样用起来就非常麻烦,模块之间合作要约定好接口的名字,编写记忆许多接口文档,增加代码量且容易出错。

只是想要函数,却能完成不只是函数的工作

类似上面的代码,许多模块的接口的参数都是需要一个函数调用,比如这个wsgi.server(port, app),第二个参数就是一个实际的wsgi服务的函数调用。然后OOP大行其道的今天,貌似地球上乃至宇宙中的万物都可被抽象成对象,然而在实际的coding中,我们真的需要将所有的东西都抽象成对象吗?

这也是我喜欢Python的一个原因,虽然Python中万物都是对象,但是却提供这种对象可调用的方式,而它可以完成一些函数不能完成的工作。比如静态变量,这在Python中是不允许的,但是通过__call__可以这样做

[python] view plaincopy
  1. class Factorial:  
  2.     def __init__(self):  
  3.         self.cache = {}  
  4.     def __call__(self, n):  
  5.         if n not in self.cache:  
  6.             if n == 0:  
  7.                 self.cache[n] = 1  
  8.             else:  
  9.                 self.cache[n] = n * self.__call__(n-1)  
  10.         return self.cache[n]  
  11.   
  12. fact = Factorial()  
  13.   
  14. for i in xrange(10):                                                               
  15.     print("{}! = {}".format(i, fact(i)))  
  16.   
  17. # output  
  18. 0! = 1  
  19. 1! = 1  
  20. 2! = 2  
  21. 3! = 6  
  22. 4! = 24  
  23. 5! = 120  
  24. 6! = 720  
  25. 7! = 5040  
  26. 8! = 40320  
  27. 9! = 362880  

对象绑定

在涉及新类对象绑定的时候,可以在元类放置对象绑定时的操作代码

[python] view plaincopy
  1. class test(type):  
  2.     pass  
  3.   
  4. class test1(test):  
  5.     def __call__(self):  
  6.         print "I am in call"  
  7.   
  8. class test2(object):  
  9.     __metaclass__=test1  
  10.   
  11. t=test2()  
  12. #I am in call  
test2是test1的实例。因为test1是元类。在实例绑定元类的时候,__call__会调用

 

大家可以交流讨论下,看看还有哪些设计模式可以应用于此,我会补充的

来自 http://blog.csdn.net/networm3/article/details/8645185


 

普通分类: