gpt4 book ai didi

Python __init__ 和可变参数

转载 作者:太空宇宙 更新时间:2023-11-04 02:45:17 27 4
gpt4 key购买 nike

根据python documentation , __init__可以接受可变参数:

object.__init__(self[, ...])

Called after the instance has been created (by __new__()), but before it is returned to the caller. The arguments are those passed to the class constructor expression. If a base class has an __init__() method, the derived class’s __init__() method, if any, must explicitly call it to ensure proper initialization of the base class part of the instance; for example:

BaseClass.__init__(self, [args...]).

我正在努力理解如何在直接派生自 object 的类上使用可变参数.特别是,当试图实例化一个调用 super(<classname>, self).__init__(*args, **kwargs) 的类时,我发现如果我不带参数实例化类,一切都很好。

但是,如果我将参数传递给 init 函数,则会出现错误:

super(A,self).__init__(*args,**kwargs)
TypeError: object.__init__() takes no parameters

据我了解object.__init__应该能够根据文档获取参数——它还使编写代码更容易,因为每个类都可以将其参数向上传递到类层次结构中。

文档是否不正确,或者是 object.__init__特例?

代码如下:

class A(object):
def __init__(self, *args, **kwargs):
for i,a in enumerate(args):
print "arg", i,a
for k,v in kwargs.iteritems():
print "kwarg", k,v

super(A,self).__init__(*args,**kwargs)




a=A()
print "Done with first one"
a2=A(5,4,5,3)

最佳答案

您对文档的解释有问题。在你的第一行 object.__init__(self[, ...]) 不是指可变参数。它只是说 可能 __init__ 的参数不是 self

__init__ 在被 super 或任何其他方式调用方面与任何其他方法没有区别。举一个不那么令人困惑的例子,比如 abs .如果您将多个参数传递给 abs,它将引发 TypeError: abs() takes exactly one argument (2 given)。这是正常的,也是意料之中的。如果您将比预期更多的参数传递给 __init__ 方法,您将得到相同的错误。

未声明能够接受可变参数的 Python 方法将无法接受任意参数。 object.__init__ 不接受任何参数。您可以从 __init__ 将其全部作为 object.__init__(self)super(type(self), self).__init__() .

您可以重写您的示例,使其看起来像这样:

class A(object):
def __init__(self, *args, **kwargs):
for i, a in enumerate(args):
print "arg", i, a
for k, v in kwargs.iteritems():
print "kwarg", k, v

super(A, self).__init__()

起初这看起来毫无意义,因为您正在扩展一个不需要初始化的类 (object)。然而,即使是这个简单的示例也表明您可以为您的类处理一些参数,并将其他参数传递给基类。

一个常见的习惯用法是显式命名所有子类的参数(位置参数和关键字参数),让父构造函数处理其余部分。例如,请考虑以下内容:

class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age

class Citizen(Person):
def __init__(self, nationality, *args, **kwargs):
self.nationality = nationality
super(Citizen, self).__init__(*args, **kwargs)

在这种情况下,声明 Citizen除了接受普通参数之外的可变参数是非常方便的。您不必记住 Person 接受的参数,或者在参数发生变化时修改任何内容。但是,这并不意味着您可以使用完全任意的参数调用 Citizen.__init__。一共还是要传入三个参数,关键字只能有名字。 国籍姓名年龄。请注意,Person.__init__ 甚至懒得调用 object.__init__

要牢记的重要一点是,您将要处理的所有真实类,无论是来自 Python 库还是外部源,都应该有足够的文档记录,以告诉您什么可以传入,什么不能传入。只是因为某些东西在技术上接受可变参数,并不意味着它对可以传入的内容没有限制。

关于Python __init__ 和可变参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45293721/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com