Python Private Field … And JavaScript Ones

Photo by Vino Li on Unsplash

When I first started to learn python, I was confused about the naming conventions for the private fields. Since I have only very faint memory about it regarding JavaScript, I think it’s a good idea to compare them side to side(Well…since both languages are not as strict as Java).

Python

Several rules can be applied and adopted by the community:

Single Underscore: ._variable/method

This simply means that the variable or method should be be accessed from outside and is just for convention.

food.pyclass Food:
def __init__(self):
self.taste = "sweet"
self._weight = 500
>>> t = Food()
>>> t.tast
"sweet"
>>> t._weight
500

However, it will raise error when calling from wildcard import:

PEP-8:

_single_leading_underscore: weak “internal use” indicator. E.g. from M import * does not import objects whose name starts with an underscore.

Double Underscore: .__variable/method

This will make python interpreter modify the identifier to a different format to avoid accidental access and is enforced by the Python interpreter.

Any identifier of the form __spam (at least two leading underscores, at most one trailing underscore) is textually replaced with _classname__spam, where classname is the current class name with leading underscore(s) stripped. This mangling is done without regard to the syntactic position of the identifier, so it can be used to define class-private instance and class variables, methods, variables stored in globals, and even variables stored in instances. private to this class on instances of other classes.

Name mangling is intended to give classes an easy way to define “private” instance variables and methods, without having to worry about instance variables defined by derived classes, or mucking with instance variables by code outside the class.

Note that the mangling rules are designed mostly to avoid accidents; it still is possible for a determined soul to access or modify a variable that is considered private.

class Food(object):
def __init__(self):
self.__taste = 'sweet'
>>> t = Food()
>>> t.__taste
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Food' object has no attribute '__taste'

To access it (you have strong will!) :


>>> t._Food__taste
'sweet'

Double Underscore both sides: .__variable/method__

This means a method is reserved for python internal use like __init__ . They are often referred to as magic methods. You can actually write your own ones but try not to do that as it might cause unexpected behaviour.

Single Trailing Underscore on the right: .variable/method_

This is by convention to avoid naming conflicts with Python reserved keywords:

>>> def bread(self, class):
SyntaxError: "invalid syntax"

>>> def bread(self, class_):
... pass

Single Underscore: _

Sometimes used as a name for temporary or insignificant variables (“don’t care”). Also: The result of the last expression in a Python REPL.

>>> bread = ('bagel', 'toast', 'baguette', 'sourdough')
>>> a, _, _, d = bread

>>> a
'bagel'
>>> _
'baguette'

JavaScript:

So our property will be called _waterAmount:

class Food {
_bread= 'toast'
}
let food = new Food();food.bread; // Error
food._bread; //"toast"

However the good news is that in ES2019, private class fields are defined using a hash # prefix ( TC39 stage 3: draft proposal ) and it has been implemented in Babel.

class Food {
material= 'wholemeal';
#taste = 'sweet';
static #weight = 500;
bread() {
this.#taste;
}
}
let food = new Food();food.bread(); // runs OK
food.#taste; // error - private property cannot be modified outside class

Hola! That’s all.

Happy Reading!