Search code examples
pythonsubclassparentattributeerror

Python: Subclass AttributeError


Python 3.5.2 I'm having some funny problem with my subclass, when trying to access parent field. There are three classes.(Command->Newarticle->Editarticle). The code is roughly like this, I've deleted additional methods, to minimize the code amount):

class Command(object):
    __metaclass__=abc.ABCMeta ;
    def __init__(self):
        # set default command name
        self.__name="I hate planes" ;
        self.__has_ended=False ;        

class Newarticle(Command):
    def __init__(self, modules):
        # parent init
        Command.__init__(self) ;
        self.__output=modules[MAIN_OUTPUT] ;
        self.__input=modules[MAIN_INPUT] ;

class Editarticle(Newarticle):
    def __init__(self, modules):
        Newarticle.__init__(self, modules) ;
        #super().__init__(modules) ;

        print(dir(self)) ;

        # ERROR HAPPENS HERE !
        self.__output.use_random_function() ;

I know for sure that there is MAIN_OUTPUT in modules, because Newarticle works perfectly. The error text: AttributeError: 'Editarticle' object has no attribute '_Editarticle__output'

The print out of 'dir' is: ['_Command__has_ended', '_Command__name', '_Editarticle__acc_data', '_Editarticle__art_id', '_Newarticle__art_images', '_Newarticle__art_name', '_Newarticle__art_text', '_Newarticle__db_mod', '_Newarticle__input', '_Newarticle__output', '_Newarticle__run_subcmds', '_Newarticle__tag_reader',...] and etc.

So the problem is clear, Python adds Class names before the methods, and is not trying even to look up in parent. So how do I fix it? I feel blind for not seeing where is the problem.

P.S. I've tried to call the 'super()', instead of 'Newarticle.init(self, modules)', absolutely same result. P.S.P.S. I've tried to remove the metaclass ABC from first parent('Command'), same error.


Solution

  • The problem is that you are using double underscore prefixes, which invokes name mangling. Don't do that. These are very rarely useful.

    Just use normal names for your attributes;

    def __init__(self):
        # set default command name
        self.name = "I hate planes"
        self.has_ended = False 
    

    (Also, please remove those semicolons. They are not used in Python.)