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?

John Eipe
  • 10,922
  • 24
  • 72
  • 114
  • 2
    Duplicate, duplicate, duplicate... lots and *lots* of questions just like this, lots and *lots* of complete documentation. – Chris Morgan Apr 11 '12 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. – Li-aung Yip Apr 11 '12 at 13:17
  • 1
    To pick a couple of examples which demonstrate all the points of this question: [class and instance variables](http://stackoverflow.com/questions/207000/python-difference-between-class-and-instance-attributes), [private variables](http://stackoverflow.com/questions/3294764/simulate-private-variables-in-python) – Chris Morgan Apr 11 '12 at 13:31

3 Answers3

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.

Li-aung Yip
  • 12,320
  • 5
  • 34
  • 49
vartec
  • 131,205
  • 36
  • 218
  • 244
  • 4
    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. – Niklas B. Apr 11 '12 at 13:09
  • @NiklasB.: single underscore is just indication, while double underscore is enforced by the interpreter. – vartec Apr 11 '12 at 13:10
  • 1
    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`. – Niklas B. Apr 11 '12 at 13:11
  • 3
    @vartec: _enforced_ is a strong word here. It is really just name mangled. – D.Shawley Apr 11 '12 at 13:12
  • 4
    Relevant quote from [PEP 8](http://www.python.org/dev/peps/pep-0008/#method-names-and-instance-variables): "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. – Niklas B. Apr 11 '12 at 13:16
  • @NiklasB: yeah, and in case of C++ you can access private members via C call to mangled function name. But what's the point? – vartec Apr 11 '12 at 13:28
  • just to confirm. Using _x and __x is same, both are treated the same way? – John Eipe Apr 11 '12 at 13:29
  • 2
    @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. – Niklas B. Apr 11 '12 at 13:30
  • @vartec: The point is that Python doesn't have *private* and that the dunderscore is usually not used (unless for implementing special Python methods like `__init__` or `__getattr__`). I think your update reflects the comments here in a sensible way :) – Niklas B. Apr 11 '12 at 13:31
  • btw. next line in PEP-8 says *"To avoid name clashes with subclasses, use two leading underscores to invoke Python's name mangling rules."* so it's more like __name -> private _name -> protected – vartec Apr 11 '12 at 13:38
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.

Li-aung Yip
  • 12,320
  • 5
  • 34
  • 49
  • 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. – Silas Ray Apr 11 '12 at 13:24
  • @sr2222: I'm rocking backwards and forwards in the corner as we speak. Ugh. – Li-aung Yip Apr 11 '12 at 13:25
  • 1
    @LiAungYip I do believe there's a PEP that says that is the correct response to such a practice. – Silas Ray Apr 11 '12 at 13:28
  • @sr2222: You can also circumvent it, I bet. – Niklas B. Apr 11 '12 at 13:35
  • "If it runs, it can be hacked." – Li-aung Yip Apr 11 '12 at 13:36
  • It is trivial to circumvent. Either 1) Use the __dict__ directly: "obj.__dict__[name] = value" or 2) If it has a base class, use its __setattr__ "base.__setattr__(obj, name, value)" or 3) patch __setattr__ on your object "obj.__setattr__ = newfun" or if you are desperate 4) do unholy things directly with the ast module. – Gurgeh Apr 11 '12 at 14:03
  • @Gurgeh: You bring the black candles, sr2222 can bring the chalk for the pentagram, and I'll bring the sacrificial goat. – Li-aung Yip Apr 11 '12 at 15:28
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.

D.Shawley
  • 58,213
  • 10
  • 98
  • 113
  • 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. – John Eipe Apr 11 '12 at 13:23
  • also, i lost the link to that article. :( – John Eipe Apr 11 '12 at 13:25