如何在调用函数后获取命名参数的顺序

时间:2015-04-03 19:49:18

标签: python elasticsearch

我有一个带有命名参数的函数

def sample(a=None, b=None, c=None)
    pass

如何在调用函数后得到这些参数的顺序?

sample(b=1, a=1, c=1)
out: ['b', 'a', 'c']

sample(c=1, a=1)
out: ['c', 'a']

sample(a=1, b=1)
out: ['a', 'b']

sample(b=1, a=1)
out: ['b', 'a']

sample(a=1, b=1, c=1)
out: ['a', 'b', 'c']

也许这可以使用装饰器或其他方式完成?

更新

我想为sqlalchemy过滤方式创建弹性搜索过滤器的包装器,但是通过命名参数

class ESQuery(object):
    def __init__(self, url, index):
        pass

    def filter(self, _bool=None, _range=None, _not=None, _and=None, _or=None, _type=None, exists=None, query=None):
        return self.query_body

调用该函数后,我需要获得正确的查询顺序,例如http://www.elastic.co/guide/en/elasticsearch/reference/1.5/query-dsl-and-filter.html

我无法构建查询以便保持严格的命令

es = Someclass(url, index)
es.filter()

我想使用命名参数来做,人们觉得它很方便用作工具提示

更新2:

我想找到另一种方式,一条线路还不够,因为可以长时间通话

from api.search_api import ESQuery
es = ESQuery(index='lot', place='etsy_spider', match_all=True)
print es.\
    filter(query='{ "tweet": "full text search" }').\
    filter(_range='{ "created": { "gte": "now - 1d / d" }}').\
    filter(should='{ "term": { "featured": true }},')

可能有一些关于如何在elasticsearch中简化长查询的想法?

2 个答案:

答案 0 :(得分:1)

我想不出它为什么会有用的原因。话虽这么说,您可以使用inspect模块(https://docs.python.org/2/library/inspect.html):

import inspect

def f(a=2, b=3):
    call_string = inspect.stack()[1][4] ## returns a list with the string that represents how the function was called.
    print call_string
    args, kwargs = get_function_args(call_string[0]) ## to return what you want
    ...

f(b=3, a=1) # prints [u'f(b=3, a=1)\n']

然后,您将使用正则表达式解析call_string

请注意,此方法仅适用于单线呼叫。

这是一个简单的正则表达式解析器,它将按照外观顺序返回参数列表和关键字参数。请注意,这是非常基本的,不适用于包含“,”的字符串。

import re

VALID_VAR = "([_A-Za-z][_a-zA-Z0-9]*)"
LEFT_PAR = '\('
RIGHT_PAR = '\)'

def get_function_args(line):
    args = []
    keywords = []
    res = re.search(VALID_VAR+LEFT_PAR+'(.*?)'+RIGHT_PAR+'$', line)
    if res:

        allargs = res.group(2)
        allargs = allargs.split(',') ## does not work if you have strings with ","

        for arg in allargs:

            ## Arguments
            res2 = re.search('^{0}$'.format(VALID_VAR), arg.strip())
            if res2:
                args.append(res2.group(1))
            ## Optional arguments
            res2 = re.search('^{0} *= *(.*)$'.format(VALID_VAR), arg.strip())
            if res2:
                keywords.append(res2.group(1))

    return args, keywords

答案 1 :(得分:-2)

是的,可以这样做 - 继续阅读。

  

如何在调用函数后得到这些参数的顺序?

命名参数作为字典传递,其.items()定义在arbitrary order中:

# this...
def foo(a=None, b=None, c=None):
    ...
# .... is the equivalent of:
def foo(**kwargs):
    a = kwargs.get('a')
    b = kwargs.get('b')
    c = kwargs.get('c')  
    ...
  

如何在调用函数后得到这些参数的顺序?

无论上述情况如何,您都可以使用OrderedDict

来实现
from collections import OrderedDict
def bar(sorted_kwargs):
      for k in sorted_kwargs.keys():
        print 'index of %s => %s' % (k, sorted_kwargs.keys().index(k))
bar(OrderedDict((('c', 1), ('a', 2), ('b', 3))))
# results
index of c => 0
index of a => 1
index of b => 2
  

也许这可以使用装饰器或其他方式完成?

参数的顺序是调用者决定的东西 - 装饰者不能改变它。

顺便说一下。关于此

的草案PEP