目标:
给出类似的东西:
stackoverflow.users['55562'].questions.unanswered()
我希望将其转换为以下内容:
http://api.stackoverflow.com/1.1/users/55562/questions/unanswered
我已经能够实现这一点,使用以下类:
class SO(object):
def __init__(self,**kwargs):
self.base_url = kwargs.pop('base_url',[]) or 'http://api.stackoverflow.com/1.1'
self.uriparts = kwargs.pop('uriparts',[])
for k,v in kwargs.items():
setattr(self,k,v)
def __getattr__(self,key):
self.uriparts.append(key)
return self.__class__(**self.__dict__)
def __getitem__(self,key):
return self.__getattr__(key)
def __call__(self,**kwargs):
return "%s/%s"%(self.base_url,"/".join(self.uriparts))
if __name__ == '__main__':
print SO().abc.mno.ghi.jkl()
print SO().abc.mno['ghi'].jkl()
#prints the following
http://api.stackoverflow.com/1.1/abc/mno/ghi/jkl
http://api.stackoverflow.com/1.1/abc/mno/ghi/jkl
现在我的问题是我做不了类似的事情:
stackoverflow = SO()
user1 = stackoverflow.users['55562']
user2 = stackoverflow.users['55462']
print user1.questions.unanswered
print user2.questions.unanswered
#prints the following
http://api.stackoverflow.com/1.1/users/55562/users/55462/questions/unanswered
http://api.stackoverflow.com/1.1/users/55562/users/55462/questions/unanswered/questions/unanswered
基本上,user1和user2引用相同的SO
对象,因此它不能代表不同的用户。
我一直在想任何指针都会有所帮助,因为这种额外的功能会使API变得更有趣。
答案 0 :(得分:2)
恕我直言,当你重新创建一个新的stackoverflow对象时,你需要将参数与旧实例属性的深度副本分开
import copy
........
def __getattr__(self,key):
dict = copy.deepcopy(self.__dict__)
dict['uriparts'].append(key)
return self.__class__(**dict)
....
如果您希望URI部分具有更大的灵活性,则需要抽象来实现更清洁的设计。例如:
class SOURIParts(object):
def __init__(self, so, uriparts, **kwargs):
self.so = so
self.uriparts = uriparts
for k,v in kwargs.items():
setattr(self,k,v)
def __getattr__(self,key):
return SOURIParts(self.so, self.uriparts+[key])
def __getitem__(self,key):
return self.__getattr__(key)
def __call__(self,**kwargs):
return "%s/%s"%(self.so.base_url,"/".join(self.uriparts))
class SO(object):
def __init__(self, base_url='http://api.stackoverflow.com/1.1'):
self.base_url = base_url
def __getattr__(self,key):
return SOURIParts(self, [])
def __getitem__(self,key):
return self.__getattr__(key)
我希望这会有所帮助。
答案 1 :(得分:0)
您可以覆盖__getslice__
(Python 2.7)或getitem()
(Python3.x)并使用记忆装饰器,这样如果您请求的切片(用户ID)已被查找,它将会使用缓存结果 - 否则它可以检索结果并填充现有的SO实例对象。
但是,我认为解决问题的更多OO方法是使SO成为一个纯查找模块,它返回堆栈溢出用户对象,然后对配置文件详细信息进行更深入的挖掘查找。但那就是我。