-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #582 from realpython/python-property
Sample code for the article on properties
- Loading branch information
Showing
22 changed files
with
382 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# Python's property(): Add Managed Attributes to Your Classes | ||
|
||
This folder provides the code examples for the Real Python tutorial [Python's property(): Add Managed Attributes to Your Classes](https://realpython.com/python-property/). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
class Circle: | ||
def __init__(self, radius): | ||
self._radius = radius | ||
|
||
def _get_radius(self): | ||
print("Get radius") | ||
return self._radius | ||
|
||
def _set_radius(self, value): | ||
print("Set radius") | ||
self._radius = value | ||
|
||
def _del_radius(self): | ||
print("Delete radius") | ||
del self._radius | ||
|
||
radius = property( | ||
fget=_get_radius, | ||
fset=_set_radius, | ||
fdel=_del_radius, | ||
doc="The radius property.", | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
class Circle: | ||
def __init__(self, radius): | ||
self._radius = radius | ||
|
||
@property | ||
def radius(self): | ||
"""The radius property.""" | ||
print("Get radius") | ||
return self._radius | ||
|
||
@radius.setter | ||
def radius(self, value): | ||
print("Set radius") | ||
self._radius = value | ||
|
||
@radius.deleter | ||
def radius(self): | ||
print("Delete radius") | ||
del self._radius |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
class Circle: | ||
def __init__(self, radius): | ||
self.radius = radius | ||
|
||
@property | ||
def radius(self): | ||
return self._radius | ||
|
||
@radius.setter | ||
def radius(self, value): | ||
self._radius = float(value) | ||
|
||
@property | ||
def diameter(self): | ||
return self.radius * 2 | ||
|
||
@diameter.setter | ||
def diameter(self, value): | ||
self.radius = value / 2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
from time import sleep | ||
|
||
|
||
class Circle: | ||
def __init__(self, radius): | ||
self.radius = radius | ||
self._diameter = None | ||
|
||
@property | ||
def diameter(self): | ||
if self._diameter is None: | ||
sleep(0.5) # Simulate a costly computation | ||
self._diameter = self.radius * 2 | ||
return self._diameter |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
from time import sleep | ||
|
||
|
||
class Circle: | ||
def __init__(self, radius): | ||
self.radius = radius | ||
|
||
@property | ||
def radius(self): | ||
return self._radius | ||
|
||
@radius.setter | ||
def radius(self, value): | ||
self._diameter = None | ||
self._radius = value | ||
|
||
@property | ||
def diameter(self): | ||
if self._diameter is None: | ||
sleep(0.5) # Simulate a costly computation | ||
self._diameter = self._radius * 2 | ||
return self._diameter |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
from functools import cached_property | ||
from time import sleep | ||
|
||
|
||
class Circle: | ||
def __init__(self, radius): | ||
self.radius = radius | ||
|
||
@cached_property | ||
def diameter(self): | ||
sleep(0.5) # Simulate a costly computation | ||
return self.radius * 2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
from functools import cache | ||
from time import sleep | ||
|
||
|
||
class Circle: | ||
def __init__(self, radius): | ||
self.radius = radius | ||
|
||
@property | ||
@cache | ||
def diameter(self): | ||
sleep(0.5) # Simulate a costly computation | ||
return self.radius * 2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import logging | ||
|
||
logging.basicConfig( | ||
format="%(asctime)s: %(message)s", | ||
level=logging.INFO, | ||
datefmt="%H:%M:%S", | ||
) | ||
|
||
|
||
class Circle: | ||
def __init__(self, radius): | ||
self._msg = '"radius" was %s. Current value: %s' | ||
self.radius = radius | ||
|
||
@property | ||
def radius(self): | ||
logging.info(self._msg % ("accessed", str(self._radius))) | ||
return self._radius | ||
|
||
@radius.setter | ||
def radius(self, value): | ||
try: | ||
self._radius = float(value) | ||
logging.info(self._msg % ("mutated", str(self._radius))) | ||
except ValueError: | ||
logging.info('validation error while mutating "radius"') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
class Currency: | ||
def __init__(self, units, cents): | ||
self.units = units | ||
self.cents = cents | ||
|
||
# Currency implementation... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
CENTS_PER_UNIT = 100 | ||
|
||
|
||
class Currency: | ||
def __init__(self, units, cents): | ||
self._total_cents = units * CENTS_PER_UNIT + cents | ||
|
||
@property | ||
def units(self): | ||
return self._total_cents // CENTS_PER_UNIT | ||
|
||
@units.setter | ||
def units(self, value): | ||
self._total_cents = self.cents + value * CENTS_PER_UNIT | ||
|
||
@property | ||
def cents(self): | ||
return self._total_cents % CENTS_PER_UNIT | ||
|
||
@cents.setter | ||
def cents(self, value): | ||
self._total_cents = self.units * CENTS_PER_UNIT + value | ||
|
||
# Currency implementation... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
class TreeNode: | ||
def __init__(self, data): | ||
self._data = data | ||
self._children = [] | ||
|
||
@property | ||
def children(self): | ||
return self._children | ||
|
||
@children.setter | ||
def children(self, value): | ||
if isinstance(value, list): | ||
self._children = value | ||
else: | ||
del self.children | ||
self._children.append(value) | ||
|
||
@children.deleter | ||
def children(self): | ||
self._children.clear() | ||
|
||
def __repr__(self): | ||
return f'{self.__class__.__name__}("{self._data}")' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
class Person: | ||
def __init__(self, name): | ||
self._name = name | ||
|
||
@property | ||
def name(self): | ||
return self._name | ||
|
||
@name.setter | ||
def name(self, value): | ||
self._name = value | ||
|
||
# Person implementation... | ||
|
||
|
||
class Employee(Person): | ||
@property | ||
def name(self): | ||
return super().name.upper() | ||
|
||
# Employee implementation... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
class Point: | ||
def __init__(self, x, y): | ||
self._x = x | ||
self._y = y | ||
|
||
def get_x(self): | ||
return self._x | ||
|
||
def set_x(self, value): | ||
self._x = value | ||
|
||
def get_y(self): | ||
return self._y | ||
|
||
def set_y(self, value): | ||
self._y = value |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
class Point: | ||
def __init__(self, x, y): | ||
self._x = x | ||
self._y = y | ||
|
||
@property | ||
def x(self): | ||
return self._x | ||
|
||
@property | ||
def y(self): | ||
return self._y |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
class WriteCoordinateError(Exception): | ||
pass | ||
|
||
|
||
class Point: | ||
def __init__(self, x, y): | ||
self._x = x | ||
self._y = y | ||
|
||
@property | ||
def x(self): | ||
return self._x | ||
|
||
@x.setter | ||
def x(self, value): | ||
raise WriteCoordinateError("x coordinate is read-only") | ||
|
||
@property | ||
def y(self): | ||
return self._y | ||
|
||
@y.setter | ||
def y(self, value): | ||
raise WriteCoordinateError("y coordinate is read-only") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
class Point: | ||
def __init__(self, x, y): | ||
self.x = x | ||
self.y = y | ||
|
||
@property | ||
def x(self): | ||
return self._x | ||
|
||
@x.setter | ||
def x(self, value): | ||
try: | ||
self._x = float(value) | ||
print("Validated!") | ||
except ValueError: | ||
raise ValueError('"x" must be a number') from None | ||
|
||
@property | ||
def y(self): | ||
return self._y | ||
|
||
@y.setter | ||
def y(self, value): | ||
try: | ||
self._y = float(value) | ||
print("Validated!") | ||
except ValueError: | ||
raise ValueError('"y" must be a number') from None |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
class Coordinate: | ||
def __set_name__(self, owner, name): | ||
self._name = name | ||
|
||
def __get__(self, instance, owner): | ||
return instance.__dict__[self._name] | ||
|
||
def __set__(self, instance, value): | ||
try: | ||
instance.__dict__[self._name] = float(value) | ||
print("Validated!") | ||
except ValueError: | ||
raise ValueError(f'"{self._name}" must be a number') from None | ||
|
||
|
||
class Point: | ||
x = Coordinate() | ||
y = Coordinate() | ||
|
||
def __init__(self, x, y): | ||
self.x = x | ||
self.y = y |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import math | ||
|
||
|
||
class Point: | ||
def __init__(self, x, y): | ||
self.x = x | ||
self.y = y | ||
|
||
@property | ||
def distance(self): | ||
return round(math.dist((0, 0), (self.x, self.y))) | ||
|
||
@property | ||
def angle(self): | ||
return round(math.degrees(math.atan(self.y / self.x)), 1) | ||
|
||
def as_cartesian(self): | ||
return self.x, self.y | ||
|
||
def as_polar(self): | ||
return self.distance, self.angle |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
class Product: | ||
def __init__(self, name, price): | ||
self._name = name | ||
self._price = float(price) | ||
|
||
@property | ||
def price(self): | ||
return f"${self._price:,.2f}" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
class Rectangle: | ||
def __init__(self, width, height): | ||
self.width = width | ||
self.height = height | ||
|
||
@property | ||
def area(self): | ||
return self.width * self.height |
Oops, something went wrong.