11

I come from Java, so I'm getting confused here.

class Sample(object):
    x = 100                     # class var?
    def __init__(self, value):
        self.y = value          # instance var?
        z = 300                 # private var? how do we access this outside Sample?

What is the difference between the 3 variable declarations?

3
  • 2
    Duplicate, duplicate, duplicate... lots and lots of questions just like this, lots and lots of complete documentation. Commented Apr 11, 2012 at 13:15
  • 10
    @ChrisMorgan: if you're going to call duplicate, at least find the best of the duplicate answers and post a link here. Commented Apr 11, 2012 at 13:17
  • 1
    To pick a couple of examples which demonstrate all the points of this question: class and instance variables, private variables Commented Apr 11, 2012 at 13:31

3 Answers 3

35
class Sample(object):
    x = 100      
    _a = 1
    __b = 11               
    def __init__(self, value):
        self.y = value      
        self._c = 'private'    
        self.__d = 'more private'
        z = 300         

In this example:

  • x is class variable,
  • _a is private class variable (by naming convention),
  • __b is private class variable (mangled by interpreter),
  • y is instance variable,
  • _c is private instance variable (by naming convention),
  • __d is private instance variable (mangled by interpreter),
  • z is local variable within scope of __init__ method.

In case of single underscore in names, it's strictly a convention. It is still possible to access these variables. In case of double underscore names, they are mangled. It's still possible to circumvent that.

Sign up to request clarification or add additional context in comments.

10 Comments

The dunderscore is rarely used in Python, though. Usually just a single underscore is prepended to signal that the variable is meant for internal use.
I'm just saying that a lot of real-world Python code doesn't make use of this "enforcement", because it doesn't have a real advantage. And yes, you can easily access it anyway through self._Class__variable.
@vartec: enforced is a strong word here. It is really just name mangled.
Relevant quote from PEP 8: "Use one leading underscore only for non-public methods and instance variables. To avoid name clashes with subclasses, use two leading underscores to invoke Python's name mangling rules." It's not more private than the single underscore.
@John: No, dunderscore causes the interpreter to enable name mangling, please see the links. But they have the same intent: Marking the variable for internal use.
|
3

@vartec is spot on. Since you come from Java, however, some clarification is in order:

  • Java has public and private members. Access to private members is strictly forbidden, and this is enforced by the language.
  • Python only has public members. There is no way to enforce something like java's private keyword.

    If you want to declare that something is an implementation detail only and shouldn't be relied on by other code, you prefix it with a single underscore - _variable, _function(). This is a hint to other programmers that they shouldn't use that variable or that function, but it is not enforced.

    It might seem like a feature has been omitted from Python, but the culture in Python is "everyone is a consenting adult". If you tell other programmers that something is "private" by prefixing it with an underscore, they will generally take the hint.

7 Comments

Well, technically, you can make a true private, you just have to maim your class by overriding __setattr__() to throw an error any time an attempt is made to set the given value from outside the class itself. Of course, that is VERY un-Pythonic, but if you want to Javaize Python (and I've had a manager that forced us to do that at a previous job), you can make it happen.
@sr2222: I'm rocking backwards and forwards in the corner as we speak. Ugh.
@LiAungYip I do believe there's a PEP that says that is the correct response to such a practice.
@sr2222: You can also circumvent it, I bet.
"If it runs, it can be hacked."
|
1

You seem to be getting the hang of it. The only one that you were completely wrong about is z = 300. This is a name that is local to the __init__ method. Python never inserts self for you in the same manner that C++ and Java will assume this where it can.

One thing to remember as you continue learning Python is that member functions can always be executed as class members. Consider the following:

>>> class Sample(object):
...   def __init__(self, value):
...     self.value = value
...   def get_value(self):
...     return self.value
...
>>> s = Sample(1)
>>> t = Sample(2)
>>> s.get_value()
1
>>> Sample.get_value(s)
1
>>> t.__class__.get_value(s)
1

The last three examples all call the member function of the s object. The last two use the fact that get_value is just an attribute of the Sample class that expects to receive an instance of Sample as the argument.

2 Comments

thanks. i came across a article that said by creating a local variable of init method, is like a private var (like in Java). But i couldn't find a way to access z anywhere else.
also, i lost the link to that article. :(

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.