views:

57

answers:

3

in school we got this class file:

class Konto:
    def __init__(self, nummer):
        self.__nr = nummer
        self.__stand = 0
        self.__minimum = -1000.0

    def getStand(self):
        return self.__stand

    def getNr(self):
        return self.__nr

    def einzahlen(self, betrag):
        self.__stand = self.__stand + betrag

    def auszahlen(self, betrag):
        if self.__stand - betrag >= self.__minimum:
            self.__stand = self.__stand - betrag
        else:
            print("Auszahlung nicht möglich!")

class Sparkonto(Konto):
    def __init__(self, nummer):
        Konto.__init__(self, nummer)
        self.__zinssatz = None
        self.__minimum = 0
        self.__maxAuszahlung = 2000.0

    def setZinssatz(self, zinssatz):
        self.__zinssatz = zinssatz

    def getZinssatz(self):
        return self.__zinssatz

    def auszahlen(self, betrag):
        if betrag <= self.__maxAuszahlung:
            Konto.auszahlen(self, betrag)
        else:
            print("Auszahlung nicht möglich!")

    def zinsenGutschreiben(self):
        zinsen = self.__stand * (self.__zinssatz / 100)
        self.einzahlen(zinsen)

When I run this test programm:

#Test
from sparkonto import *
s = Sparkonto(1)
s.einzahlen(1000)
print(s.getStand())
s.setZinssatz(4)
print(s.getZinssatz())
s.zinsenGutschreiben()
print(s.getStand())
s.auszahlen(2500)
print(s.getStand())

I get this error

1000
4
Traceback (most recent call last):
  File "/home/malte/home/py3/sparkonto/test.py", line 8, in <module>
    s.zinsenGutschreiben()
  File "/home/malte/home/py3/sparkonto/sparkonto.py", line 44, in zinsenGutschreiben
AttributeError: 'Sparkonto' object has no attribute '_Sparkonto__einzahlen'
>>> 

We do not know what we are doing wrong. Any guess?

+1  A: 

self.__einzahlen(zinsen) -> self.einzahlen(zinsen)

Daniel Băluţă
No​, not this​.
Ignacio Vazquez-Abrams
why not? __einzahlen function is not defined in base class.
Daniel Băluţă
no it is privat
Malte Schledjewski
@Malte: There is no such thing as "private" in Python.
Ignacio Vazquez-Abrams
we learned that leading double underscore means private but i often don't think that my teacher knows how python works
Malte Schledjewski
Leading double underscores does *not* mean private. There is *no such thing* as "private" in Python.
Ignacio Vazquez-Abrams
+1  A: 

Double leading underscores invoke name mangling, using the current class's name. Use a single leading underscore instead.

Ignacio Vazquez-Abrams
+2  A: 

Daniel was halfway there, you do need to change self.__einzahlen -> self.einzaheln, as he said.

Also, self.__stand belongs to the parent class. With the double underscore in the name, it gets mangled used anywhere else. But you don't need to use self.__stand directly. Konto gives you getStand().

Try something like this:

def zinsenGutschreiben(self):
    zinsen = self.getStand() * (self.__zinssatz / 100)
    self.einzahlen(zinsen)
otherchirps
just to be sure that I've understood. If you prefix your variable names with '__' than your variable cannot be accessed from derived classes? It's like private in C++?
Daniel Băluţă
yeah, that solved it
Malte Schledjewski
@daniel: yes i think so
Malte Schledjewski
@Daniel, not quite, the name of the attribute is mangled to eg. `_Konto__stand` and is perfectly accessable under that name. It does ensure that a subclass doesn't accidently overwrite that name.
gnibbler
It *can* be accessed, but with a double underscore, the name is mangled when used from the derived classes. It's just a convention, giving you a hint that the author wants to treat it as "private". In this case, you could have also used "self._Konto__stand", but why bother when there's an "official" getStand() function?
otherchirps
@gnibbler: thanks
Daniel Băluţă