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

+0

Насколько я знаю, это было бы невозможно, так как именованные аргументы обрабатываются как словари внутри, которые не имеют порядка – Finwood

+1

Ну, для простых случаев одним способом было бы прочитать строку вызова функции из вызывающего кадра и проанализировать ее используя регулярное выражение или что-то еще, но это не будет работать должным образом, если вызов функции охватывает несколько строк. –

ответ

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- order-of-named-arguments-after-a-call-the-function # comment47046374_29438746), а это не будет работать с чем-то вроде 'f (a = 1, \ nb = 3)'. –

+0

@AshwiniChaudhary Ярмарка достаточно –

+0

спасибо, я попробую –

-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 об этом

+0

благодарит вас, ребята, за downvotes. возможно, вы можете добавить некоторые комментарии, чтобы я мог улучшить сообщение? – miraculixx

Смежные вопросы