2016-09-09 3 views
5

Пусть у меня есть следующий пример:Python - Перебор аргументов, передаваемых функция

class foo: 
    ... 
    def bar(self, w, x, y, z, ...): 
     self.w = w 
     self.x = x 
     self.y = y 
     self.z = z 
     ... 

Я хочу, чтобы уменьшить п-число строк присвоения атрибутов в bar() на один назначения набора линий с использованием setattr() цикла через аргументы. Есть ли хороший способ циклически использовать указанные аргументы для этой цели?

Я хочу сохранить определенные имена параметров, чтобы ограничить количество переданных функции, а также порядок их передачи. Я также понимаю, что functions can be handled like objects; так можно ли получить список определенных параметров как атрибут функции и перебрать это?

+0

информацию, которую вы ищете будет определен в [Python Language Reference - Модель данных - объекты, значения и типы] (https://docs.python.org/2/reference/datamodel.html#objects-values-and-types) ссылка ([ссылка на версию 3] (https://docs.python.org/3/reference/datamodel .html # объекты-значения и-типа)). Не похоже, что список параметров определен как часть объекта функции. –

+1

Просто нашел это после того, как я разместил вопрос. [Получение списка имен параметров внутри функции Python] (http://stackoverflow.com/questions/582056/getting-list-of-parameter-names-inside-python-function) Это может ответить на мой вопрос. Не стесняйтесь отмечать этот вопрос как дубликат. –

+0

@JEarls Список параметров не определен, но в верхней части функции или метода 'locals()' будет содержать только параметры (включая 'self', если это метод). –

ответ

0

Используйте locals() и вы можете получить все аргументы (и любые другие локальные переменные):

class foo: 
    def bar(self, w, x, y, z): 
     argdict = {arg: locals()[arg] for arg in ('w', 'x', 'y', 'z')} 
     for key, value in argdict.iteritems(): 
      setattr(self, key, value) 
     ... 

Возможно, можно сделать это более эффективно, и вы можете включить аргумент, если вы предпочитаете меньше строк для чтения или считаете его более читаемым.

+0

Итак, 'locals()', в этом случае вернет словарь аргументов, переданных функции 'bar()' со значениями, введенными для имен? Является ли 'locals()' работает только в масштабе функции 'bar()'? –

+1

Да. Более конкретно, 'locals()' возвращает все локальные переменные - если вы вставили строку 'q = 73' перед вызовом' locals() ', dict будет включать эту пару. В dict есть «self», поэтому я скопировал его в новый dict вместо использования его напрямую - он позволяет ограничивать только предполагаемые переменные, даже если вам нужно позже его переместить, а также означает, что вы не пытаетесь установить 'self.self = self', что было бы бесполезно в лучшем случае. –

+0

Хорошо. Так что, если я вызываю 'argdict = locals()' в самом начале функции 'bar()', он будет содержать только элементы, переданные в bar в качестве аргументов? Это то, что я ищу. –

-1

Атрибут __setattr__ только присваивает один атрибут в то время, если вы хотите назначить несколько атрибутов, вы можете использовать **kwargs в вашем заголовке функции и для ограничения количества аргументов, вы можете просто проверить длину kwargs в пределах вашей функции. и позвоните по номеру __setattr__ для каждого из аргументов один за другим. Одной из веских причин этого рецепта является то, что в принципе назначение атрибута объекту без учета чего-либо не является правильной и желательной работой из-за множества причин. Таким образом, вы должны назначать каждый атрибут по одному, рассматривая все необходимые условия.

Вы также можете сделать это вручную, обновив словарь экземпляра, но также должны обрабатывать исключения.

In [80]: class foo:      
    def bar(self, **kwargs): 
     if len(kwargs) != 4: 
      raise Exception("Please enter 4 keyword argument") 
     for k, v in kwargs.items(): 
      foo.__setattr__(self, k, v) 
    ....:    

In [81]: f = foo() 

In [82]: f.bar(w=1, x=2, y=3, z=4) 

In [83]: f.w 
Out[83]: 1 

In [84]: f.bar(w=1, x=2, y=3, z=4, r=5) 
--------------------------------------------------------------------------- 
Exception         Traceback (most recent call last) 
<ipython-input-84-758f669d08e0> in <module>() 
----> 1 f.bar(w=1, x=2, y=3, z=4, r=5) 

<ipython-input-80-9e46a6a78787> in bar(self, **kwargs) 
     2  def bar(self, **kwargs): 
     3   if len(kwargs) != 4: 
----> 4    raise Exception("Please enter 4 keyword argument") 
     5   for k, v in kwargs.items(): 
     6    foo.__setattr__(self, k, v) 

Exception: Please enter 4 keyword argument 

С помощью __setatter__ он будет автоматически заботиться, за исключением:

In [70]: f.bar(1, 2) 
--------------------------------------------------------------------------- 
TypeError         Traceback (most recent call last) 
<ipython-input-70-07d1f3c9e27f> in <module>() 
----> 1 f.bar(1, 2) 

<ipython-input-65-1049e26120c1> in bar(self, *args) 
     2  def bar(self, *args): 
     3   for item in args: 
----> 4    foo.__setattr__(self, item, item) 
     5 

TypeError: attribute name must be string, not 'int' 
+0

Это не приводит к назначению конкретных имен и количества параметров по запросу. –

+0

@DavidHeyman Я не вижу такой вещи в вопросе. Можете ли вы подробнее рассказать? – Kasramvd

+0

Первая строка последнего абзаца, когда я пишу это: «Я хочу сохранить определенные имена параметров, чтобы ограничить количество параметров, переданных функции, а также порядок, в котором они передаются». –

0

Так что вам не нужно на самом деле назвать аргументы явно использовать:

class foo: 
    def __init__(self, w, x, y, z): 
     args = locals()# gets a dictionary of all local parameters 
     for argName in args: 
      if argName!='self': 
       setattr(self, argName, args[argName]) 
Смежные вопросы