0

I am trying to change a public to private parameter inside a Python class. As far as I know, to make it private I need to declare for instance:

self.__top = None # <-- Instead of self.top = None

However, I cannot figure out how to make a private struct with private properties, such that they are called properly in the public methods.

For instance:

class Stack:

    def __init__(self, size=None):
        self.__top = None
        if size is None:  # if size is unset
            self.__size = -1
        else:
            self.__size = size
        self.__current_size = -1

    def push(self, data):
        if self.current_size >= self.size: # ERROR!
            print("Stack Overflow!")
            return
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
NiRvanA
  • 105
  • 1
  • 1
  • 8
  • 1
    If you create an attribute `self.__size`, then it is `self.__size`, not `self.size`. The underscores are part of the name. – khelwood Apr 04 '19 at 21:55
  • 1
    **Python does not have private attributes**. You are using double-underscore name-mangling, which is not the same thing as *private*. By convention, members that are not part of the public api are *prepended with a single underscore*. This is merely a *naming convention*. Double-underscore name-mangling is to prevent name-collisions in *subclasses*. – juanpa.arrivillaga Apr 04 '19 at 21:59

1 Answers1

4

I'm assuming that by using terms such as struct, public and private you must come from a background of C/C++. There are no such things in Python, and the naming of the attributes are purely conventional.

I recommend reading What is the meaning of a single and a double underscore before an object name?.

Typically for your "private" attributes which you don't want for others to use outside of your class, the convention is to prefix it with a single underscore _, like _size. If you plan on using this outside, it boils down to these cases:

  • do you want it to be writable from outside? In that case you just define it as size and use it like this everywhere
  • do you want it to be read-only from outside? In this case you can make it private and make a property for it like:

Code:

class A:

    self __init__(self, size):
        self._size = size

    @property
    def size(self):
        return self._size

You also have the ability to translate the internal variable to another name, and make it writable at the same time under that different name.

Example:

class A:

    def __init__(self, value):
        self._internal_var = value

    def set_data(self, value):
        self._internal_var = value

    def get_data(self):
        return self._internal_var

    data = property(get_data, set_data)

Or alternatively:

@property
def data(self):
    return self._internal_var

@data.setter
def data(self, value):
    self._internal_var = value

Then if you call

a1 = A(11)
print(a1.data)
a1.data = 22
print(a1.data)

it will yield:

11
22
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
andreihondrari
  • 5,743
  • 5
  • 30
  • 59