刚刚看了一下廖老师的python小教程,里面提到Rest API有关URl书写的问题。利用python面向对象中的__getattr__
与'__call__'
来解决这一一个问题。
比如,对于/api/people/all这一类东西,利用python是怎么自动拼接的呢?
class MakeUrl(object):
def __init__(self,path=''):
self._path=path
def __getattr__(self,path):
return MakeUrl('%s/%s'%(self._path,path))
def __str__(self):
return self._path
print(MakeUrl().api.people.all)
解读一下上面的代码,__getattr__
,当这个类的实例访问一个不存在的属性的时候,这个实例就会自动调用__getattr__
方法,对于上面的MakeUrl类来说此__getattr__
接收实例本身,以及不存在的这个属性的名称为参数,所以在这个方法中我依然返回一个MakeUrl的实例,形成这样一种链式模式。
还有如github之类的api,我们使用的时候,经常要替换成自己的用户名,就像这样/users/:user/repos
要把user换成你自己,该怎么做呢,第一种方式,就是继续沿用上面的代码,注意一下user的位置做个判断就好了,第二种方式就是利用__call__
这个方法了;当我们想要在实例层面直接调用方法时,像这样s=MakeUrl() s()
此时,就会调用实例中的这个_call_方法,那我们拼这个Url的时候,就可以像这样MakeUrl.users(jerry).repos
实现代码如下:
class MakeUrl(object):
def __init__(self,path=''):
self._path=path
def __getattr__(self,path):
return MakeUrl('%s/%s'%(self._path,path))
def __call__(self,username):
return MakeUrl('%s/:%s'%(self._path,username))
def __str__(self):
return self._path
print(MakeUrl().users('jerry').repo)
至于理解方式,和之前的类似,就不赘述了,不得不感叹python的自由,像c#之类的静态语言实现可能还要用上扩展方法,反射之类的特性,python让人有充分的自由区发挥自己的想象,很完美。