我是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可以覆盖相同的方法来附加/合并其数据映射与基类?
感谢您的见解和智慧。
答案 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