2015-04-03 110 views
0

后,我有命名的参数如何获得命名参数顺序调用函数

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'] 

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

更新:

我想为elasticsearch过滤器像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中长查询的一些想法?

+10

您可以举个例子说明这些信息会有用吗? – Kevin 2015-04-03 19:50:10

+0

据我所知这是不可能的,因为命名参数在内部作为字典处理,没有命令 – Finwood 2015-04-03 19:53:03

+1

对于简单的情况,一种方法是从调用帧读取函数调用行并解析它使用正则表达式或其他东西,但如果函数调用跨越多行,这将无法正常工作。 – 2015-04-03 19:58:15

回答

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 
+0

正如我在[评论]中提到的(http://stackoverflow.com/questions/29438746/how-to-get-the-命名参数 - 函数调用函数#comment47046374_29438746),这对于'f(a = 1,\ nb = 3)'这样的函数不起作用。 – 2015-04-03 20:09:52

+0

@AshwiniChaudhary足够足够 – 2015-04-03 20:12:41

+0

谢谢,我会尝试 – 2015-04-03 20:16:27

-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 

这也许可以用一个装饰或者一些其他的方式来完成?

参数的顺序是由调用者决定的 - 一个装饰器不能改变它。

Btw。有关于此的草稿PEP

+0

感谢你们的支持。也许你可以添加一些评论,所以我可以改善这个帖子? – miraculixx 2015-04-03 20:08:45