2015-03-06 3 views
1

Я хотел бы создать класс, у которого есть метод класса, возвращающий экземпляр класса, созданного с помощью любого из заранее определенных наборов значений по умолчанию, извлеченных из атрибута частного класса. Однако я нахожу, что если я создаю класс с атрибутом private class overriden, метод класса по-прежнему, кажется, использует версию родительского класса! Почему это происходит?Наследование атрибута метода класса

Вот MWE демонстрирует вопрос:

class MyCoolBeansClass: 

    __MyCoolBeansPrivateAttr = {'FizzBuzz': {'foo': 'Fizz', 'bar': 'Buzz'}, 
           'WimWam': {'foo': 'Wim', 'bar': 'Wam'}} 

    def __init__(self, foo, bar): 
     self.foo = foo 
     self.bar = bar 

    def __str__(self): 
     return 'foo: {foo}\tbar: {bar}'.format(foo=self.foo, bar=self.bar) 

    @classmethod 
    def specificBeanz(cls, cbtype, printclass=False): 
     """ Create a specific instance from a pre-determined set of instances """ 
     if printclass: 
      print("Class Name: " + cls.__name__) 

     if cbtype not in cls.__MyCoolBeansPrivateAttr.keys(): 
      raise ValueError('Invalid pre-determined Beanz, valid values are: ' + 
          ', '.join(cls.__MyCoolBeansPrivateAttr.keys())) 

     kwargs = cls.__MyCoolBeansPrivateAttr[cbtype] 
     return cls(**kwargs) 

class MyCubeGleamer(MyCoolBeansClass): 
    __MyCoolBeansPrivateAttr = {'GleamCube': {'foo': 'Gleam', 'bar': 'Cube'}, 
           'FogSnarl': {'foo': 'Fog', 'bar': 'Snarl'}} 

if __name__ == "__main__": 
    FizzBuzz = MyCoolBeansClass.specificBeanz('FizzBuzz', printclass=True) 
    print(FizzBuzz) 

    WimWam = MyCoolBeansClass.specificBeanz('WimWam', printclass=True) 
    print(WimWam) 

    GleamCube = MyCubeGleamer.specificBeanz('GleamCube', printclass=True) 
    print(GleamCube) 

Запуск этого дает:

> testinheritance.py 
Class Name: MyCoolBeansClass 
foo: Fizz  bar: Buzz 
Class Name: MyCoolBeansClass 
foo: Wim  bar: Wam 
Class Name: MyCubeGleamer 
----------------------------------------------------------------------------- 
Traceback (most recent call last): 
    File "testinheritance.py", line 37, in <module> 
    GleamCube = MyCubeGleamer.specificBeanz('GleamCube', printclass=True) 
    File "testinheritance.py", line 21, in specificBeanz 
    ', '.join(cls.__MyCoolBeansPrivateAttr.keys())) 
ValueError: Invalid pre-determined Beanz, valid values are: FizzBuzz, WimWam 
----------------------------------------------------------------------------- 

Как вы можете видеть, в MyCubeGleamer.specificBeanz() вызова, cls.__name__, кажется, работает правильно, но cls.__MyCoolBeansPrivateAttr является получение MyCoolBeansClass.__MyCoolBeansPrivateAttr.

ответ

3

Исправить. Двойные начальные подчеркивания замалчивают имя атрибута, чтобы предотвращал доступ к ним из числа. Они не, однако, фактически частные, поскольку в Python нет такой вещи, как «частный». Переключите имя атрибута на одно начальное подчеркивание.

+0

Это похоже на то, что происходит. Класс child получает доступ к частному атрибуту класса * parent * в методе класса, даже если он явно переопределен. Имейте в виду, это работает, но непонятно, почему. – Paul

+0

@Paul: 'specificBeanz()' определен в 'MyCoolBeansClass', поэтому это имя используется при изменении имени атрибута независимо от того, что может быть' cls'. –

+0

Hm. Это похоже на непонятный подход к обработке таких вещей, особенно когда я * явно * вызываю 'cls .__ theattr'. – Paul

Смежные вопросы