Python - Iterating over Arguments passed to a Function
<p>Suppose I have the following example:</p>

<pre><code>class foo:
   ...
   def bar(self, w, x, y, z, ...):
      self.w = w
      self.x = x
      self.y = y
      self.z = z
      ...
</code></pre>

<p>I wish to reduce the n-number of attribute assignment lines in <code>bar()</code> to one assignment line set using a <code>setattr()</code> cycle through the arguments. Is there a good way to cycle through said arguments for this purpose?</p>

<p>I wish to retain the defined parameter names so as to limit the number of parameters passed to the function as well as the order in which they are passed. I also understand that <a href="http://stackoverflow.com/questions/739654/how-to-make-a-chain-of-function-decorators-in-python/1594484#1594484">functions can be handled like objects</a>; so is it possible to obtain a list of the defined parameters as an attribute of the function and iterate through that?</p>

<p>The <a href="https://docs.python.org/3/reference/datamodel.html#object.__setattr__" rel="nofollow"><code>__setattr__</code></a> attribute only assigns one attribute at a time, if you want to assign multiple attribute, you can use <code>**kwargs</code> in your function header and for limiting the number of arguments you can simply check the length of <code>kwargs</code> within your function. and call the <code>__setattr__</code> for each each of the arguments one by one. One good reason for this recipe is that basically assigning attribute to an object without considering anything is not a correct and desirable job, due to a lot of reasons. Thus you have to assign each attribute one at a time by considering all the required conditions.</p>

<p>You can also do this manually by updating the instance dictionary but you should handle the exceptions too. </p>

<pre><code>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)
&lt;ipython-input-84-758f669d08e0&gt; in &lt;module&gt;()
----&gt; 1 f.bar(w=1, x=2, y=3, z=4, r=5)

&lt;ipython-input-80-9e46a6a78787&gt; in bar(self, **kwargs)
      2     def bar(self, **kwargs):
      3         if len(kwargs) != 4:
----&gt; 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
</code></pre>

<p>By using <code>__setatter__</code> it will take care of the exception automatically:</p>

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

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

TypeError: attribute name must be string, not 'int'
</code></pre>

python arguments variable-assignment setattr