Bob Dylan
Bob Dylan

Reputation: 4453

Why can't I call a private method when I'm inside a public method?

I have the following code:

class MyClass:
    def __private(self):
        print "Hey man! This is private!"

    def public(self):
        __private()
        print "I don't care if you see this!"

if __name__ == '__main__':
    x = MyClass()
    x.public()

However it gives me the following error:

NameError: global name '_MyClass__private' is not defined

What am I doing wrong?

Upvotes: 6

Views: 5400

Answers (2)

Chris Pfohl
Chris Pfohl

Reputation: 19064

You need self:

self.__private()

Classes in python take getting used to if you're coming from C#/C++/Java, like it looks like you are. This is probably butchering the "pythonic" way of wording things, but you can think about it like this (it helped me out):

Each class defines a namespace defined from within itself as self and from without by the name of an instance of that class. "Private" things with two underscores get mangled so that from without you have to call it by a special name, but from within you can simply use self.__private().

As Joe mentioned in his comment normal private variables are typically just named with a single underscore, the double underscore mangles it so inheritance can work without name clashes in sub-classes. There's no enforcement of privacy in python, it's purely convention that says you can't use a private variable from outside the class.

As Thomas mentioned, self is also a convention. For any method (a function declared as part of a class) the instance that the method is being called on is the first parameter passed in. You could just as easily do this:

def __private(randomText):
    print "Hey man! This is private!"

def public(otherRandomText):
    otherRandomText.__private()
    print "I don't care if you see this!"

However, if you do that the spirits of logic and good programming style will haunt you and your descendants for all eternity. (self is much preferable).

Any pythonistas wish to correct/further-explain?

Upvotes: 22

AlG
AlG

Reputation: 15157

Your code as is is trying to call a static function MyCalls.__private, you want to do this:

class MyClass:
    def __private(self):
        print "Hey man! This is private!"

    def public(self):
        self.__private()
        print "I don't care if you see this!"

if __name__ == '__main__':
    x = MyClass()
    x.public()

Upvotes: 3

Related Questions