简体   繁体   English

Python-遍历传递给函数的参数

[英]Python - Iterating 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 wish to reduce the n-number of attribute assignment lines in bar() to one assignment line set using a setattr() cycle through the arguments. 我希望使用setattr()循环遍历参数,将bar()的n个属性赋值线减少为一组赋值线。 Is there a good way to cycle through said arguments for this purpose? 为此目的,有没有一种很好的方法可以循环讨论上述论点?

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 functions can be handled like objects ; 我也理解函数可以像对象一样处理 ; so is it possible to obtain a list of the defined parameters as an attribute of the function and iterate through that? 那么是否有可能获得已定义参数的列表作为函数的属性并对其进行迭代?

Use locals() and you can get all the arguments (and any other local variables): 使用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)
        ...

Might be possible to do it more efficiently, and you could inline argdict if you prefer less lines to readability or find it more readable that way. 可能可以更有效地执行此操作,并且如果您希望行数少一些而不是可读性,或者发现那样更具可读性,则可以内联argdict。

So you don't have to actually name the arguments explicitly use: 因此,您不必实际使用显式命名的参数:

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

The __setattr__ attribute only assigns one attribute at a time, if you want to assign multiple attribute, you can use **kwargs in your function header and for limiting the number of arguments you can simply check the length of kwargs within your function. __setattr__属性一次仅分配一个属性,如果要分配多个属性,则可以在函数头中使用**kwargs ,并且为了限制参数数量,您可以简单地检查函数中kwargs的长度。 and call the __setattr__ for each each of the arguments one by one. __setattr__调用每个参数的__setattr__ 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. 因此,您必须通过考虑所有所需条件来一次分配每个属性。

You can also do this manually by updating the instance dictionary but you should handle the exceptions too. 您也可以通过更新实例字典来手动执行此操作,但是您也应该处理异常。

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

By using __setatter__ it will take care of the exception automatically: 通过使用__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'

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM