根据python documentation,__init__
可以接受varargs:
object.__init__(self[, ...])
在创建实例(由
__new__()
)之后调用,但在将其返回给调用者之前调用。参数是传递给类构造函数表达式的参数。如果基类具有__init__()
方法,则派生类的__init__()
方法(如果有)必须显式调用它以确保实例的基类部分的正确初始化;例如:
BaseClass.__init__(self, [args...]).
我很难理解如何在直接派生自object
的类上使用varargs。特别是,当试图实例化一个调用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)
答案 0 :(得分:1)
object
只是一个特例,因为没有什么可以初始化,所以它的构造函数不接受任何args或kwargs。由于__init__
上的object
方法无法执行任何操作,因此如果您仅从object
继承,则无需调用它。
答案 1 :(得分:1)
您对文档的解释存在问题。在你的第一行object.__init__(self[, ...])
并不是指varargs。只是说可能是self
到__init__
以外的参数。
__init__
与其他任何方法的区别在于super
或其他任何方法。对于一个不那么令人困惑的例子,请采取abs
之类的方法。如果您将多个参数传递给abs
,则会引发TypeError: abs() takes exactly one argument (2 given)
。这是正常的和预期的。如果您向__init__
方法传递的参数多于预期,则会出现相同的错误。
未声明能够接受varargs的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
接受varargs 以及正常参数非常方便。您不必记住Person
接受的参数,或者在更改时修改任何内容。但是,这并不意味着您可以使用完全随意的参数调用Citizen.__init__
。您仍然必须传入总共三个参数,关键字只能包含名称。 nationality
,name
和age
。请注意,Person.__init__
甚至无法拨打object.__init__
。
要记住的重要一点是,您要处理的所有真正的类,无论是来自Python库还是外部源,都应该有足够的文档记录,告诉您可以和不能传递的内容。只是因为技术上接受varargs的东西,并不意味着它对传入的内容没有限制。
答案 2 :(得分:-3)
super()
有缺陷。见这里:https://fuhm.net/super-harmful/
简而言之:
您编写了代码,您应该知道层次结构。只需使用MySuperclass.__foobar__(self, etc)
即可。一直有效。