I'm learning about encapsulation and abstraction in python and i came across the property function and decorator. The common example is something like this.
class Celsius():
def __init__(self, temperature = 0):
self.set_temperature(temperature)
def to_fahrenheit(self):
return (self._temperature * 1.8) 32
def get_temperature(self):
print("Getting value")
return self._temperature
def set_temperature(self, value):
if value < -273:
raise ValueError("Temperature below -273 is not possible")
print("Setting value")
self._temperature = value
temperature = property(get_temperature,set_temperature)
I dont understand why the property function is assigning the descriptor to temperature
and not self.temperature
. Isn't it suppouse to create a getter or setter functionality to a Instance, not to the class?
something like
self.temperature = property(get_temperature,set_temperature)
using
test = Celsius()
pprint(test.__dict__)
returns that the instance object just have the self._temperature
attribute (Which we are trying to make private).
using pprint(Celsius.__dict__)
returns that is actually the class that have the temperature attribute that we are accessing when using the objects, which to my understanding doesn't make sense since i am interested in creating functionality to the instance and access the instance atributes, not the class attributes.
Thanks in advance :)
CodePudding user response:
There's no self outside the method. This is defining a class attribute.
@Barmar has a helpful comment above.
The commonly used class function parameters self
and cls
are not available outside of class functions. In this case, you are defining a static member of the class. It is implied by default that vars (like your temperature =
) defined this way are static members of the class.
See some useful tips on static members here: Are static class variables possible in Python?
But why is the syntax like that. Isnt should be assigning the property to a instance variable?
Note the below. The behavior of class_static_var = 4
is similar to how someone may view cls.class_static_var = 4
, however it is not similar to self.instance_var = 4
. To define a instance var, you can use the __init__
method
class DemoClass:
def __init__(self):
self.instance_var = 3
class_static_var = 4
CodePudding user response:
You don't explain why you believe the descriptor has to be in the instance namespace, but looking at the documentation:
A descriptor is what we call any object that defines
__get__()
,__set__()
, or__delete__()
. ... Descriptors only work when used as class variables. When put in instances, they have no effect.
So, for property
to work at all, it must be a member of the class, not the instance.
If you have a descriptor, Descriptor
, and a class Foo
:
class Foo:
bar = Descriptor()
foo = Foo()
then the descriptor protocol will be invoked on either
Foo.bar
or
foo.bar
In any case, this is a good thing. There's no need for each instance to carry around a reference to the descriptor. Just like a method, it will belong to the class but instances have access to it.