Как правильно сделать данные классов наследуемыми в python?

1

Я новичок в 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 с базой?

Ваше понимание и мудрость оценены.

Теги:
class
oop
inheritance

2 ответа

2

Просто, чтобы вы знали, использование измененного объекта, такого как 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
  • 0
    Да, ваш первый пример не работает, как я думал. Я хочу иметь неизменные наборы данных, которые используются всеми объектами этого класса. Ваш второй пример - создание копии данных для каждого экземпляра объекта, в котором нет необходимости.
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, но это нарушит принципы ООП, поскольку дочерний класс не должен изменять родителя. И это не будет наследованием, так как изменения в 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
  • 1
    В моем примере я показал одну карту данных, но в действительности я смотрю на несколько карт данных для различных целей, которые должны использоваться всеми объектами. Я думаю, что это решение будет грязным под моим "реальным миром" правильно?
  • 0
    @tima: правда; было бы грязно. В этом случае, чтобы использовать атрибуты класса, а также получить преимущество наследования, я думаю, что было бы лучше сделать DataMap классом и добавить новые значения ключа в карту данных, DataMap подкласс DataMap .

Ещё вопросы

Сообщество Overcoder
Наверх
Меню