I'm new to Python, coming from C#. I know how to publicize class attributes and methods. I'd like to publicize my instance variables. Having intellisense detect them would be ideal. Also, please let me know if this is not pythonic or if I should be doing something else.
class MyClass(Object):
class_attribute = "Foo"
#This is the way I'm currently publicizing instance attributes.
#Basically I'm using properties instead of instance attributes.
#property
def instance_property(self):
return self._instance_property
#instance_property.setter
def instance_property_set(self, value):
self._instance_property = value
You are not required to do so. Python community uses a convention that any class member which name have:
leading underscore - considered private/protected,
double leading underscore considered class private - mimics private access by using name mangling. Member is not accessible by it's name outside the class, as it's prefixed with class name (but still accessible if you directly call it)
double leading underscore and double trailing underscore - overrides some behavior, closest C# analogue would be built-in interface implementations and overrides of Object methods. More info in the docs.
everything else considered public.
You can do properties, if you actually want to do some calculations upon acessing a member, but it's not considered/enforced as best practice.
class MyClass(Object):
class_attribute = "Foo"
def __init__(self,*args,**kwargs):
self.instance_property = "whatever"
often it(setting required values) is done in the init function ... or through documentation, or setting it to an invalid default value that you later check and inform consumer that they must set variable X before calling Calculate() or whatever ... getters and setters are not meant to inform a consumer what variables they should set
there is no reason to use getters/setters unless you actually need to do some work (not just pass it on to another variable)
a use case for a setter would be
class GPIO(object):
#property
def value(self):
return open("/sys/class/gpio/gpio141/value").read()
#value.setter
def set_value(self,val):
open("/sys/class/gpio/gpio141/value","w").write(val)
Related
How does the name mangling for a private class (class __ThisClass: pass) works, if we want to use the class inside a #staticmethod
I am able to access it with __class__ (The class to which a class instance belongs). However, is there a way to use a mangled name?
class PublicClass:
#staticmethod
def foo(n):
if n>10:
return n
return PublicClass.foo(100) # <---
pub_obj = PublicClass()
print(pub_obj.foo(1), pub_obj.foo(11))
output: 100 11
Here PublicClass.foo(100) can be used (or even __class__)
class __PrivateClass:
#staticmethod
def foo(n):
if n>10:
return n
return __class__.foo(100) # <---
pri_obj = __PrivateClass()
print(pri_obj.foo(1), pri_obj.foo(11))
output: 100 11
if we use __PrivateClass.foo(100) below exception is raised
class __PrivateClass:
#staticmethod
def foo(n):
if n>10:
return n
return __PrivateClass.foo(100) # <---
NameError: name '_PrivateClass__PrivateClass' is not defined
if we use _PrivateClass__PrivateClass.foo(100) below exception is raised (replace the line# <---)
NameError: name '_PrivateClass__PrivateClass' is not defined
Ask:
How does the name mangling works for a private class?
Should we (try to) never use the double underscore for the class name?
Note: Tried on Python 3.6.13 and Python 3.8.12
Answering first question, in python you can't actually enforce privacy, the point is that it's only suggestion to be private. The python convention says to sugest private method/class use an _ (underscore) and double __ (underscore) is pseudo privacy that won't allow you to call it directly but still will be possibility to workaround it. About your example it doesn't make sense to call __PrivateClass.foo(100) inside this class, better would be just use self.foo(100) and not making it static method.
Answering second question, using underscore for anything is only suggestion that it should be private you can still call it like in example below:
class __PrivateClass:
def foo(self, n):
if n>10:
return n
return self.foo(5)
print(__PrivateClass().foo(100))
at the end use underscore only if you want something to be called only inside it's scope as a suggestion, have it in mind you can still call it outside but you shouldn't, probably there was some reason why it's private.
As suggested in Python docs
This class object is the one that will be referenced by the zero-argument form of super(). __class__ is an implicit closure reference created by the compiler if any methods in a class body refer to either __class__ or super. This allows the zero argument form of super() to correctly identify the class being defined based on lexical scoping, while the class or instance that was used to make the current call is identified based on the first argument passed to the method.
When a name is not bound, an attempt to evaluate it raises a NameError exception.
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. If the transformed name is extremely long (longer than 255 characters), implementation defined truncation may happen. If the class name consists only of underscores, no transformation is done.
So whenever you are trying to call foo() method with __PrivateClass.foo() it automatically inserts the class name with it _PrivateClass__PrivateClass
But whenever you are using __class__, this is resolved to <class '__main__.__PrivateClass'> so we are not accessing attribute with class name instead we are accessing it as an object in current module.
Instead of using __class__ you can also access it like this:
import sys
class __PrivateClass:
#staticmethod
def foo(n):
if n>10:
return n
print(__class__)
print(getattr(sys.modules[__name__], '__PrivateClass'))
print(__class__ is getattr(sys.modules[__name__], '__PrivateClass')) # This will return True so you got it that __class__ is nothing but the current module and then __PrivateClass as its object
return __PrivateClass.foo(100) # <--- This line is raising exception because whenever we use __ inside class anywhere then that is transformed to **name_of_class_with_leading_underscore_stripped and single underscore appended** -> "_PrivateClass" and then double underscore and then the attribute name.
pri_obj = __PrivateClass()
print(pri_obj.foo(1), pri_obj.foo(11))
Also there is no such private class in python because when you insert double underscore in front of class then this will not affect any thing until you are not importing it somewhere
Also if you do the above thing using methods then also the same error will be there so there is nothing special to use staticmethod here
Let me know if this clears your doubt.
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.
I don't believe in calling the magic functions or properties directly from outside of the class because they are private to the class and it's not the caller's responsibility to know about them but I can't find the equivalent public functions/properties.
If I have a class:
class A:
def __init__(self):
pass
def B:
def __init__(self):
pass
my_classes = {'one':A(), 'two':B()}
As an instance, how do I call the
my_val = some_func(input)
instance_type = my_classes[my_val]
instance_type.__name__
I think you are confusing private functions/attributes with functions/attributes with double underscores before AND after the name. There is nothing wrong with accessing attributes with double underscores before and after the attribute. They are just labelled like that to avoid collisions, but it's legitimate to use, though something like __getattr__() probably doesn't make much sense to call outside of the class. But __name__ and __class__ are both okay to access.
I believe what you are thinking of is prefixing a function or attribute with double underscore. This will mangle the name and is not meant to be used/called outside the class. The difference is that they don't have a double underscore suffix.
class T():
def __priv(self):
pass
def __special__(self):
pass
__attr = None
print(dir(T()))
You should see _T__priv, _T__attr, and __special__. So the double underscore before AND after will not mangle. I'm not sure making your own __someattribute__ is the best idea, but the builtin ones for sure are available to you to use.
Assuming I have a class which requires a function (or should I say method) which is:
independent from my class instance - doesn't need self argument;
is called only inside my class object
I won't need access to it at any point (to override it for example);
should I (A) place it inside the class and mark it as a #staticmethod or should I (B) define it outside my class object (but in the same namespace)? Why?
Example:
class A:
def __init__(self, my_int):
self.my_int = my_int
def my_int_and_4(self):
print(self.adder(self.my_int,4))
#staticmethod
def adder(a,b):
return a+b
or
def adder(a,b):
return a+b
class B:
def __init__(self, my_int):
self.my_int = my_int
def my_int_and_4(self):
print(adder(self.my_int,4))
EDIT: maybe the example is a bit oversimplified. I should have added that my version of "adder" is specificly used with my class and in no other case.
This is a textbook use case for a private static method.
They key point here is that you should make it a private method of that class. That way you're certain nothing else will use it and depend on its implementation. You'll be free to change it in the future, or even delete it, without breaking anything outside that class.
And yeah, make it static, because you can.
In Python, there is no way to make a method truly private, but by convention, prefixing the method name by a _ means it should be treated as private.
#staticmethod
def _adder(a,b): ## <-- note the _
return a+b
If at some point you suddenly need to use it outside the class, then exposing it will be no trouble at all, e.g. using a public wrapper method.
The reverse, however, isn't true; once exposed, it's difficult to retract that exposure.
I would definitely use a private static method in this case, for the reasons described by Jean-Francois Corbett. There are two types of methods in Python that belong to the class itself, rather than an instance: class methods and static methods.
The first parameter of a class method (created with #classmethod) references the class in exactly the same manner that the first parameter of an instance method (self) references an instance. It is the equivalent of static methods in most other languages. If your method requires access to other class members, use a class method.
A static method (created with #staticmethod) does not contain a reference to the class, and therefore cannot reference other class members. It's generally used for private helper methods and the like.
For your adder method, I would definitely use a static method. However, in this modified (and rather useless) version, a class method is necessary:
class A:
x = 1
def __init__(self, my_int):
self.my_int = my_int
def my_int_and_4(self):
print(self._adder(self.my_int,4))
#staticmethod
def _adder(a,b):
return a+b
#classmethod
def _increment(cls, n):
return n + cls.x
Both approaches will work, so it's the matter of readability and following conventions.
Does the method need to look at the instance's private attributes? If yes, it's a good reason to keep it in the class.
Is the method only used as a helper for one of different methods? If yes, it's a good reason to put it right after the calling method so that the code can be read top-down.
Does the method seem to make sense outside of the context of your class? If yes, it's a good reason to make it a free function or even move it to a different file, like utils.
In Python, I have the following example class :
class Foo:
self._attr = 0
#property
def attr(self):
return self._attr
#attr.setter
def attr(self, value):
self._attr = value
#attr.deleter
def attr(self):
del self._attr
As you can see, I have a simple "private" attribute "_attr" and a property to access it. There is a lot of codes to declare a simple private attribute and I think that it's not respecting the "KISS" philosophy to declare all attributes like that.
So, why not declare all my attributes as public attributes if I don't need a particular getter/setter/deleter ?
My answer will be :
Because the principle of encapsulation (OOP) says otherwise!
What is the best way ?
Typically, Python code strives to adhere to the Uniform Access Principle. Specifically, the accepted approach is:
Expose your instance variables directly, allowing, for instance, foo.x = 0, not foo.set_x(0)
If you need to wrap the accesses inside methods, for whatever reason, use #property, which preserves the access semantics. That is, foo.x = 0 now invokes foo.set_x(0).
The main advantage to this approach is that the caller gets to do this:
foo.x += 1
even though the code might really be doing:
foo.set_x(foo.get_x() + 1)
The first statement is infinitely more readable. Yet, with properties, you can add (at the beginning, or later on) the access control you get with the second approach.
Note, too, that instance variables starting with a single underscore are conventionally private. That is, the underscore signals to other developers that you consider the value to be private, and they shouldn't mess with it directly; however, nothing in the language prevents them from messing with it directly.
If you use a double leading underscore (e.g., __x), Python does a little obfuscation of the name. The variable is still accessible from outside the class, via its obfuscated name, however. It's not truly private. It's just kind of ... more opaque. And there are valid arguments against using the double underscore; for one thing, it can make debugging more difficult.
The "dunder" (double underscore, __) prefix prevents access to attribute, except through accessors.
class Foo():
def __init__(self):
self.__attr = 0
#property
def attr(self):
return self.__attr
#attr.setter
def attr(self, value):
self.__attr = value
#attr.deleter
def attr(self):
del self.__attr
Some examples:
>>> f = Foo()
>>> f.__attr # Not directly accessible.
Traceback (most recent call last):
File "<input>", line 1, in <module>
AttributeError: 'Foo' object has no attribute '__attr'
>>> '__attr' in f.__dir__() # Not listed by __dir__()
False
>>> f.__getattribute__('__attr') # Not listed by __getattribute__()
Traceback (most recent call last):
File "<input>", line 1, in <module>
AttributeError: 'Foo' object has no attribute '__attr'
>>> f.attr # Accessible by implemented getter.
0
>>> f.attr = 'Presto' # Can be set by implemented setter.
>>> f.attr
'Presto'
>>> f.__attr = 'Tricky?' # Can we set it explicitly?
>>> f.attr # No. By doing that we have created a
'Presto' # new but unrelated attribute, same name.
However, you can access this type of attribute through name mangling (_classname__attribute), which Python does in the background:
>>> f._Foo__attr
0
>>> f.__getattribute__('_Foo__attr')
0
Quite simply, the OOP principles are wrong. Why this is is a long discussion which leads to flamewars and is probably off topic for this site. :-)
In Python there is not private attributes, you can't protect them, and this is never a real problem. So don't. Easy! :)
Then comes the question: Should you have a leading underscore or not. And in the example you have here you should definitely not. A leading underscore in Python is a convention to show that something is internal, and not a part of the API, and that you should use it on your own risk. This is obviously not the case here, but it's a common and useful convention.
Python doesn't have public OR private attributes. All attributes are accessible to all code.
self.attr = 0 #Done
Your method isn't in any way making _attr private, it's just a bit of obfuscation.
See this link:https://docs.python.org/2/tutorial/classes.html
9.6. Private Variables and Class-local References
“Private” instance variables that cannot be accessed except from inside an object don’t exist in Python. However, there is a convention that is followed by most Python code: a name prefixed with an underscore (e.g. _spam) should be treated as a non-public part of the API (whether it is a function, a method or a data member). It should be considered an implementation detail and subject to change without notice.
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.
As others have said, private attributes in Python are merely a convention. The use of property syntax should be used for special processing when attributes are bound, modified or deleted. The beauty of Python is that you can start off by just using normal attribute binding, e.g., self.attr = 0 and if at some later date you decide you want to restrict the value of attr to say 0 <= attr <=100, you can make attr a property and define a method to make sure this condition is true without ever having to change any user code.
To make an attribute private, you just have to do self.__attr
class Foo:
self.__attr = 0
#property
def attr(self):
return self._attr
#attr.setter
def attr(self, value):
self._attr = value
#attr.deleter
def attr(self):
del self._attr
In Python, unless you need special behavior out of an attribute, there's no need to hide it behind accessor methods. If an attribute is for internal use only, prepend it with an underscore.
The nice thing about properties is that they given you a really cool interface to work with. Sometimes it's handy to derive a property based on some other (ie. BMI is defined by weight and height). The user of the interface doesn't have to know this of course.
I prefer this way over having explicit getters and setters like in Java ie. Way nicer. :)