Python - 迭代传递给函数的参数

Python - Iterating over Arguments passed to a Function

假设我有以下例子:

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

我希望使用 setattr() 参数循环将 bar() 中的 n 个属性赋值行减少到一个赋值行集。有没有一种好的方法可以为此目的循环上述参数?

我希望保留已定义的参数名称,以限制传递给函数的参数数量以及传递参数的顺序。我也明白 functions can be handled like objects;那么是否可以获取已定义参数的列表作为函数的属性并对其进行迭代?

__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'

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

也许可以更有效地做到这一点,如果您更喜欢更少的行而不是可读性或发现那样更可读,则可以内联 argdict。

所以你不必明确地命名参数使用:

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