Python - Iterate over arguments passed to a function

Suppose I have the following example:

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

I want to reduce the n-number of attribute assignment lines in bar() to one job line using the setattr() loop through the arguments. Is there a good way to cyclically use the specified arguments for this purpose?

I want to save certain parameter names in order to limit the number of parameters passed to the function, as well as the order in which they are passed. I also understand that functions can be treated as objects ; so is it possible to get a list of certain parameters as an attribute of a function and repeat this?

+5
source share
3 answers

Use locals() , and you can get all the arguments (and any other local variables):

 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) ... 

It is possible to do this more efficiently, and you can include the argdict argument if you prefer fewer lines to read, or find it more readable in this way.

0
source

Thus, you do not need to explicitly specify the arguments explicitly:

 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]) 
0
source

The __setattr__ attribute only assigns one attribute at a time, if you want to assign multiple attributes, you can use **kwargs in your function header and to limit the number of arguments you can simply check the length of kwargs inside your function. and call __setattr__ for each of the arguments one by one. One of the good reasons for this recipe is that, in principle, assigning an attribute to an object without considering anything is not a correct and desirable job due to a variety of reasons. Therefore, you must assign each attribute one at a time, considering all the necessary conditions.

You can also do this manually by updating the instance dictionary, but you must also handle exceptions.

 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]: fw 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 

Using __setatter__ , it will automatically take care of the exception:

 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' 
-1
source

All Articles