Как правильно сделать данные классов наследуемыми в python? - PullRequest
1 голос
/ 19 августа 2011

Я новичок в 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, поскольку прямой доступ к данным класса является обычным явлением и в основном поощряется из-за накладных расходов на вызовметод.У меня такое ощущение, что этот подход не очень питонен, но я хотел, чтобы проверка работоспособности была точной.

Если DataMap, хотя и неизменный после компиляции, находится в функции класса, где subClass1 получит эти данныечерез метод класса, когда наследование baseClass и subClass2 может переопределить тот же метод, чтобы добавить / объединить свою карту данных с базой?

Ваша проницательность и мудрость приветствуются.

Ответы [ 2 ]

2 голосов
/ 19 августа 2011

Если вы определяете:

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
2 голосов
/ 19 августа 2011

Как вы знаете, использование изменяемого объекта, такого как 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__ класса. Э.Г.

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

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

b = A()
print b.a
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...