我是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想到,直接类数据访问是常见的,并且由于调用方法的开销而受到大多数鼓励。我感觉这种方法虽然不是很Python,但是我想进行一次健全性检查。
DataMap是否应该驻留在一个类函数中,尽管该类一旦编译后就不会改变,那么当继承BaseClass和subClass2时,subClass1可以通过一个类方法获取该数据,而subClass2可以覆盖同一方法以将其datamap与base附加/合并。
感谢您的见解和智慧。
如果您定义:
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将仅访问subClass2.__dict__中的DataMap,并且在找到它时将永远不会在baseClass.__dict__中查找。因此不会发生继承。
您可以在subClass2中修改baseClass.__dict__,但这会违反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
我在示例中展示了一个DataMap,但实际上我正在查看出于各种目的应由所有对象共享的多个数据图。 我认为在我的"真实世界"中,这种解决方案会变得混乱吗?
@tima:是的; 它会变得凌乱。 在那种情况下,要使用类属性并获得继承的好处,我认为最好使DataMap成为一个类,并通过子类化DataMap将新的键值添加到数据映射中。
众所周知,将像dict这样的可变对象用作默认参数,或者在诸如__init__方法之类的东西之外使用行为,可能不会像您认为的那样起作用。
作为一个简单的例子:
class A(object):
a = {'foo':1}
a = A()
a.a['bar'] = 2
b = A()
print b.a
因此,即使您希望b.a只是{'foo':1},b.a还是{'foo': 1, 'bar': 2}
因此,通常将可变数据放入类的__init__函数中。例如。
class A(object):
def __init__(self):
self.a = {'foo':1}
a = A()
a.a['bar'] = 2
b = A()
print b.a
是的,您的第一个示例不像我想的那样有效。 我希望拥有该类的所有对象共享的不可变数据集。 第二个示例是为每个不必要的对象实例创建数据副本。