Why is changing class variables considered a bad practice? [duplicate] - python

I would like to have a function in my class, which I am going to use only inside methods of this class. I will not call it outside the implementations of these methods. In C++, I would use a method declared in the private section of the class. What is the best way to implement such a function in Python?
I am thinking of using a static decorator for this case. Can I use a function without any decorators and the self word?

Python doesn't have the concept of private methods or attributes. It's all about how you implement your class. But you can use pseudo-private variables (name mangling); any variable preceded by __(two underscores) becomes a pseudo-private variable.
From the documentation:
Since there is a valid use-case for class-private members (namely to
avoid name clashes of names with names defined by subclasses), there
is limited support for such a mechanism, called name mangling. 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, as long as it occurs
within the definition of a class.
class A:
def __private(self):
pass
So __private now actually becomes _A__private.
Example of a static method:
>>> class A:
... #staticmethod # Not required in Python 3.x
... def __private():
... print 'hello'
...
>>> A._A__private()
hello

Python doesn't have the concept of 'private' the way many other languages do. It is built on the consenting adult principle that says that users of your code will use it responsibly. By convention, attributes starting with a single or double leading underscore will be treated as part of the internal implementation, but they are not actually hidden from users. Double underscore will cause name mangling of the attribute name though.
Also, note that self is only special by convention, not by any feature of the language. Instance methods, when called as members of an instance, are implicitly passed the instance as a first argument, but in the implementation of the method itself, that argument can technically be named any arbitrary thing you want. self is just the convention for ease of understanding code. As a result, not including self in the signature of a method has no actual functional effect other than causing the implicit instance argument to be assigned to the next variable name in the signature.
This is of course different for class methods, which receive the instance of the class object itself as an implicit first argument, and static methods, which receive no implicit arguments at all.

Python just doesn't do private. If you like you can follow convention and precede the name with a single underscore, but it's up to other coders to respect that in a gentlemanly† fashion
† or gentlewomanly

There is plenty of great stuff here with obfuscation using leading underscores. Personally, I benefit greatly from the language design decision to make everything public as it reduces the time it takes to understand and use new modules.
However, if you're determined to implement private attributes/methods and you're willing to be unpythonic, you could do something along the lines of:
from pprint import pprint
# CamelCase because it 'acts' like a class
def SneakyCounter():
class SneakyCounterInternal(object):
def __init__(self):
self.counter = 0
def add_two(self):
self.increment()
self.increment()
def increment(self):
self.counter += 1
def reset(self):
print 'count prior to reset: {}'.format(self.counter)
self.counter = 0
sneaky_counter = SneakyCounterInternal()
class SneakyCounterExternal(object):
def add_two(self):
sneaky_counter.add_two()
def reset(self):
sneaky_counter.reset()
return SneakyCounterExternal()
# counter attribute is not accessible from out here
sneaky_counter = SneakyCounter()
sneaky_counter.add_two()
sneaky_counter.add_two()
sneaky_counter.reset()
# `increment` and `counter` not exposed (AFAIK)
pprint(dir(sneaky_counter))
It is hard to imagine a case where you'd want to do this, but it is possible.

