如何在Python中合并函数
首先是代码:
class Api():
def __init__(self, baseurl='http://localhost:8080/api'):
self.base_url = baseurl
def _makerequest(self, arguments):
data = urllib.urlencode(arguments)
req = urllib2.Request(self.base_url, data)
response = urllib2.urlopen(req)
return response
def getId(self, **kwargs):
arguments = kwargs
arguments['Type'] = 'getId'
return self._makerequest(arguments)
def getKey(self, **kwargs):
arguments = kwargs
arguments['Type'] = 'getKey'
return self._makerequest(arguments)
你可以看到,每个函数最终都会调用 _makerequest()
。我这样写是为了有不同的函数(这样代码补全时会有提示),但又尽量减少代码的重复。
我想知道是否可以只用一个函数,但用不同的名字来调用它。例如,我可以调用 getId() 和 getKey(),但它们实际上会触发类里面的同一个函数。
有没有什么建议可以让这个过程更简单呢?
5 个回答
0
在Python中,函数和方法跟其他任何对象一样,名字是可以随意取的,甚至可以没有名字——比如返回值是一个函数,或者叫做匿名函数的lambda。给_makerequests
一个类型参数,把重复的代码移出获取方法。
0
你可以使用装饰器。下面是一个简单的例子:
In [21]: def make_request(func):
def _get_request(*args):
print func(*args)
return _get_request
In [26]: class Api(object):
@make_request
def hello(self, s):
return 'Hello, '+s
@make_request
def goodbye(self, s):
return 'Goodbye, '+s
In [27]: api = Api()
In [28]: api.hello('world')
Hello, world
In [29]: api.goodbye('world')
Goodbye, world
1
我觉得你反对的主要是你在每个API方法里都有一些重复的基础代码。
arguments = kwargs
arguments['Type'] = # Something
你能不能简单地这样做:
def _makerequest(self, rtype, **kwargs):
kwargs['Type'] = rtype
data = urllib.urlencode(kwargs)
req = urllib2.Request(api.base_url, data)
response = urllib2.urlopen(req)
return response
这样你就可以做到:
def getId(self, **kwargs):
return self._makerequest('getId', **kwargs)
1
如果你真的想的话,可以直接使用 makerequest
,不需要这些包装函数。如果你想让代码看起来更好看,可以这样做:
def get(self, type, **kwargs):
arguments = kwargs
arguments['Type'] = 'Get'+type
return self.makerequest(arguments)
这样你就可以调用 get('Id', args)
或者 get('Key', args)
了。
0
这就是Python作为一种动态语言的优势所在——让这样的功能变得很简单。
class DynamicMethods(object):
def __init__(self):
pass
class HiddenImplementation(object):
''' we create a separate implementation class that:
1. stores the 'type' of the call (or whatever else you need to
store on a per-call basis)
2. define a __call__() method that lets us perform whatever our
dynamic method call needs to do. In this example, we just print
the kwargs we're passed along with the call 'type'.
'''
def __init__(self, typeName):
self.typeName = typeName
def __call__(self, **kwargs):
args = kwargs
args['type'] = self.typeName
for k, v in args.items():
print "{0}: {1}".format(k, v)
def __getattr__(self, name):
''' any time code looks up an attribute that the class doesn't have
explicitly, this will be called. If the attribute being looked up
starts with 'get', we create a HiddenImplementation object and
return that.
'''
if name.startswith('get'):
return self.HiddenImplementation(name)
if __name__ == "__main__":
d = DynamicMethods()
d.getId(a=1, b=2, c=3)
...打印出
bgporter@varese ~/temp:python dynamicFn.py
a: 1
c: 3
b: 2
type: getId