派生类的Python构造函数

4 投票
4 回答
12782 浏览
提问于 2025-04-17 06:21
class baseClass():
  def __init__(self,mark,name):
    self.mark = mark
    self.name = name

class derivedClass(baseClass):

b1 = derivedClass(name='Jibin')
print b1.name

这是我最开始的代码,运行得很好。

(注意:我没有权限访问 baseClass

但后来我需要给 derivedClass 传递一个额外的属性 rank,所以我把代码改成了这样。

class baseClass():
  def __init__(self,mark,name):
    self.mark = mark
    self.name = name

class derivedClass(baseClass):
  def __init__(self,rank):
    self.rank = rank 

b1 = derivedClass(name='Jibin')
print b1.name

这导致了一个错误 __init__() got an unexpected keyword argument 'name'

这个错误是可以预料的,因为 derivedClass__init__ 方法并没有 name 这个参数。

我不想在 derivedClass__init__ 方法中添加一个额外的 name 参数,因为实际上 baseClass 有十个参数,而不是两个(mark, name),如果我把所有这些都作为额外参数传给 derivedClass,那样会让参数列表变得很乱。

注意:我知道可以通过 baseClass.__init__(self)super(derivedClass, self).__init__() 来初始化 baseClass

4 个回答

0

这个博客讲述了如何解决这类问题。解决方法是让 basederived 在它们的 __init__ 方法中都接受一个 **kwargs 参数,并把这个参数传递给 super 的调用。

0

derivedClass 实际上并不是从 baseClass 继承来的。在 Python 中,要创建一个子类,你必须在类定义时指定父类,像这样:

class DerivedClass(BaseClass):
    pass

DerivedClass 现在可以使用 BaseClass 的方法,包括 __init__() 方法。如果你没有重写某个方法,那么在子类中调用这个方法时,实际上是调用了父类中定义的那个方法。

所以,如果你想让 DerivedClass(name='Jibin') 这样使用,你需要提供一个特别的 init():

class BaseClass(object):
    def __init__(self, mark, name):
        self.mark = mark
        self.name = name

class DerivedClass(BaseClass):
    def __init__(self, mark, name, rank):
        BaseClass.__init__(self, mark, name)
        self.rank = rank

现在,你还想让 DerivedClass() 支持额外的关键字参数,而不需要明确地添加它们。实现这个的一个方法是将所有的 kwargs 赋值给实例属性,像这样:

class BaseClass(object):
    def __init__(self, mark, name, **kwargs):
        self.mark = mark
        self.name = name
        self.__dict__.update(kwargs)

不过,我并不建议你真的这么做。盲目地设置属性可能会在将来引入一些微妙的错误(比如不小心用同名的关键字参数替换了一个方法)。

10

也许你可以试试这样的做法:

class BaseClass(object):
  def __init__(self, mark=None, name=None):   # you're using named parameters, declare them as named one.
    self.mark = mark
    self.name = name

class DerivedClass(BaseClass):   # don't forget to declare inheritance
  def __init__(self, rank=None, *args, **kwargs):    # in args, kwargs, there will be all parameters you don't care, but needed for baseClass
    super(DerivedClass, self).__init__(*args, **kwargs)
    self.rank = rank 

b1 = DerivedClass(name='Jibin')
print b1.name

撰写回答