As others have noted, they use a language feature called descriptors.
The reason that the actual property object is returned when you access it via a class Foo.hello
lies in how the property implements the __get__(self, instance, owner)
special method:
- If a descriptor is accessed on an instance, then that instance is passed as the appropriate argument, and
owner
is the class of that instance. - When it is accessed through the class, then
instance
is None and onlyowner
is passed. Theproperty
object recognizes this and returnsself
.
Besides the Descriptors howto, see also the documentation on Implementing Descriptors and Invoking Descriptors in the Language Guide.