This post is the highlight of Raymond Hettinger’s talk “Python’s Class Development Toolkit“ at PyCon US 2013.
Things to keep in mind while writing Classes:
- Inherit from
object()
- Instance variables for information unique to an instance
- Class variables for data shared among all instances
- Regular methods need self to operate on instance data
- Class methods implement alternative constructors. They need
cls
so they can create subclass instances as well - Static methods attach functions to classes. They don’t need
either
self
orcls
. Static methods improve discoverability and require context to be specified. - A
property()
lets getter and setter methods be invoked automatically by attribute access. This allows Python Classes to expose their instance variables freely. - The
__slots__
variable implements Flyweight Design Pattern by supressing instance dictionaries. - Use
__perimeter
to preserve namespace when subclassing. The underlying variable name changes based on the caller.
This is an example with all the above practices implemented:
import math
class GoodCircle(object):
'''This represents the circle class'''
__slots__ = ['diameter'] # Last Resort for memory efficiency
version = '0.1'
def __init__(self, radius):
self.radius = radius
@classmethod
def from_bbd(cls, bbd):
'Construct a Circle from bounding box diagonal'
radius = bbd / 2.0 / math.sqrt(2.0)
return cls(radius)
@property
def radius(self):
return self.diameter / 2.0
@radius.setter
def radius(self, radius):
self.diameter = radius * 2.0
@staticmethod
def angle_to_grade(angle):
'Convert angle in degree to percentage degree'
return math.tan(math.radians(angle)) * 100.0
def area(self):
p = self.__perimeter()
r = p / math.pi / 2.0
return math.pi * r ** 2.0
def perimeter(self):
return 2.0 * math.pi * self.radius
__perimeter = perimeter