参数解包和赋值给类变量

时间:2013-08-24 16:39:36

标签: python class args argument-unpacking

您好我有以下代码,它尝试创建一个类的实例并为其分配参数值。我正在尝试使用* args执行此操作,如下所示:

def main():
    testdata = ['FDR', False, 4, 1933]
    apresident = President(testdata)
    print apresident
    print apresident.alive

class President:
    id_iter = itertools.count(1)
    #def __init__(self, president, alive, terms, firstelected):
    def __init__(self, *args):
        self.id = self.id_iter.next()
        self.president = args[0]
        self.alive = args[1]
        self.terms = args[2]
        self.firstelected = args[3]

我收到“元组索引超出范围”错误。从注释行中可以看出,我以前使用位置参数来完成这个(有效),并使用如下行来执行此操作:

    self.president = president

在这种情况下使用* args的正确方法是什么?我应该使用* kwargs吗?

3 个答案:

答案 0 :(得分:3)

您只将一个参数传递给President(),即列表

['FDR', False, 4, 1933]

如果要将该列表中的项目作为单独的参数传递,请按以下方式执行:

    apresident = President(*testdata)  # note the * character

正如Panic上校指出的那样,在你的例子中,使用参数解包有点毫无意义 - 可能是你的实际用例更复杂,并且证明了它的使用是合理的。

<强>更新

你的评论确实是一个后续问题,作为一个单独的问题会更好,但是:

def main():
    testdata = {
        "president": "FDR",
        "alive": False,
        "terms": 4,
        "firstelected": 1933,
    }
    apresident = President(**testdata)
    anotherpresident = President(president="BHO", terms=2, firstelected=2008)
    print apresident
    print apresident.alive
    print anotherpresident
    print anotherpresident.alive

class President:
    id_iter = itertools.count(1)
    #def __init__(self, president, alive, terms, firstelected):
    def __init__(self, **kwargs):
        self.id = self.id_iter.next()
        self.president = kwargs.get("president", None)
        self.alive = kwargs.get("alive", True)
        self.terms = kwargs.get("president", 1)
        self.firstelected = kwargs.get("president", None)

这显示了如何定义默认值。

答案 1 :(得分:2)

如果你不知道将多少个参数传递给函数,你应该只使用*args

在您的情况下,您似乎需要全部president, alive, terms, firstelected。拥有一个将所有这些作为参数的构造函数没有任何问题。

使用

*kwargs有几个原因。一种是如果你有默认值应该使用,除非用户想要指定它们。

有关详细信息,请参阅this questionthis questionofficial documentation


回应您的评论

我建议你为每位总统提供datedied财产。如果他们尚未死亡,则该值应为None。当您仅使用功能扩展某些实例时,对代码进行推理变得更加困难(但并非不可能)。

话虽如此,如果你想要每个总统的任意属性显然不适用于每个实例,那么你可以使用关键字参数。但添加属性不仅限于构造函数。我会简单地使用 setattr()getattr()

如何使用kwargs

设置类属性
class President(object):
   def __init__(self, *args, **kwargs):
      for name, value in kwargs.items():
         # Make each keyword-argument a property of the class.
         setattr(self, name, value)

tVar = President(is_cool=True)
print tVar.is_cool # Returns True

答案 2 :(得分:1)

您正在调用President(testdata),当您应该执行President(*testdata)时,为了在调用构造函数时解压缩列表。

现在,你基本上传递了一个参数(列表),因此IndexError:你传递了一个参数,所以args等于[testdata]并且不是testdata


正如在另一个答案中所提到的,在你的构造函数中使用*args并不是非常Pythonic。你知道你期望哪些参数,所以只需使用它们。

但是,当你调用这个函数时,可以使用它。