如何在python中合并函数

时间:2014-04-24 12:41:23

标签: python python-2.7

首先是代码:

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 :(得分:1)

如果你真的想要,你可以在没有这些包装函数的情况下使用makerequest。如果你想要它更漂亮你可以做到:

def get(self, type, **kwargs):
    arguments = kwargs
    arguments['Type'] = 'Get'+type
    return self.makerequest(arguments)

因此,您可以致电get('Id', args)get('Key', args)

答案 1 :(得分:1)

在我看来,你所例外的是你有样板代码

arguments = kwargs
arguments['Type'] = # Something

在每种API方法中。你能不能简单地做到以下几点:

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)

答案 2 :(得分: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

答案 3 :(得分: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

答案 4 :(得分:0)

Python函数和方法中的

与任何其他对象相同,因此这个对象绑定的名称是完全免费的,甚至可能没有名称 - 想想返回值是函数,还是lambdas。给_makerequests一个类型参数并将重复的代码移出get-methods。