Python:嵌套类继承
我可以在基类(也就是父类)中声明一个子类的实例吗?就像我在这里做的那样:
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 !
还有一些不相关的建议。
- 不要使用
x in dct.keys()
,在 python2.x 中效率非常低。你可以直接用x in dct
:-)。 - 一般来说,写像
getClassB
这样的简单包装函数被认为是不够“pythonic”的。你可以直接访问数据。 - 你可以重写
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