Я новичок в Python и я пришел из вселенной Perl.
Я пытаюсь определить, что лучше всего относится к хранению и доступу к данным класса, чтобы он мог наследоваться и потенциально расширяться подклассом. Чтение документов Python 2.7 (я застрял с использованием 2.6), Dive In на 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 в том, что прямой доступ к данным по данным является обычным явлением и в основном рекомендуется из-за накладных расходов на вызов метода. У меня возникает ощущение, что подход не очень питонический, но я хотел, чтобы проверка здравомыслия была уверенной.
Если DataMap, хотя и неизменяемый после компиляции, находится в функции класса, где subClass1 будет получать эти данные с помощью метода класса, когда наследование baseClass и subClass2 может переопределить тот же метод, чтобы добавить/объединить его datamap с базой?
Ваше понимание и мудрость оценены.
Просто, чтобы вы знали, использование измененного объекта, такого как dict в качестве аргумента по умолчанию, или за пределами чего-то вроде метода __init__
не может вести себя так, как вы думаете.
В качестве простого примера:
class A(object):
a = {'foo':1}
a = A()
a.a['bar'] = 2
b = A()
print b.a
Итак, теперь ba
является {'foo': 1, 'bar': 2}
, хотя вы ожидаете, что это будет просто {'foo':1}
По этой причине он обычно ставит изменяемые данные внутри функции класса __init__
. Например
class A(object):
def __init__(self):
self.a = {'foo':1}
a = A()
a.a['bar'] = 2
b = A()
print b.a
Если вы определяете:
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
, но это нарушит принципы ООП, поскольку дочерний класс не должен изменять родителя. И это не будет наследованием, так как изменения в 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
классом и добавить новые значения ключа в карту данных, DataMap
подкласс DataMap
.