如何有效地传递参数(在Python中的**kwargs)

2024-05-13 21:02:53 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个继承自其他两个类的类。这些是基类:

class FirstBase(object):
      def __init__(self, detail_text=desc, backed_object=backed_object,
                   window=window, droppable_zone_obj=droppable_zone_obj,
                   bound_zone_obj=bound_zone_object,
                   on_drag_opacity=on_drag_opacity):
          # bla bla bla

class SecondBase(object):
      def __init__(self, size, texture, desc, backed_object, window):
          # bla bla bla

这就是孩子:

class Child(FirstBase, SecondBase):
       """ this contructor doesnt work
       def __init__(self, **kwargs):
          # PROBLEM HERE
          #super(Child, self).__init__(**kwargs)
       """
       #have to do it this TERRIBLE WAY
       def __init__(self, size=(0,0), texture=None, desc="", backed_object=None,
                    window=None, droppable_zone_obj=[], bound_zone_object=[],
                    on_drag_opacity=1.0):
          FirstBase.__init__(self, detail_text=desc, backed_object=backed_object,
                             window=window, droppable_zone_obj=droppable_zone_obj,
                             bound_zone_obj=bound_zone_object,
                             on_drag_opacity=on_drag_opacity)
          SecondBase.__init__(self, size, texture, desc, backed_object, window)

我想用**kwargs很好地解决这个问题,但是当我调用第一个注释掉的构造函数时,我得到了TypeError: __init__() got an unexpected keyword argument 'size'

有什么办法可以让它和**kwargs?一起工作吗


Tags: selfobjzoneobjectinitondefwindow
3条回答

因为FirstBase.__init__没有size参数。您可以添加size参数,也可以将**kwargs添加到FirstBase.__init__

您的问题是,您只尝试在子类中使用super

如果在基类中也使用super,那么这将起作用。每个构造函数将“吃掉”它所接受的关键字参数,而不是将它们传递给下一个构造函数。当调用object的构造函数时,如果有任何关键字参数遗留在它上面,它将引发异常。

class FirstBase(object):
    def __init__(self, detail_text=None, backed_object=None,
                 window=None, droppable_zone_obj=None,
                 bound_zone_obj=None, on_drag_opacity=None, **kwargs):
        super(FirstBase, self).__init__(**kwargs)

class SecondBase(object):
    def __init__(self, size=(0,0), texture=None, desc="",
                 backed_object=None, window=None, **kwargs):
        super(SecondBase, self).__init__(**kwargs)

class Child(FirstBase, SecondBase):
    def __init__(self, **kwargs):
        super(Child, self).__init__(**kwargs)

如您所见,它可以工作,除非您传递一个虚假的关键字参数:

>>> Child()
<__main__.Child object at 0x7f4aef413bd0>
>>> Child(detail_text="abc")
<__main__.Child object at 0x7f4aef413cd0>
>>> Child(bogus_kw=123)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "test.py", line 14, in __init__
    super(Child, self).__init__(**kwargs)
  File "test.py", line 5, in __init__
    super(FirstBase, self).__init__(**kwargs)
  File "test.py", line 10, in __init__
    super(SecondBase, self).__init__(**kwargs)
TypeError: object.__init__() takes no parameters

我不喜欢这个解决方案,但你可以这样做:

class FirstBase(object):
  def __init__(self, *args, **kargs):
      kargs.get('karg name', 'default value')
      # bla bla bla

class SecondBase(object):
  def __init__(self, *args, **kargs):
      kargs.get('karg name', 'default value')
      # bla bla bla

class Child(FirstBase, SecondBase):
   def __init__(self, *args, **kargs):
      FirstBase.__init__(self, *args, **kargs)
      SecondBase.__init__(self, *args, **kargs)

相关问题 更多 >