Preface
Python 的可調用對像到底有什麼用處,為什麼要費事的重載括號而不是直接綁定類的普通方法。下面就來為大家分享__call__可調用對象的一些感悟。
底下為精簡代碼,方便接口調用的“約定俗成”:
- class route(object):
- def __init__(self , res):
- self.resource = res
- @classmethod
- def factory(cls):
- print 'factory'
- return cls()
- def __call__( self ,req):
- print 'route __call__'
- return self.resource()
- class resource(object):
- def __call__( self ,req):
- print 'resource __call__'
- class API(route):
- def __init__( self ):
- res = resource()
- super(API, self ).__init__(res)
- wsgi.server(eventlet.listen(( '' , 80 )), API.factory())
- class route(object):
- def __init__( self , res):
- self .resource = res
- @classmethod
- def factory( cls ):
- print 'factory'
- return cls ()
- def notcall( self ,req):
- print 'route notcall'
- return self .resource.notcall()
- class resource(object):
- def notcall( self ,req):
- print 'resource notcall'
- class API(route):
- def __init__( self ):
- res = resource()
- super(API, self ).__init__(res)
- wsgi.server(eventlet.listen(( '' , 80 )), API.factory().notcall())
只是想要函數,卻能完成不只是函數的工作
類似上面的代碼,許多模塊的接口的參數都是需要一個函數調用,比如這個 wsgi.server(port, app),第二個參數就是一個實際的 wsgi 服務的函數調用。然後 OOP 大行其道的今天,貌似地球上乃至宇宙中的萬物都可被抽象成對象,然而在實際的coding中,我們真的需要將所有的東西都抽象成對象嗎?
這也是我喜歡 Python 的一個原因,雖然 Python 中萬物都是對象,但是卻提供這種對象可調用的方式,而它可以完成一些函數不能完成的工作。比如靜態變量,這在 Python 中是不允許的,但是通過 __call__ 可以這樣做:
- class Factorial:
- def __init__( self ):
- self .cache = {}
- def __call__( self , n):
- if n not in self .cache:
- if n == 0:
- self .cache[n] = 1
- else:
- self .cache[n] = n * self .__call__(n-1)
- return self .cache[n]
- fact = Factorial()
- for i in xrange(10):
- print ( "{}! = {}" .format(i, fact(i)))
對象綁定
在涉及新類對象綁定的時候,可以在元類放置對象綁定時的操作代碼:
- class Metaclass(type):
- pass
- class Class1(Metaclass):
- def __call__( self ):
- print "I am in call: {}".format(self.__class__.__name__)
- class Class2(object):
- __metaclass__=Class1
- t=Class2()
- #I am in call: Class1
Supplement
* 化整為零的次世代網頁開發標準: WSGI
* 深刻理解 Python 中的元類 (metaclass)
沒有留言:
張貼留言