What is a property?
I'm not new to python, but I have a pretty simple question.
I was playing with python and found that there is a type property
>>> property
<type 'property'>
But I've only heard about properties in the context of a function.
>>> a = property()
<property object at 0x0246C090>
But what about property objects? What are they using? Property methods are not very intuitive or suggestive
>>> dir(a)
['__class__', '__delattr__', '__delete__', '__doc__', '__format__', '__get__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__set__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'deleter', 'fdel', 'fget', 'fset', 'getter', 'setter']
Thanks for your attention!
source to share
An object property
is what you actually think of as a property. Consider this example:
class Foo(object):
def __init__(self):
self._bar = 0
@property
def bar(self):
return self._bar + 5
Foo.bar
- a property object that has a method __get__
. When you write something like
x = Foo() print(x.bar)
lookup x.bar
finds it type(x).bar
has a method __get__
, so lookup for the attribute becomes equivalent
type(x).bar.__get__(x, type(x))
which outputs the value x._bar + 5
.
Using property
as a decorator obscures somewhat the fact that it bar
is an object property
. Equivalent definition
class Foo(object):
def __init__(self):
self._bar = 0
bar = property(lambda self: self._bar + 5)
which shows more explicitly that you create an object property
with a given expression lambda
as a getter for that property and bind the object to the class attribute bar
.
A class property
(along with instance methods, class methods, and static methods) is a specific application of the Python common descriptor protocol that defines the behavior of class attributes using __get__
, __set__
and / or __del__
.
source to share
class MyClass:
def __init__(self,*costs):
self.costs = costs
def item_cost(self):
return sum(self.costs)
now you can do
MyClass(1,2,3,4).item_cost() #prints 10
but we can make it a property
class MyClass:
def __init__(self,*costs):
self.costs = costs
@property
def item_cost(self):
return sum(self.costs)
and now we can access it as a simple variable
MyClass(1,2,3,4).item_cost
you can also create a setter for the value with
...
@item_cost.setter
def set_item_cost(self,value):
pass #do something with value
...
MyClass(1,2,3,4).item_cost = "yellow"
All in all I think this is kind of an anti-pattern ... but some people like em
(note that you can also make this property by using it as a regular function instead of a decorator MyClass.item_cost_prop = property(MyClass.item_cost)
)
source to share