Python:嵌套类继承

0 投票
1 回答
617 浏览
提问于 2025-04-18 01:15

我可以在基类(也就是父类)中声明一个子类的实例吗?就像我在这里做的那样:

if 'classB_args' in dictArg.keys() and dictArg['classB_args']:
    self['classB']=ClassA( dictArg['classB_args'] )

这样做会有什么副作用吗?在继续之前我需要注意些什么?我有种感觉,迟早会出问题……可能是和cPickle、pickle有关,或者可能是PyQt的拖放功能?如果是这样的话,问题为什么会出现呢?

class Base(dict):
    def __init__(self, *args, **kwargs):
        super(Base, self).__init__(*args, **kwargs)
        self.setdefault('id', -1)
        self.setdefault('name', None)
        self.setdefault('classB', None)

        if not args or len(args)==0: return
        dictArg=args[0]

        if 'classB_args' in dictArg.keys() and dictArg['classB_args']:
            self['classB']=ClassA( dictArg['classB_args'] )

    def getClassB(self):
        return self['classB']

class ClassA(Base):
    def __init__(self, *args, **kwargs):
        if not (args or kwargs):   raise Exception('you need to give me *something*!')
        super(ClassA, self).__init__(*args, **kwargs)
        self.setdefault('win', None)
        self.setdefault('mac', None)

myDictArg= {'id':1, 'name':'MyName', 'win':'c:/windows', 'mac': '/Volumes/mac/', 'classB_args': {'id':1, 'name':'MyProject'}}

myInstance=ClassA(myDictArg)
print myInstance.getClassB()

1 个回答

1

如果你在问这个方法是否可行,答案是可以,但我想不出有什么情况适合这样做。原因是,这样会让你的基类只能和 ClassA 一起使用,限制了它的灵活性。我觉得更好的解决方案是这样做:

myDictArg = {'id':1, 'name':'MyName', 'win':'c:/windows', 'mac': '/Volumes/mac/', 'classB': ClassA(id=1, name='MyProject')}

这样可以避免在 Base.__init__ 中搞一些复杂的 classB_args。这样写更清晰,用户也能更好地知道会发生什么。

如果你真的不喜欢这样,你可以用 self 的类型来决定使用什么,而不是直接指定 ClassA,这样会稍微好一点:

self['classB'] = type(self)(dictArg['classB_args'])

现在,如果你从 Base 派生一个新类,它会被用到:

class Foo(Base): pass

instance = Foo(myDictArg)
print type(instance.getClassB())  # Foo !

还有一些不相关的建议。

  1. 不要使用 x in dct.keys(),在 python2.x 中效率非常低。你可以直接用 x in dct :-)。
  2. 一般来说,写像 getClassB 这样的简单包装函数被认为是不够“pythonic”的。你可以直接访问数据。
  3. 你可以重写 if 语句,让它更简洁:

具体做法是:

   if 'classB_args' in dictArg.keys() and dictArg['classB_args']:
        self['classB']=ClassA( dictArg['classB_args'] )

可以改成:

   # with this, you can remove the `self.setdefault('classB', None)` statement.
   item = dictArg.get('classB_args')
   self['classB'] = type(self)(item) if item else item

撰写回答