You just don't do it:
The Pythonic way is to not document those methods/members using docstrings, only with "real" code comments. And the convention is to append a single or a double underscore to them;
Then you can use double underscores in front of your member, so they are made local to the class (it's mostly name mangling, i.e., the real name of the member outside of the class becomes: instance.__classname_membername). It's useful to avoid conflicts when using inheritance, or create a "private space" between children of a class.
As far as I can tell, it is possible to "hide" variables using metaclasses, but that violates the whole philosophy of Python, so I won't go into details about that.

Related

Why doesn't overloading a method work in this Python example? [duplicate]

Consider a class with a "private" method such as:
class Foo(object):
def __init__(self):
self.__method()
def __method(self):
print('42')
When I try to subclass Foo and override method __method, it can be seen that Foo.__method is still called, instead of MoreFoo.__method.
class MoreFoo(Foo):
def __method(self):
print('41')
>>> MoreFoo()
42
<__main__.MoreFoo object at 0x7fb726197d90>
What would be the way to override such a method?
The point of using the double-underscore name convention is to prevent subclasses from (accidentally) overriding the method.
If you have to override it anyway, someone made a serious class design error. You can do it still, by naming your object just so:
def _Foo__method(self):
where you prefix the method name with one more underscore and the defining classname (so in this case prefixed with _Foo). The process of renaming methods and attributes with a double underscore is called private name mangling.
If you want to define a 'private' method that is still overridable in a subclass, you generally stick to names with one underscore instead (def _method(self):).
Due to its dynamic nature, almost nothing in Python is truly private; with a little introspection almost anything can be reached.
A double underscore prefix invokes name mangling. It is not equivalent to a private method and is specifically designed to avoid being overridden by subclasses (and in this case, the method name becomes _Foo__method).
If you have an implementation detail, prefix it with a single underscore. This is the universally accepted sign for Python methods that are not to be used externally. There is no enforcement of this, because that's not the way Python functions.
I believe that you would do something like:
class MoreFoo(Foo):
def _Foo__method(self):
print('41')
as documented.
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.
But the designers of the original class were of the opinion that you shouldn't need to do something like this as making it difficult to override with subclassing is the whole point of the double underscores to begin with:
Name mangling is helpful for letting subclasses override methods without breaking intraclass method calls.

single underscore vs double underscore encapsulation in python

I see that with help of underscore, one can declare private members in class but with one score, it is still accessed in main but with two it is not. If two makes the variable private then why there is single score one? What is the use/purpose of single underscore variable?
class Temp:
def __init__(self):
self.a = 123
self._b = 123
self.__c = 123
obj = Temp()
print(obj.a)
print(obj._b)
print(obj.__c)
Here's why that's the "standard," a little different from other languages.
No underscore indicates it's a public thing that users of that class can touch/modify/use
One underscore is more of an implementation detail that usually (note the term usually) should only be referenced/used in sub-classes or if you know what you're doing. The beautiful thing about python is that we're all adults here and if someone wants to access something for some really custom thing then they should be able to.
Two underscores is name mangled to include the classname like so _Temp__c behind the scenes to prevent your variables clashing with a subclass. However, I would stay away from defaulting to two because it's not a great habit and is generally unnecessary. There are arguments and other posts about it that you can read up on like this
Note: there is no difference to variables/methods that either have an underscore or not. It's just a convention for classes that's not enforced but rather accepted by the community to be private.
Note #2: There is an exception described by Matthias for non-class methods
In Python, there is no existence of “private” instance variables that cannot be accessed except inside an object.
However, a convention is being followed by most Python code and coders i.e., a name prefixed with an underscore, For e.g. _xyz should be treated as a non-public part of the API or any Python code, whether it is a function, a method, or a data member

Calling base class method in Python [bis] [duplicate]

I know, there are no 'real' private/protected methods in Python. This approach isn't meant to hide anything; I just want to understand what Python does.
class Parent(object):
def _protected(self):
pass
def __private(self):
pass
class Child(Parent):
def foo(self):
self._protected() # This works
def bar(self):
self.__private() # This doesn't work, I get a AttributeError:
# 'Child' object has no attribute '_Child__private'
So, does this behaviour mean, that 'protected' methods will be inherited but 'private' won't at all?
Or did I miss anything?
Python has no privacy model, there are no access modifiers like in C++, C# or Java. There are no truly 'protected' or 'private' attributes.
Names with a leading double underscore and no trailing double underscore are mangled to protect them from clashes when inherited. Subclasses can define their own __private() method and these will not interfere with the same name on the parent class. Such names are considered class private; they are still accessible from outside the class but are far less likely to accidentally clash.
Mangling is done by prepending any such name with an extra underscore and the class name (regardless of how the name is used or if it exists), effectively giving them a namespace. In the Parent class, any __private identifier is replaced (at compilation time) by the name _Parent__private, while in the Child class the identifier is replaced by _Child__private, everywhere in the class definition.
The following will work:
class Child(Parent):
def foo(self):
self._protected()
def bar(self):
self._Parent__private()
See Reserved classes of identifiers in the lexical analysis documentation:
__*
Class-private names. Names in this category, when used within the context of a class definition, are re-written to use a mangled form to help avoid name clashes between “private” attributes of base and derived classes.
and the referenced documentation on names:
Private name mangling: When an identifier that textually occurs in a class definition begins with two or more underscore characters and does not end in two or more underscores, it is considered a private name of that class. Private names are transformed to a longer form before code is generated for them. The transformation inserts the class name, with leading underscores removed and a single underscore inserted, in front of the name. For example, the identifier __spam occurring in a class named Ham will be transformed to _Ham__spam. This transformation is independent of the syntactical context in which the identifier is used.
Don't use class-private names unless you specifically want to avoid having to tell developers that want to subclass your class that they can't use certain names or risk breaking your class. Outside of published frameworks and libraries, there is little use for this feature.
The PEP 8 Python Style Guide has this to say about private name mangling:
If your class is intended to be subclassed, and you have attributes
that you do not want subclasses to use, consider naming them with
double leading underscores and no trailing underscores. This invokes
Python's name mangling algorithm, where the name of the class is
mangled into the attribute name. This helps avoid attribute name
collisions should subclasses inadvertently contain attributes with the
same name.
Note 1: Note that only the simple class name is used in the mangled
name, so if a subclass chooses both the same class name and attribute
name, you can still get name collisions.
Note 2: Name mangling can make certain uses, such as debugging and
__getattr__(), less convenient. However the name mangling algorithm
is well documented and easy to perform manually.
Note 3: Not everyone likes name mangling. Try to balance the need to
avoid accidental name clashes with potential use by advanced callers.
The double __ attribute is changed to _ClassName__method_name which makes it more private than the semantic privacy implied by _method_name.
You can technically still get at it if you'd really like to, but presumably no one is going to do that, so for maintenance of code abstraction reasons, the method might as well be private at that point.
class Parent(object):
def _protected(self):
pass
def __private(self):
print("Is it really private?")
class Child(Parent):
def foo(self):
self._protected()
def bar(self):
self.__private()
c = Child()
c._Parent__private()
This has the additional upside (or some would say primary upside) of allowing a method to not collide with child class method names.
By declaring your data member private :
__private()
you simply can't access it from outside the class
Python supports a technique called name mangling.
This feature turns class member prefixed with two underscores into:
_className.memberName
if you want to access it from Child() you can use: self._Parent__private()
Also PEP8 says
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.
Python mangles these names with the class name: if class Foo has an
attribute named __a, it cannot be accessed by Foo.__a. (An insistent
user could still gain access by calling Foo._Foo__a.) Generally,
double leading underscores should be used only to avoid name conflicts
with attributes in classes designed to be subclassed.
You should stay away from _such_methods too, by convention. I mean you should treat them as private
Although this is an old question, I encountered it and found a nice workaround.
In the case you name mangled on the parent class because you wanted to mimic a protected function, but still wanted to access the function in an easy manner on the child class.
parent_class_private_func_list = [func for func in dir(Child) if func.startswith ('_Parent__')]
for parent_private_func in parent_class_private_func_list:
setattr(self, parent_private_func.replace("_Parent__", "_Child"), getattr(self, parent_private_func))
The idea is manually replacing the parents function name into one fitting to the current namespace.
After adding this in the init function of the child class, you can call the function in an easy manner.
self.__private()
AFAIK, in the second case Python perform "name mangling", so the name of the __private method of the parent class is really:
_Parent__private
And you cannot use it in child in this form neither

epydoc hide some class functions?

I have some methods in my class which are only meant to be used by other methods of the class. I've prefixed their names with '_'. Can I hide those functions from epydoc? Is it a good idea?
Should I use '_' or double underscore? To be honest I didn't get the difference after reading about them in some places. Should this naming convention be used only on module/class (instance) functions? Or also variables?
If you want to hide all private methods and private variables, pass option '--no-private' to epydoc.
Note that - for epydoc - a method or variable is private if:
its name starts with an underscore '_' and
its name does not end with an underscore '_' and
you did not include its name in the special all dictionary.
Alternatively you can use the 'undocumented' tag to force epydoc to completely ignore certain methods or variables.
For instance (and here I assume a ReStructured Text kind of formatting):
class MyClass:
"""Some neat description
:undocumented: x
"""
def _y(self): pass
def x(self): pass
def z(self): pass
will result in the documentation to contain only _y (unless you used the '--no-private' option) and z. There will be nothing about x even if it is not private.
Whether private methods should be visible at all or not in the final documentation is a matter of taste. To me, documentation is read by people who don't or should not have any interest in the internal implementation. Private methods are best hidden completely.

How do you call a private module function from inside a class?

I have a module that looks something like this:
def __myFunc():
...
class MyClass(object):
def __init__(self):
self.myVar = __myFunc()
and I get the error:
NameError: global name '_MyClass__myFunc' is not defined
How can I call this function from inside the class?
edit: Since posting this, I've discovered I can avoid the automatic mangling by using a single underscore instead of double underscores. I was using two as per "Dive Into Python", which only states a double underscore denotes private functions.
That is because Python's compiler replaces method calls (and attribute accesses) inside classes if the name begins with two underscores. Seems like this also applies to functions. A call to a method self.__X would be replaced by self._ClassName__X, for example. This makes it possible to have pseudo-private attributes and methods.
There is absolutely no reason to use two underscores for functions inside the module. Programmers often follow the convention of putting one underscore in front of the function name if the function shouldn't be called from outside.
Using two underscores is only necessary for attributes/methods in classes if you don't want them to be overwritten by subclasses, for example. But there are few cases in which that is useful.

Categories

Resources