在python中使类数据可以继承的正确方法是什么?

时间:2011-08-19 15:11:24

标签: python oop class inheritance

我是Python的新手,来自Perl宇宙。

我正在尝试确定关于存储和访问类数据的最佳实践,以便它可以继承并可能由子类扩展。阅读Python 2.7文档(我真的坚持使用2.6),潜入Python和过去的问题,这个问题的答案并不清楚。

在python伪代码中就像......

class baseClass:
    'DataMap' = {
        'key1': 'val1',
        'key2': 'val2',
        'key3': 'val2',
    }

class subClass1(baseClass): # has access to DataMap
    def myfunc:
        ...
        if DataMap[x] == 'val2':
            print 'foo' # if x equals 'key2' according to the data map
        y = DataMap['key4'] # error!
        ...

class subClass2(baseClass): # appends values to base DataMap
    DataMap['key4'] = 'val4'
    def myfunc:
        ...
        if DataMap[x] == 'val4':
            print 'foo' # if x equals 'key4' according to the data map
        elif DataMap[x] == 'val2':
            print 'bar' # if x equals 'key2' according to the data map
        ...

我上面写的有些Perl意识到直接类数据访问很常见,并且由于调用方法的开销而受到鼓励。我觉得这种方法并不是非常pythonic,但我想要一个健全检查确定。

DataMap虽然一旦编译后仍然是不可变的,但它应该驻留在一个类函数中,当继承baseClass时,subClass1将通过类方法获取该数据,而subClass2可以覆盖相同的方法来附加/合并其数据映射与基类?

感谢您的见解和智慧。

2 个答案:

答案 0 :(得分:2)

您知道,使用像dict这样的可变对象作为默认参数,或者使用像__init__方法之类的方法,可能不会按照您认为的方式运行。

举个简单的例子:

class A(object):
    a = {'foo':1}

a = A()
a.a['bar'] = 2

b = A()
print b.a

现在,b.a{'foo': 1, 'bar': 2},即使您希望它只是{'foo':1}

出于这个原因,将可变数据放在类的__init__函数中是很常见的。 E.g。

class A(object):
    def __init__(self):
        self.a = {'foo':1}

a = A()
a.a['bar'] = 2

b = A()
print b.a

答案 1 :(得分:2)

如果你定义:

class baseClass:
    DataMap = {
        'key1': 'val1',
        'key2': 'val2',
        'key3': 'val2',
    }

然后baseClass.__dict__包含'DataMap': {'key3': 'val2', 'key2': 'val2', 'key1': 'val1'}

这使得DataMap无法涉及类继承,因为如果您稍后定义

class subClass2(baseClass): # appends values to base DataMap
    DataMap = {'key4':'val4'}

然后subClass2.__dict__有自己的竞争条目,密钥为'DataMap'。 如果s = subClass2()subClass2的实例,那么s.DataMap将仅访问DataMap中的subClass2.__dict__,并且在找到它后,将永远不会查看baseClass.__dict__ }。所以没有继承发生。

您可以修改baseClass.__dict__内的subClass2,但这会违反OOP原则,因为子类不应修改其父级。这不会是继承,因为对baseClass.__dict__的更改会影响baseClass的所有实例以及使用其DataMap的所有子类。


也许你可以通过继承DataMap本身来实现你想要的东西:

class DataMap(object):  
    key1='val1'
    key2='val2'
    key3='val2'

class subDataMap(DataMap):  
    key4='val4'

class baseClass(object):
    dataMap=DataMap

class subClass1(baseClass): 
    def myfunc(self,x):
        val=getattr(self.dataMap,x) 
        if val == 'val2':
            print 'foo' 

class subClass2(baseClass): 
    dataMap=subDataMap
    def myfunc(self,x):
        val=getattr(self.dataMap,x)
        if val == 'val4':
            print 'foo' 
        elif val == 'val2':
            print 'bar' 

s=subClass1()
s.myfunc('key2')
# foo
try:
    s.myfunc('key4')
except AttributeError as err:
    print(err)
    # subClass1 instance has no attribute 'key4'

s2=subClass2()
s2.myfunc('key2')
# bar
s2.myfunc('key4')
# foo