Casing of class attributes in Python - python

I don't see a PEP 8 standard for the casing of class attributes in Python. I see occurrences of both lowercased and uppercased class attributes (e.g. pandas) and I'm wondering if there are formal standards anywhere.
class MyClass:
CLASS_SPECIFIC_CONSTANT = 1 # should the name of this attr be lowercased?

Related

Inheritance and Private attributes in Python

class Parent:
def __init__(self):
self._lst = []
class Child(Parent):
def __init__(self):
super().__init__()
Considering the code above, say I wanted to implement a method in the Child class, am I allowed to used self._lst (which is a private attribute initialized in the Parent Class) for this method? In other words, am I allowed to access private attributes that are initialized in the Parent Class through Subclasses?
In python, truly private attributes / methods don't exist. There are only naming conventions. What this means is if an attribute / method has its name beginning with one underscore, it can still be accessed from anywhere, just like regular attributes / methods. The only thing that this does is serve as a reminder to yourself and let other developers know that this attribute was not meant to be accessed from the outside.
To answer your question, yes, you can use _lst in the function. Even in languages that do have real access modifiers, there is frequently a different keyword to distinguish attributes not accessible from anywhere vs those that are not accessible anywhere but derived classes. In python, this is generally signified with a double underscore (__) vs a single underscore (_). Double underscores are not meant to be accessed from anywhere, while single underscores can be accessed by derived classes. See here for more information.

refer to own class in python class method when subclassing

I'm wanting to keep a class attribute on a base class which keeps track of all names of all its subclasses.
class SomeThing(abc.ABC):
subclass_names = set()
def __init_subclass__(cls):
cls.subclass_names.add(cls.__name__)
print(cls.subclass_names)
However, I'm afraid that because I'm creating an abstract class, users might overwrite the class attribute I am keeping.
class SomeSub(SomeThing):
subclass_names = set()
out: {'SomeSub'}
class SomeOtherSub(SomeThing):
pass
out: {'SomeOtherThing'} # should be {'SomeSub', 'SomeOtherThing'}
# but SomeOtherThing is registered in SomeOtherThing's, not SomeThing's subclass_names
Is there a way to refer to "own class" in a class method? It seems like the cls in __init_subclass__ ends up being whichever subclass is passed in (which makes sense).
Take advantage of name mangling:
class SomeThing(abc.ABC):
__subclass_names = set()
def __init_subclass__(cls):
cls.__subclass_names.add(cls.__name__)
print(cls.__subclass_names)
As the docs say:
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 means that subclasses of SomeThing won't accidentally override __subclass_names, since they will actually have to override _SomeThing__subclass_names instead.
Use a double-underscore to designate an attribute as private to a particular class. Python will "name-mangle" it behind the scenes to ensure that child classes can't accidentally override it.
import abc
class SomeThing(abc.ABC):
__subclass_names = set()
def __init_subclass__(cls):
SomeThing.__subclass_names.add(cls.__name__)
print(SomeThing.__subclass_names)
class SomeSub(SomeThing):
__subclass_names = set()
# {'SomeSub'}
class SomeOtherThing(SomeThing):
pass
# {'SomeOtherSub', 'SomeSub'}

Equivalent to private inheritance - Python [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

Inheritance of private and protected methods in Python

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

Significance and use of instance/class attributes with leading double underscores(special behaviour) [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What is the benefit of private name mangling in Python?
While I was playing with python, I found that if class or instance variable-name starts with 2 underscores, they will be renamed so as to be preceded by '_'.
eg
class Test(object):
__attribute = "dunderscored"
def __init__(self, value=0):
self.__instance_attribute = value
test_instance = Test()
then both the variables will be renamed to
test_instance._Test__attribute and test_instance._Test__instance_attribute
Why is there such a behaviour/feature? Is there any need of that, or any special use intended of that?
I can think of a use case that when different classes have some attribute with a generic name, eg. value, id, member in common, but for some function/method we are expecting/assuming only one of these classes. In this case there is a chance that type checking is not being done and when another class instance is passed to it(maybe by mistake) may result in errors and/or undesired behaviour.
But apart from this use case I don't see any benefit of this special behaviour. The behaviour looks like a feature, pretty fundamental one, and I feel like I am missing something here. If it's a feature what is the use of it? Any typical use case?
Use of prefixing double underscore is called name mangling: (from the Python docs):
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.
Note that single underscore prefix is used to indicate that the variable / function / class should be private (although that is not strictly enforced)
This feature is to help avoid name clashes with attributes when subclassing.
Consider the following:
class MyClass1(object):
def __init__(self):
self.__attribute = 3
def doSomething(self):
print(self.__attribute)
class MyClass2(MyClass1):
def __init__(self):
MyClass1.__init__(self)
self.__attribute = 4
def doSomething2(self):
print(self.__attribute)
Now if you create an instance:
x = MyClass2()
x.doSomething() #prints 3
x.doSomething2() #prints 4
This essentially can be used to separate some of the behavior of the parent class (MyClass) from the behavior of the child class (MyClass2)

Categories