为什么不能在子类的__init__中传递*args和**kwargs

Nic*_*Guy 14 python

为了理解*args和**kwargs我做了一些搜索,当我遇到这个问题时*args和**kwargs?

所选答案下面的答案引起了我的注意,这是:

class Foo(object):
    def __init__(self, value1, value2):
    # do something with the values
        print value1, value2

class MyFoo(Foo):
    def __init__(self, *args, **kwargs):
    # do something else, don't care about the args
        print 'myfoo'
        super(MyFoo, self).__init__(*args, **kwargs)
Run Code Online (Sandbox Code Playgroud)

我在这个例子上尝试了一些东西并以这种方式运行代码:

class Foo(object):
    def __init__(self, value1, value2):
    # do something with the values
        print 'I think something is being called here'
        print value1, value2


class MyFoo(Foo):
    def __init__(self, *args, **kwargs):
    # do something else, don't care about the args
        print args, kwargs
        super(MyFoo, self).__init__(*args, **kwargs)


foo = MyFoo('Python', 2.7, stack='overflow')
Run Code Online (Sandbox Code Playgroud)

我懂了:

[...]
    super(MyFoo, self).__init__(*args, **kwargs)
TypeError: __init__() got an unexpected keyword argument 'stack'
Run Code Online (Sandbox Code Playgroud)

变得像 super(MyFoo, self).__init__(args, kwargs)

结果是:

('Python', 2.7) {'stack': 'overflow'}
I think something is being called here
('Python', 2.7) {'stack': 'overflow'}
Run Code Online (Sandbox Code Playgroud)

出于某些打击的原因,我正在质疑这个问题:上面的例子中有什么可能是对的?什么是允许做什么和现实生产中不会做什么?

Mar*_*ers 19

Foo.__init__()不会支持任意关键字参数.您可以添加**kw它的签名以使其接受它们:

class Foo(object):
    def __init__(self, value1, value2, **kw):
       print 'I think something is being called here'
       print value1, value2, kw
Run Code Online (Sandbox Code Playgroud)

关键字参数仅与具有完全匹配关键字名称的参数匹配; 你的Foo方法需要有Pythonstack关键字参数.如果找不到匹配的关键字参数但**kw参数,则会在该参数中收集它们.

如果您的子类知道父类只有位置参数,您始终可以传入位置:

class MyFoo(Foo):
    def __init__(self, *args, **kwargs):
    # do something else, don't care about the args
        print args, kwargs
        while len(args) < 2:
            args += kwargs.popitem()
        super(MyFoo, self).__init__(*args[:2])
Run Code Online (Sandbox Code Playgroud)

您现在必须传入两个或多个参数才能MyFoo使调用工作.

实质上,super().methodname返回对bound方法的引用; 从那里开始它是一个普通的方法,所以你需要传递任何方法都可以接受的参数.如果您的方法不接受关键字参数,则会出现异常.


Bry*_*ley 6

执行此操作时:

super(MyFoo, self).__init__(*args, **kwargs)
Run Code Online (Sandbox Code Playgroud)

就像您执行此操作一样,基于代码的工作方式:

super(MyFoo, self).__init__("python", 2.7, stack="overflow")
Run Code Online (Sandbox Code Playgroud)

然而,__init__功能Foo(从MyFoo继承)不支持名为“栈”关键字参数。


Vas*_*sif 5

原因是所有的论点都已经解包到 kwargs 中,现在它是一个 dict。并且您正试图将其传递给普通变量。

def bun(args,kwargs):
print 'i am here'
print kwargs

def fun(*args,**kwargs):
print kwargs
bun(*args,**kwargs)

 fun(hill=3,bi=9) # will fail.


def bun(*args,**kwargs):
print 'i am here'
print kwargs

def fun(*args,**kwargs):
print kwargs
bun(*args,**kwargs) # will work.



fun(hill=3,bi=9)
Run Code Online (Sandbox Code Playgroud)

尝试在

class Foo(object):
    def __init__(self, *value1, **value2):
# do something with the values
        print 'I think something is being called here'
        print value1, value2


class MyFoo(Foo):
    def __init__(self, *args, **kwargs):
# do something else, don't care about the args
        print args, kwargs
        super(MyFoo, self).__init__(*args, **kwargs)


foo = MyFoo('Python', 2.7, stack='overflow'
Run Code Online (Sandbox Code Playgroud)

应该管用..!