2015-04-03 96 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