class a_class():
_x = []
@property
def x(self):
return a_class._x
ac1 = a_class()
print(a_class.x)
print(ac1.x)
Why does the first print return a property object, while the second print returns the list object?
Accessing the property on the class won't call it; it's only called on instances. If it were to be called on classes, it would break method lookup, because method lookup reads attributes from the class of an instance, not from the instance itself.
class cls:
@property
def attr(self):
print('Property was called')
cls.attr # doesn't output anything, and evaluates to the property
cls().attr # calls the property, outputting the string
When an attribute is looked up on an object (class instance) obj
, Python will do the following:
type(obj).__getattribute__(obj,attr)
/type(obj).__getattr__(obj,attr)
where attr
is the string name of the attribute (assuming the attribute exists, we only need to worry about the latter).__get__
method), then those methods will call the type(descriptor).__get__(descriptor)
, and return that value as the attribute's value.Objects of type property
define the __get__
method, and are therefore descriptors. For properties specifically, they will call their wrapped function. Therefore, when they are looked up on an instance, that __get__
method will call the wrapped function. Equally, it won't get called when it's looked up on the class.
I hope this helps!