Python Specific
Slots
When your application creates thousands or millions of small objects (like game entities, data points, or cache entries), memory usage can explode due to Python's per-instance dictionary overhead. Using __slots__ restricts objects to a fixed set of attributes, dramatically reducing memory consumption.
__slots__ is a class-level attribute that restricts instance attributes to a fixed set, providing memory savings and faster attribute access. By defining __slots__, Python does not create a __dict__ for each instance.
Defining __slots__
"""Basic __slots__ definition"""
# Without __slots__
print("Without __slots__:")
class PersonNoSlots:
def __init__(self, name, age):
self.name = name
self.age = age
person1 = PersonNoSlots("Alice", 30)
print(f"Name: {person1.name}, Age: {person1.age}")
print(f"Has __dict__: {hasattr(person1, '__dict__')}")
print(f"__dict__: {person1.__dict__}")
# Can add dynamic attributes
person1.email = "alice@example.com"
print(f"Added email: {person1.email}")
# With __slots__
print("\nWith __slots__:")
class PersonWithSlots:
__slots__ = ['name', 'age']
def __init__(self, name, age):
self.name = name
self.age = age
person2 = PersonWithSlots("Bob", 25)
print(f"Name: {person2.name}, Age: {person2.age}")
print(f"Has __dict__: {hasattr(person2, '__dict__')}")
# Cannot add dynamic attributes
try:
person2.email = "bob@example.com"
except AttributeError as e:
print(f"Error adding email: {e}")
# Tuple __slots__
print("\nTuple __slots__:")
class Point:
__slots__ = ('x', 'y') # Can use tuple instead of list
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return f"Point({self.x}, {self.y})"
p = Point(10, 20)
print(f"Point: {p}")
print(f"x={p.x}, y={p.y}")
# Multiple attributes
print("\nMultiple attributes:")
class User:
__slots__ = ['user_id', 'username', 'email', 'created_at']
def __init__(self, user_id, username, email, created_at):
self.user_id = user_id
self.username = username
self.email = email
self.created_at = created_at
def __repr__(self):
return f"User(id={self.user_id}, username='{self.username}')"
user = User(1, "alice", "alice@example.com", "2024-01-01")
print(f"User: {user}")
# Read-only slots
print("\nRead-only slots:")
class Config:
__slots__ = ['_host', '_port']
def __init__(self, host, port):
self._host = host
self._port = port
@property
def host(self):
return self._host
@property
def port(self):
return self._port
config = Config("localhost", 8080)
print(f"Config: {config.host}:{config.port}")
# Cannot modify (no setter)
try:
config.host = "0.0.0.0"
except AttributeError as e:
print(f"Error: {e}")
# Empty __slots__
print("\nEmpty __slots__:")
class Immutable:
__slots__ = [] # No instance attributes allowed
VALUE = 42 # Class attribute is OK
im = Immutable()
print(f"Class value: {im.VALUE}")
try:
im.x = 10
except AttributeError as e:
print(f"Error: {e}")
# Checking __slots__
print("\nChecking __slots__:")
class Example:
__slots__ = ['a', 'b', 'c']
print(f"__slots__: {Example.__slots__}")
print(f"Allowed attributes: {', '.join(Example.__slots__)}")
# Practical example
print("\nPractical example:")
class Vector2D:
__slots__ = ['x', 'y']
def __init__(self, x=0, y=0):
self.x = x
self.y = y
def __repr__(self):
return f"Vector2D({self.x}, {self.y})"
def __add__(self, other):
return Vector2D(self.x + other.x, self.y + other.y)
def magnitude(self):
return (self.x ** 2 + self.y ** 2) ** 0.5
v1 = Vector2D(3, 4)
v2 = Vector2D(1, 2)
v3 = v1 + v2
print(f"v1 = {v1}")
print(f"v2 = {v2}")
print(f"v3 = v1 + v2 = {v3}")
print(f"v1 magnitude = {v1.magnitude()}")
"""Basic __slots__ definition"""
# Without __slots__
print("Without __slots__:")
class PersonNoSlots:
def __init__(self, name, age):
self.name = name
self.age = age
person1 = PersonNoSlots("Bob", 25)
print(f"Name: {person1.name}, Age: {person1.age}")
print(f"Has __dict__: {hasattr(person1, '__dict__')}")
print(f"__dict__: {person1.__dict__}")
# Can add dynamic attributes
person1.email = "alice@example.com"
print(f"Added email: {person1.email}")
# With __slots__
print("\nWith __slots__:")
class PersonWithSlots:
__slots__ = ['name', 'age']
def __init__(self, name, age):
self.name = name
self.age = age
person2 = PersonWithSlots("Bob", 25)
print(f"Name: {person2.name}, Age: {person2.age}")
print(f"Has __dict__: {hasattr(person2, '__dict__')}")
# Cannot add dynamic attributes
try:
person2.email = "bob@example.com"
except AttributeError as e:
print(f"Error adding email: {e}")
# Tuple __slots__
print("\nTuple __slots__:")
class Point:
__slots__ = ('x', 'y') # Can use tuple instead of list
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return f"Point({self.x}, {self.y})"
p = Point(10, 20)
print(f"Point: {p}")
print(f"x={p.x}, y={p.y}")
# Multiple attributes
print("\nMultiple attributes:")
class User:
__slots__ = ['user_id', 'username', 'email', 'created_at']
def __init__(self, user_id, username, email, created_at):
self.user_id = user_id
self.username = username
self.email = email
self.created_at = created_at
def __repr__(self):
return f"User(id={self.user_id}, username='{self.username}')"
user = User(1, "alice", "alice@example.com", "2024-01-01")
print(f"User: {user}")
# Read-only slots
print("\nRead-only slots:")
class Config:
__slots__ = ['_host', '_port']
def __init__(self, host, port):
self._host = host
self._port = port
@property
def host(self):
return self._host
@property
def port(self):
return self._port
config = Config("localhost", 8080)
print(f"Config: {config.host}:{config.port}")
# Cannot modify (no setter)
try:
config.host = "0.0.0.0"
except AttributeError as e:
print(f"Error: {e}")
# Empty __slots__
print("\nEmpty __slots__:")
class Immutable:
__slots__ = [] # No instance attributes allowed
VALUE = 42 # Class attribute is OK
im = Immutable()
print(f"Class value: {im.VALUE}")
try:
im.x = 10
except AttributeError as e:
print(f"Error: {e}")
# Checking __slots__
print("\nChecking __slots__:")
class Example:
__slots__ = ['a', 'b', 'c']
print(f"__slots__: {Example.__slots__}")
print(f"Allowed attributes: {', '.join(Example.__slots__)}")
# Practical example
print("\nPractical example:")
class Vector2D:
__slots__ = ['x', 'y']
def __init__(self, x=0, y=0):
self.x = x
self.y = y
def __repr__(self):
return f"Vector2D({self.x}, {self.y})"
def __add__(self, other):
return Vector2D(self.x + other.x, self.y + other.y)
def magnitude(self):
return (self.x ** 2 + self.y ** 2) ** 0.5
v1 = Vector2D(3, 4)
v2 = Vector2D(1, 2)
v3 = v1 + v2
print(f"v1 = {v1}")
print(f"v2 = {v2}")
print(f"v3 = v1 + v2 = {v3}")
print(f"v1 magnitude = {v1.magnitude()}")
"""Basic __slots__ definition"""
# Without __slots__
print("Without __slots__:")
class PersonNoSlots:
def __init__(self, name, age):
self.name = name
self.age = age
person1 = PersonNoSlots("Carol", 45)
print(f"Name: {person1.name}, Age: {person1.age}")
print(f"Has __dict__: {hasattr(person1, '__dict__')}")
print(f"__dict__: {person1.__dict__}")
# Can add dynamic attributes
person1.email = "alice@example.com"
print(f"Added email: {person1.email}")
# With __slots__
print("\nWith __slots__:")
class PersonWithSlots:
__slots__ = ['name', 'age']
def __init__(self, name, age):
self.name = name
self.age = age
person2 = PersonWithSlots("Bob", 25)
print(f"Name: {person2.name}, Age: {person2.age}")
print(f"Has __dict__: {hasattr(person2, '__dict__')}")
# Cannot add dynamic attributes
try:
person2.email = "bob@example.com"
except AttributeError as e:
print(f"Error adding email: {e}")
# Tuple __slots__
print("\nTuple __slots__:")
class Point:
__slots__ = ('x', 'y') # Can use tuple instead of list
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return f"Point({self.x}, {self.y})"
p = Point(10, 20)
print(f"Point: {p}")
print(f"x={p.x}, y={p.y}")
# Multiple attributes
print("\nMultiple attributes:")
class User:
__slots__ = ['user_id', 'username', 'email', 'created_at']
def __init__(self, user_id, username, email, created_at):
self.user_id = user_id
self.username = username
self.email = email
self.created_at = created_at
def __repr__(self):
return f"User(id={self.user_id}, username='{self.username}')"
user = User(1, "alice", "alice@example.com", "2024-01-01")
print(f"User: {user}")
# Read-only slots
print("\nRead-only slots:")
class Config:
__slots__ = ['_host', '_port']
def __init__(self, host, port):
self._host = host
self._port = port
@property
def host(self):
return self._host
@property
def port(self):
return self._port
config = Config("localhost", 8080)
print(f"Config: {config.host}:{config.port}")
# Cannot modify (no setter)
try:
config.host = "0.0.0.0"
except AttributeError as e:
print(f"Error: {e}")
# Empty __slots__
print("\nEmpty __slots__:")
class Immutable:
__slots__ = [] # No instance attributes allowed
VALUE = 42 # Class attribute is OK
im = Immutable()
print(f"Class value: {im.VALUE}")
try:
im.x = 10
except AttributeError as e:
print(f"Error: {e}")
# Checking __slots__
print("\nChecking __slots__:")
class Example:
__slots__ = ['a', 'b', 'c']
print(f"__slots__: {Example.__slots__}")
print(f"Allowed attributes: {', '.join(Example.__slots__)}")
# Practical example
print("\nPractical example:")
class Vector2D:
__slots__ = ['x', 'y']
def __init__(self, x=0, y=0):
self.x = x
self.y = y
def __repr__(self):
return f"Vector2D({self.x}, {self.y})"
def __add__(self, other):
return Vector2D(self.x + other.x, self.y + other.y)
def magnitude(self):
return (self.x ** 2 + self.y ** 2) ** 0.5
v1 = Vector2D(3, 4)
v2 = Vector2D(1, 2)
v3 = v1 + v2
print(f"v1 = {v1}")
print(f"v2 = {v2}")
print(f"v3 = v1 + v2 = {v3}")
print(f"v1 magnitude = {v1.magnitude()}")
"""Basic __slots__ definition"""
1"""Basic __slots__ definition"""23# Without __slots__4print("Without __slots__:")56class PersonNoSlots:7 def __init__(self, name, age):8 self.name = name9 self.age = age1011person1 = PersonNoSlots("Alice", 30) #@person1=PersonNoSlots("Bob", 25), PersonNoSlots("Carol", 45)12print(f"Name: {person1.name}, Age: {person1.age}")outputWithout __slots__:self.name ← Alice, self.age ← 30
6class PersonNoSlots:7 def __init__(self⟨PersonNoSlots A⟩, nameAlice, age30):8 self.name→ Alice = nameAlice9 self.age→ 30 = age30person1 ← ⟨PersonNoSlots A⟩, person1.email ← alice@example.com
11person1→ ⟨PersonNoSlots A⟩ = PersonNoSlots("Alice", 30) #@person1=PersonNoSlots("Bob", 25), PersonNoSlots("Carol", 45)12print(f"Name: {person1.nameAlice}, Age: {person1.age30}")13print(f"Has __dict__: {hasattr(person1⟨PersonNoSlots A⟩, '__dict__')}")14print(f"__dict__: {person1.__dict__{'name': 'Alice', 'age': 30}}")1516# Can add dynamic attributes17person1.email→ alice@example.com = "alice@example.com"18print(f"Added email: {person1.emailalice@example.com}")1920# With __slots__21print("\nWith __slots__:")2223class PersonWithSlots:24 __slots__ = ['name', 'age']25 26 def __init__(self, name, age):27 self.name = name28 self.age = age2930person2 = PersonWithSlots("Bob", 25)31print(f"Name: {person2.name}, Age: {person2.age}")outputName: Alice, Age: 30 Has __dict__: True __dict__: {'name': 'Alice', 'age': 30} Added email: alice@example.com With __slots__:self.name ← Bob, self.age ← 25
26def __init__(self⟨PersonWithSlots B⟩, nameBob, age25):27 self.name→ Bob = nameBob28 self.age→ 25 = age25person2 ← ⟨PersonWithSlots B⟩
30person2→ ⟨PersonWithSlots B⟩ = PersonWithSlots("Bob", 25)31print(f"Name: {person2.nameBob}, Age: {person2.age25}")32print(f"Has __dict__: {hasattr(person2⟨PersonWithSlots B⟩, '__dict__')}")outputName: Bob, Age: 25 Has __dict__: Falseexcept AttributeError as e:
36 person2.email = "bob@example.com"37except AttributeError as e:38 print(f"Error adding email: {e'PersonWithSlots' object has no attribute 'email'}")outputError adding email: 'PersonWithSlots' object has no attribute 'email'print(" Tuple __slots__:")
40# Tuple __slots__41print("\nTuple __slots__:")4243class Point:44 __slots__ = ('x', 'y') # Can use tuple instead of list45 46 def __init__(self, x, y):47 self.x = x48 self.y = y49 50 def __repr__(self):51 return f"Point({self.x}, {self.y})"5253p = Point(10, 20)54print(f"Point: {p}")output Tuple __slots__:self.x ← 10, self.y ← 20
46def __init__(self(empty), x10, y20):47 self.x→ 10 = x1048 self.y→ 20 = y20p ← Point(10, 20)
53p→ Point(10, 20) = Point(10, 20)54print(f"Point: {pPoint(10, 20)}")55print(f"x={p.x10}, y={p.y20}")5657# Multiple attributes58print("\nMultiple attributes:")5960class User:61 __slots__ = ['user_id', 'username', 'email', 'created_at']62 63 def __init__(self, user_id, username, email, created_at):64 self.user_id = user_id65 self.username = username66 self.email = email67 self.created_at = created_at68 69 def __repr__(self):70 return f"User(id={self.user_id}, username='{self.username}')"7172user = User(1, "alice", "alice@example.com", "2024-01-01")73print(f"User: {user}")outputPoint: Point(10, 20) x=10, y=20 Multiple attributes:self.user_id ← 1, self.username ← alice, self.email ← alice@example.com
63def __init__(self(empty), user_id1, usernamealice, emailalice@example.com, created_at2024-01-01):64 self.user_id→ 1 = user_id165 self.username→ alice = usernamealice66 self.email→ alice@example.com = emailalice@example.com67 self.created_at→ 2024-01-01 = created_at2024-01-01user ← User(id=1, username='alice')
72user→ User(id=1, username='alice') = User(1, "alice", "alice@example.com", "2024-01-01")73print(f"User: {userUser(id=1, username='alice')}")7475# Read-only slots76print("\nRead-only slots:")7778class Config:79 __slots__ = ['_host', '_port']80 81 def __init__(self, host, port):82 self._host = host83 self._port = port84 85 @property86 def host(self):87 return self._host88 89 @property90 def port(self):91 return self._port9293config = Config("localhost", 8080)94print(f"Config: {config.host}:{config.port}")outputUser: User(id=1, username='alice') Read-only slots:self._host ← localhost, self._port ← 8080
81def __init__(self⟨Config C⟩, hostlocalhost, port8080):82 self._host→ localhost = hostlocalhost83 self._port→ 8080 = port8080config ← ⟨Config C⟩
93config→ ⟨Config C⟩ = Config("localhost", 8080)94print(f"Config: {config.hostlocalhost}:{config.port8080}")def host(self):
85@property86def host(self⟨Config C⟩):87 return self._hostlocalhostdef port(self):
89@property90def port(self⟨Config C⟩):91 return self._port8080print(f"Config: {config.host}:{config.port}")
93config = Config("localhost", 8080)94print(f"Config: {config.hostlocalhost}:{config.port8080}")outputConfig: localhost:8080except AttributeError as e:
98 config.host = "0.0.0.0"99except AttributeError as e:100 print(f"Error: {eproperty 'host' of 'Config' object has no setter}")outputError: property 'host' of 'Config' object has no setterVALUE ← (empty), im ← ⟨Immutable D⟩
102# Empty __slots__103print("\nEmpty __slots__:")104105class Immutable:106 __slots__ = [] # No instance attributes allowed107 108 VALUE→ (empty) = 42 # Class attribute is OK109110im→ ⟨Immutable D⟩ = Immutable()111print(f"Class value: {im.VALUE42}")output Empty __slots__: Class value: 42except AttributeError as e:
114 im.x = 10115except AttributeError as e:116 print(f"Error: {e'Immutable' object has no attribute 'x'}")outputError: 'Immutable' object has no attribute 'x'print(f"__slots__: {Example.__slots__}")
118# Checking __slots__119print("\nChecking __slots__:")120121class Example:122 __slots__ = ['a', 'b', 'c']123124print(f"__slots__: {Example.__slots__['a', 'b', 'c']}")125print(f"Allowed attributes: {', '.join(Example.__slots__['a', 'b', 'c'])}")126127# Practical example128print("\nPractical example:")129130class Vector2D:131 __slots__ = ['x', 'y']132 133 def __init__(self, x=0, y=0):134 self.x = x135 self.y = y136 137 def __repr__(self):138 return f"Vector2D({self.x}, {self.y})"139 140 def __add__(self, other):141 return Vector2D(self.x + other.x, self.y + other.y)142 143 def magnitude(self):144 return (self.x ** 2 + self.y ** 2) ** 0.5145146v1 = Vector2D(3, 4)147v2 = Vector2D(1, 2)output Checking __slots__: __slots__: ['a', 'b', 'c'] Allowed attributes: a, b, c Practical example:self.x ← 3, self.y ← 4
pass 1 of 3133def __init__(self(empty), x3=0, y4=0):134 self.x→ 3 = x3135 self.y→ 4 = y4All 3 passes — pass 1 is the card above pass xyself.xself.y1 3 4 3 4 2 1 2 1 2 3 4 6 4 6 v1 ← Vector2D(3, 4)
146v1→ Vector2D(3, 4) = Vector2D(3, 4)147v2 = Vector2D(1, 2)148v3 = v1 + v2v2 ← Vector2D(1, 2)
146v1 = Vector2D(3, 4)147v2→ Vector2D(1, 2) = Vector2D(1, 2)148v3 = v1Vector2D(3, 4) + v2Vector2D(1, 2)def __add__(self, other):
140def __add__(selfVector2D(3, 4), otherVector2D(1, 2)):141 return Vector2D(self.x3 + other.x1, self.y4 + other.y2)v3 ← Vector2D(4, 6)
147v2 = Vector2D(1, 2)148v3→ Vector2D(4, 6) = v1Vector2D(3, 4) + v2Vector2D(1, 2)149150print(f"v1 = {v1Vector2D(3, 4)}")151print(f"v2 = {v2Vector2D(1, 2)}")152print(f"v3 = v1 + v2 = {v3Vector2D(4, 6)}")153print(f"v1 magnitude = {v1Vector2D(3, 4).magnitude()}")outputv1 = Vector2D(3, 4) v2 = Vector2D(1, 2) v3 = v1 + v2 = Vector2D(4, 6)def magnitude(self):
143def magnitude(selfVector2D(3, 4)):144 return (self.x3 ** 2 + self.y4 ** 2) ** 0.5print(f"v1 magnitude = {v1.magnitude()}")
152print(f"v3 = v1 + v2 = {v3}")153print(f"v1 magnitude = {v1Vector2D(3, 4).magnitude()}")outputv1 magnitude = 5.0
"""Basic __slots__ definition"""
1"""Basic __slots__ definition"""23# Without __slots__4print("Without __slots__:")56class PersonNoSlots:7 def __init__(self, name, age):8 self.name = name9 self.age = age1011person1 = PersonNoSlots("Bob", 25)12print(f"Name: {person1.name}, Age: {person1.age}")outputWithout __slots__:self.name ← Bob, self.age ← 25
6class PersonNoSlots:7 def __init__(self⟨PersonNoSlots A⟩, nameBob, age25):8 self.name→ Bob = nameBob9 self.age→ 25 = age25person1 ← ⟨PersonNoSlots A⟩, person1.email ← alice@example.com
11person1→ ⟨PersonNoSlots A⟩ = PersonNoSlots("Bob", 25)12print(f"Name: {person1.nameBob}, Age: {person1.age25}")13print(f"Has __dict__: {hasattr(person1⟨PersonNoSlots A⟩, '__dict__')}")14print(f"__dict__: {person1.__dict__{'name': 'Bob', 'age': 25}}")1516# Can add dynamic attributes17person1.email→ alice@example.com = "alice@example.com"18print(f"Added email: {person1.emailalice@example.com}")1920# With __slots__21print("\nWith __slots__:")2223class PersonWithSlots:24 __slots__ = ['name', 'age']25 26 def __init__(self, name, age):27 self.name = name28 self.age = age2930person2 = PersonWithSlots("Bob", 25)31print(f"Name: {person2.name}, Age: {person2.age}")outputName: Bob, Age: 25 Has __dict__: True __dict__: {'name': 'Bob', 'age': 25} Added email: alice@example.com With __slots__:self.name ← Bob, self.age ← 25
26def __init__(self⟨PersonWithSlots B⟩, nameBob, age25):27 self.name→ Bob = nameBob28 self.age→ 25 = age25person2 ← ⟨PersonWithSlots B⟩
30person2→ ⟨PersonWithSlots B⟩ = PersonWithSlots("Bob", 25)31print(f"Name: {person2.nameBob}, Age: {person2.age25}")32print(f"Has __dict__: {hasattr(person2⟨PersonWithSlots B⟩, '__dict__')}")outputName: Bob, Age: 25 Has __dict__: Falseexcept AttributeError as e:
36 person2.email = "bob@example.com"37except AttributeError as e:38 print(f"Error adding email: {e'PersonWithSlots' object has no attribute 'email'}")outputError adding email: 'PersonWithSlots' object has no attribute 'email'print(" Tuple __slots__:")
40# Tuple __slots__41print("\nTuple __slots__:")4243class Point:44 __slots__ = ('x', 'y') # Can use tuple instead of list45 46 def __init__(self, x, y):47 self.x = x48 self.y = y49 50 def __repr__(self):51 return f"Point({self.x}, {self.y})"5253p = Point(10, 20)54print(f"Point: {p}")output Tuple __slots__:self.x ← 10, self.y ← 20
46def __init__(self(empty), x10, y20):47 self.x→ 10 = x1048 self.y→ 20 = y20p ← Point(10, 20)
53p→ Point(10, 20) = Point(10, 20)54print(f"Point: {pPoint(10, 20)}")55print(f"x={p.x10}, y={p.y20}")5657# Multiple attributes58print("\nMultiple attributes:")5960class User:61 __slots__ = ['user_id', 'username', 'email', 'created_at']62 63 def __init__(self, user_id, username, email, created_at):64 self.user_id = user_id65 self.username = username66 self.email = email67 self.created_at = created_at68 69 def __repr__(self):70 return f"User(id={self.user_id}, username='{self.username}')"7172user = User(1, "alice", "alice@example.com", "2024-01-01")73print(f"User: {user}")outputPoint: Point(10, 20) x=10, y=20 Multiple attributes:self.user_id ← 1, self.username ← alice, self.email ← alice@example.com
63def __init__(self(empty), user_id1, usernamealice, emailalice@example.com, created_at2024-01-01):64 self.user_id→ 1 = user_id165 self.username→ alice = usernamealice66 self.email→ alice@example.com = emailalice@example.com67 self.created_at→ 2024-01-01 = created_at2024-01-01user ← User(id=1, username='alice')
72user→ User(id=1, username='alice') = User(1, "alice", "alice@example.com", "2024-01-01")73print(f"User: {userUser(id=1, username='alice')}")7475# Read-only slots76print("\nRead-only slots:")7778class Config:79 __slots__ = ['_host', '_port']80 81 def __init__(self, host, port):82 self._host = host83 self._port = port84 85 @property86 def host(self):87 return self._host88 89 @property90 def port(self):91 return self._port9293config = Config("localhost", 8080)94print(f"Config: {config.host}:{config.port}")outputUser: User(id=1, username='alice') Read-only slots:self._host ← localhost, self._port ← 8080
81def __init__(self⟨Config C⟩, hostlocalhost, port8080):82 self._host→ localhost = hostlocalhost83 self._port→ 8080 = port8080config ← ⟨Config C⟩
93config→ ⟨Config C⟩ = Config("localhost", 8080)94print(f"Config: {config.hostlocalhost}:{config.port8080}")def host(self):
85@property86def host(self⟨Config C⟩):87 return self._hostlocalhostdef port(self):
89@property90def port(self⟨Config C⟩):91 return self._port8080print(f"Config: {config.host}:{config.port}")
93config = Config("localhost", 8080)94print(f"Config: {config.hostlocalhost}:{config.port8080}")outputConfig: localhost:8080except AttributeError as e:
98 config.host = "0.0.0.0"99except AttributeError as e:100 print(f"Error: {eproperty 'host' of 'Config' object has no setter}")outputError: property 'host' of 'Config' object has no setterVALUE ← (empty), im ← ⟨Immutable D⟩
102# Empty __slots__103print("\nEmpty __slots__:")104105class Immutable:106 __slots__ = [] # No instance attributes allowed107 108 VALUE→ (empty) = 42 # Class attribute is OK109110im→ ⟨Immutable D⟩ = Immutable()111print(f"Class value: {im.VALUE42}")output Empty __slots__: Class value: 42except AttributeError as e:
114 im.x = 10115except AttributeError as e:116 print(f"Error: {e'Immutable' object has no attribute 'x'}")outputError: 'Immutable' object has no attribute 'x'print(f"__slots__: {Example.__slots__}")
118# Checking __slots__119print("\nChecking __slots__:")120121class Example:122 __slots__ = ['a', 'b', 'c']123124print(f"__slots__: {Example.__slots__['a', 'b', 'c']}")125print(f"Allowed attributes: {', '.join(Example.__slots__['a', 'b', 'c'])}")126127# Practical example128print("\nPractical example:")129130class Vector2D:131 __slots__ = ['x', 'y']132 133 def __init__(self, x=0, y=0):134 self.x = x135 self.y = y136 137 def __repr__(self):138 return f"Vector2D({self.x}, {self.y})"139 140 def __add__(self, other):141 return Vector2D(self.x + other.x, self.y + other.y)142 143 def magnitude(self):144 return (self.x ** 2 + self.y ** 2) ** 0.5145146v1 = Vector2D(3, 4)147v2 = Vector2D(1, 2)output Checking __slots__: __slots__: ['a', 'b', 'c'] Allowed attributes: a, b, c Practical example:self.x ← 3, self.y ← 4
pass 1 of 3133def __init__(self(empty), x3=0, y4=0):134 self.x→ 3 = x3135 self.y→ 4 = y4All 3 passes — pass 1 is the card above pass xyself.xself.y1 3 4 3 4 2 1 2 1 2 3 4 6 4 6 v1 ← Vector2D(3, 4)
146v1→ Vector2D(3, 4) = Vector2D(3, 4)147v2 = Vector2D(1, 2)148v3 = v1 + v2v2 ← Vector2D(1, 2)
146v1 = Vector2D(3, 4)147v2→ Vector2D(1, 2) = Vector2D(1, 2)148v3 = v1Vector2D(3, 4) + v2Vector2D(1, 2)def __add__(self, other):
140def __add__(selfVector2D(3, 4), otherVector2D(1, 2)):141 return Vector2D(self.x3 + other.x1, self.y4 + other.y2)v3 ← Vector2D(4, 6)
147v2 = Vector2D(1, 2)148v3→ Vector2D(4, 6) = v1Vector2D(3, 4) + v2Vector2D(1, 2)149150print(f"v1 = {v1Vector2D(3, 4)}")151print(f"v2 = {v2Vector2D(1, 2)}")152print(f"v3 = v1 + v2 = {v3Vector2D(4, 6)}")153print(f"v1 magnitude = {v1Vector2D(3, 4).magnitude()}")outputv1 = Vector2D(3, 4) v2 = Vector2D(1, 2) v3 = v1 + v2 = Vector2D(4, 6)def magnitude(self):
143def magnitude(selfVector2D(3, 4)):144 return (self.x3 ** 2 + self.y4 ** 2) ** 0.5print(f"v1 magnitude = {v1.magnitude()}")
152print(f"v3 = v1 + v2 = {v3}")153print(f"v1 magnitude = {v1Vector2D(3, 4).magnitude()}")outputv1 magnitude = 5.0
"""Basic __slots__ definition"""
1"""Basic __slots__ definition"""23# Without __slots__4print("Without __slots__:")56class PersonNoSlots:7 def __init__(self, name, age):8 self.name = name9 self.age = age1011person1 = PersonNoSlots("Carol", 45)12print(f"Name: {person1.name}, Age: {person1.age}")outputWithout __slots__:self.name ← Carol, self.age ← 45
6class PersonNoSlots:7 def __init__(self⟨PersonNoSlots A⟩, nameCarol, age45):8 self.name→ Carol = nameCarol9 self.age→ 45 = age45person1 ← ⟨PersonNoSlots A⟩, person1.email ← alice@example.com
11person1→ ⟨PersonNoSlots A⟩ = PersonNoSlots("Carol", 45)12print(f"Name: {person1.nameCarol}, Age: {person1.age45}")13print(f"Has __dict__: {hasattr(person1⟨PersonNoSlots A⟩, '__dict__')}")14print(f"__dict__: {person1.__dict__{'name': 'Carol', 'age': 45}}")1516# Can add dynamic attributes17person1.email→ alice@example.com = "alice@example.com"18print(f"Added email: {person1.emailalice@example.com}")1920# With __slots__21print("\nWith __slots__:")2223class PersonWithSlots:24 __slots__ = ['name', 'age']25 26 def __init__(self, name, age):27 self.name = name28 self.age = age2930person2 = PersonWithSlots("Bob", 25)31print(f"Name: {person2.name}, Age: {person2.age}")outputName: Carol, Age: 45 Has __dict__: True __dict__: {'name': 'Carol', 'age': 45} Added email: alice@example.com With __slots__:self.name ← Bob, self.age ← 25
26def __init__(self⟨PersonWithSlots B⟩, nameBob, age25):27 self.name→ Bob = nameBob28 self.age→ 25 = age25person2 ← ⟨PersonWithSlots B⟩
30person2→ ⟨PersonWithSlots B⟩ = PersonWithSlots("Bob", 25)31print(f"Name: {person2.nameBob}, Age: {person2.age25}")32print(f"Has __dict__: {hasattr(person2⟨PersonWithSlots B⟩, '__dict__')}")outputName: Bob, Age: 25 Has __dict__: Falseexcept AttributeError as e:
36 person2.email = "bob@example.com"37except AttributeError as e:38 print(f"Error adding email: {e'PersonWithSlots' object has no attribute 'email'}")outputError adding email: 'PersonWithSlots' object has no attribute 'email'print(" Tuple __slots__:")
40# Tuple __slots__41print("\nTuple __slots__:")4243class Point:44 __slots__ = ('x', 'y') # Can use tuple instead of list45 46 def __init__(self, x, y):47 self.x = x48 self.y = y49 50 def __repr__(self):51 return f"Point({self.x}, {self.y})"5253p = Point(10, 20)54print(f"Point: {p}")output Tuple __slots__:self.x ← 10, self.y ← 20
46def __init__(self(empty), x10, y20):47 self.x→ 10 = x1048 self.y→ 20 = y20p ← Point(10, 20)
53p→ Point(10, 20) = Point(10, 20)54print(f"Point: {pPoint(10, 20)}")55print(f"x={p.x10}, y={p.y20}")5657# Multiple attributes58print("\nMultiple attributes:")5960class User:61 __slots__ = ['user_id', 'username', 'email', 'created_at']62 63 def __init__(self, user_id, username, email, created_at):64 self.user_id = user_id65 self.username = username66 self.email = email67 self.created_at = created_at68 69 def __repr__(self):70 return f"User(id={self.user_id}, username='{self.username}')"7172user = User(1, "alice", "alice@example.com", "2024-01-01")73print(f"User: {user}")outputPoint: Point(10, 20) x=10, y=20 Multiple attributes:self.user_id ← 1, self.username ← alice, self.email ← alice@example.com
63def __init__(self(empty), user_id1, usernamealice, emailalice@example.com, created_at2024-01-01):64 self.user_id→ 1 = user_id165 self.username→ alice = usernamealice66 self.email→ alice@example.com = emailalice@example.com67 self.created_at→ 2024-01-01 = created_at2024-01-01user ← User(id=1, username='alice')
72user→ User(id=1, username='alice') = User(1, "alice", "alice@example.com", "2024-01-01")73print(f"User: {userUser(id=1, username='alice')}")7475# Read-only slots76print("\nRead-only slots:")7778class Config:79 __slots__ = ['_host', '_port']80 81 def __init__(self, host, port):82 self._host = host83 self._port = port84 85 @property86 def host(self):87 return self._host88 89 @property90 def port(self):91 return self._port9293config = Config("localhost", 8080)94print(f"Config: {config.host}:{config.port}")outputUser: User(id=1, username='alice') Read-only slots:self._host ← localhost, self._port ← 8080
81def __init__(self⟨Config C⟩, hostlocalhost, port8080):82 self._host→ localhost = hostlocalhost83 self._port→ 8080 = port8080config ← ⟨Config C⟩
93config→ ⟨Config C⟩ = Config("localhost", 8080)94print(f"Config: {config.hostlocalhost}:{config.port8080}")def host(self):
85@property86def host(self⟨Config C⟩):87 return self._hostlocalhostdef port(self):
89@property90def port(self⟨Config C⟩):91 return self._port8080print(f"Config: {config.host}:{config.port}")
93config = Config("localhost", 8080)94print(f"Config: {config.hostlocalhost}:{config.port8080}")outputConfig: localhost:8080except AttributeError as e:
98 config.host = "0.0.0.0"99except AttributeError as e:100 print(f"Error: {eproperty 'host' of 'Config' object has no setter}")outputError: property 'host' of 'Config' object has no setterVALUE ← (empty), im ← ⟨Immutable D⟩
102# Empty __slots__103print("\nEmpty __slots__:")104105class Immutable:106 __slots__ = [] # No instance attributes allowed107 108 VALUE→ (empty) = 42 # Class attribute is OK109110im→ ⟨Immutable D⟩ = Immutable()111print(f"Class value: {im.VALUE42}")output Empty __slots__: Class value: 42except AttributeError as e:
114 im.x = 10115except AttributeError as e:116 print(f"Error: {e'Immutable' object has no attribute 'x'}")outputError: 'Immutable' object has no attribute 'x'print(f"__slots__: {Example.__slots__}")
118# Checking __slots__119print("\nChecking __slots__:")120121class Example:122 __slots__ = ['a', 'b', 'c']123124print(f"__slots__: {Example.__slots__['a', 'b', 'c']}")125print(f"Allowed attributes: {', '.join(Example.__slots__['a', 'b', 'c'])}")126127# Practical example128print("\nPractical example:")129130class Vector2D:131 __slots__ = ['x', 'y']132 133 def __init__(self, x=0, y=0):134 self.x = x135 self.y = y136 137 def __repr__(self):138 return f"Vector2D({self.x}, {self.y})"139 140 def __add__(self, other):141 return Vector2D(self.x + other.x, self.y + other.y)142 143 def magnitude(self):144 return (self.x ** 2 + self.y ** 2) ** 0.5145146v1 = Vector2D(3, 4)147v2 = Vector2D(1, 2)output Checking __slots__: __slots__: ['a', 'b', 'c'] Allowed attributes: a, b, c Practical example:self.x ← 3, self.y ← 4
pass 1 of 3133def __init__(self(empty), x3=0, y4=0):134 self.x→ 3 = x3135 self.y→ 4 = y4All 3 passes — pass 1 is the card above pass xyself.xself.y1 3 4 3 4 2 1 2 1 2 3 4 6 4 6 v1 ← Vector2D(3, 4)
146v1→ Vector2D(3, 4) = Vector2D(3, 4)147v2 = Vector2D(1, 2)148v3 = v1 + v2v2 ← Vector2D(1, 2)
146v1 = Vector2D(3, 4)147v2→ Vector2D(1, 2) = Vector2D(1, 2)148v3 = v1Vector2D(3, 4) + v2Vector2D(1, 2)def __add__(self, other):
140def __add__(selfVector2D(3, 4), otherVector2D(1, 2)):141 return Vector2D(self.x3 + other.x1, self.y4 + other.y2)v3 ← Vector2D(4, 6)
147v2 = Vector2D(1, 2)148v3→ Vector2D(4, 6) = v1Vector2D(3, 4) + v2Vector2D(1, 2)149150print(f"v1 = {v1Vector2D(3, 4)}")151print(f"v2 = {v2Vector2D(1, 2)}")152print(f"v3 = v1 + v2 = {v3Vector2D(4, 6)}")153print(f"v1 magnitude = {v1Vector2D(3, 4).magnitude()}")outputv1 = Vector2D(3, 4) v2 = Vector2D(1, 2) v3 = v1 + v2 = Vector2D(4, 6)def magnitude(self):
143def magnitude(selfVector2D(3, 4)):144 return (self.x3 ** 2 + self.y4 ** 2) ** 0.5print(f"v1 magnitude = {v1.magnitude()}")
152print(f"v3 = v1 + v2 = {v3}")153print(f"v1 magnitude = {v1Vector2D(3, 4).magnitude()}")outputv1 magnitude = 5.0
When you define __slots__, Python uses a more compact internal representation for instances instead of a dictionary.
Memory Savings
"""Memory savings with __slots__"""
# Memory comparison
print("Memory comparison:")
import sys
class WithoutSlots:
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
class WithSlots:
__slots__ = ['x', 'y', 'z']
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
# Create single instances
obj_no_slots = WithoutSlots(1, 2, 3)
obj_with_slots = WithSlots(1, 2, 3)
# Get sizes
size_no_slots = sys.getsizeof(obj_no_slots) + sys.getsizeof(obj_no_slots.__dict__)
size_with_slots = sys.getsizeof(obj_with_slots)
print(f"Without __slots__: {size_no_slots} bytes")
print(f"With __slots__: {size_with_slots} bytes")
print(f"Savings: {size_no_slots - size_with_slots} bytes ({100 * (1 - size_with_slots/size_no_slots):.1f}%)")
# Many instances
print("\nMany instances:")
# Create many instances
count = 100
no_slots_list = [WithoutSlots(i, i+1, i+2) for i in range(count)]
with_slots_list = [WithSlots(i, i+1, i+2) for i in range(count)]
# Estimate total size
total_no_slots = sum(sys.getsizeof(obj) + sys.getsizeof(obj.__dict__) for obj in no_slots_list[:100]) / 100 * count
total_with_slots = sum(sys.getsizeof(obj) for obj in with_slots_list[:100]) / 100 * count
print(f"{count} instances:")
print(f"Without __slots__: ~{total_no_slots/1024:.1f} KB")
print(f"With __slots__: ~{total_with_slots/1024:.1f} KB")
print(f"Estimated savings: ~{(total_no_slots - total_with_slots)/1024:.1f} KB")
# Simple data class
print("\nSimple data class:")
class Point:
__slots__ = ['x', 'y']
def __init__(self, x, y):
self.x = x
self.y = y
# Create many points
points = [Point(i, i*2) for i in range(100)]
# Sample memory usage
sample_size = sys.getsizeof(points[0])
print(f"Point with __slots__: {sample_size} bytes each")
print(f"100 points: ~{sample_size * 100 / 1024:.1f} KB")
# Complex object
print("\nComplex object:")
class PersonNoSlots:
def __init__(self, name, age, email, city):
self.name = name
self.age = age
self.email = email
self.city = city
class PersonWithSlots:
__slots__ = ['name', 'age', 'email', 'city']
def __init__(self, name, age, email, city):
self.name = name
self.age = age
self.email = email
self.city = city
p1 = PersonNoSlots("Alice", 30, "alice@example.com", "NYC")
p2 = PersonWithSlots("Alice", 30, "alice@example.com", "NYC")
size1 = sys.getsizeof(p1) + sys.getsizeof(p1.__dict__)
size2 = sys.getsizeof(p2)
print(f"PersonNoSlots: {size1} bytes")
print(f"PersonWithSlots: {size2} bytes")
print(f"Savings per instance: {size1 - size2} bytes")
# Large dataset
print("\nLarge dataset:")
class Record:
__slots__ = ['id', 'timestamp', 'value', 'status']
def __init__(self, id, timestamp, value, status):
self.id = id
self.timestamp = timestamp
self.value = value
self.status = status
# Simulate large dataset
dataset_size = 10000
print(f"Creating {dataset_size} records...")
# Estimate memory (based on sample)
sample = Record(1, 1234567890, 42.5, "active")
record_size = sys.getsizeof(sample)
print(f"Size per record: {record_size} bytes")
print(f"Total for {dataset_size} records: ~{record_size * dataset_size / 1024 / 1024:.1f} MB")
# Time series data
print("\nTime series data:")
class DataPoint:
__slots__ = ['timestamp', 'value']
def __init__(self, timestamp, value):
self.timestamp = timestamp
self.value = value
# Simulate 1 year of per-minute data
minutes_per_year = 365 * 24 * 60
point_size = sys.getsizeof(DataPoint(0, 0.0))
print(f"Data point size: {point_size} bytes")
print(f"1 year (minute resolution): ~{point_size * minutes_per_year / 1024 / 1024:.1f} MB")
# Practical comparison
print("\nPractical comparison:")
# Coordinates for game
class CoordNoSlots:
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
class CoordWithSlots:
__slots__ = ['x', 'y', 'z']
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
# Simulate game world with many entities
entity_count = 1000
# Sample sizes
no_slots = CoordNoSlots(0, 0, 0)
with_slots = CoordWithSlots(0, 0, 0)
size_no = sys.getsizeof(no_slots) + sys.getsizeof(no_slots.__dict__)
size_with = sys.getsizeof(with_slots)
print(f"{entity_count} game entities:")
print(f"Without __slots__: ~{size_no * entity_count / 1024:.1f} KB")
print(f"With __slots__: ~{size_with * entity_count / 1024:.1f} KB")
print(f"Memory saved: ~{(size_no - size_with) * entity_count / 1024:.1f} KB")
"""Memory savings with __slots__"""
1"""Memory savings with __slots__"""23# Memory comparison4print("Memory comparison:")56import sys78class WithoutSlots:9 def __init__(self, x, y, z):10 self.x = x11 self.y = y12 self.z = z1314class WithSlots:15 __slots__ = ['x', 'y', 'z']16 17 def __init__(self, x, y, z):18 self.x = x19 self.y = y20 self.z = z2122# Create single instances23obj_no_slots = WithoutSlots(1, 2, 3)24obj_with_slots = WithSlots(1, 2, 3)outputMemory comparison:self.x ← 1, self.y ← 2, self.z ← 3
pass 1 of 1018class WithoutSlots:9 def __init__(self⟨WithoutSlots A⟩, x1, y2, z3):10 self.x→ 1 = x111 self.y→ 2 = y212 self.z→ 3 = z3101 passes — pass 1 is the card above pass selfxyzself.xself.yself.z1 ⟨WithoutSlots A⟩ 1 2 3 1 2 3 2 ⟨WithoutSlots B⟩ 0 1 2 0 1 2 3 ⟨WithoutSlots C⟩ 1 2 3 1 2 3 4 ⟨WithoutSlots D⟩ 2 3 4 2 3 4 5 ⟨WithoutSlots E⟩ 3 4 5 3 4 5 6 ⟨WithoutSlots F⟩ 4 5 6 4 5 6 7 ⟨WithoutSlots G⟩ 5 6 7 5 6 7 8 ⟨WithoutSlots H⟩ 6 7 8 6 7 8 9 ⟨WithoutSlots I⟩ 7 8 9 7 8 9 ⋯ 90 more passes ⋯ 100 ⟨WithoutSlots J⟩ 98 99 100 98 99 100 101 ⟨WithoutSlots K⟩ 99 100 101 99 100 101 obj_no_slots ← ⟨WithoutSlots A⟩
22# Create single instances23obj_no_slots→ ⟨WithoutSlots A⟩ = WithoutSlots(1, 2, 3)24obj_with_slots = WithSlots(1, 2, 3)self.x ← 1, self.y ← 2, self.z ← 3
pass 1 of 10117def __init__(self⟨WithSlots L⟩, x1, y2, z3):18 self.x→ 1 = x119 self.y→ 2 = y220 self.z→ 3 = z3101 passes — pass 1 is the card above pass selfxyzself.xself.yself.z1 ⟨WithSlots L⟩ 1 2 3 1 2 3 2 ⟨WithSlots M⟩ 0 1 2 0 1 2 3 ⟨WithSlots N⟩ 1 2 3 1 2 3 4 ⟨WithSlots O⟩ 2 3 4 2 3 4 5 ⟨WithSlots P⟩ 3 4 5 3 4 5 6 ⟨WithSlots Q⟩ 4 5 6 4 5 6 7 ⟨WithSlots R⟩ 5 6 7 5 6 7 8 ⟨WithSlots S⟩ 6 7 8 6 7 8 9 ⟨WithSlots T⟩ 7 8 9 7 8 9 ⋯ 90 more passes ⋯ 100 ⟨WithSlots U⟩ 98 99 100 98 99 100 101 ⟨WithSlots V⟩ 99 100 101 99 100 101 obj_with_slots ← ⟨WithSlots L⟩, size_no_slots ← 344, size_with_slots ← 56
23obj_no_slots = WithoutSlots(1, 2, 3)24obj_with_slots→ ⟨WithSlots L⟩ = WithSlots(1, 2, 3)2526# Get sizes27size_no_slots→ 344 = sys<module 'sys' (built-in)>.getsizeof(obj_no_slots⟨WithoutSlots A⟩) + sys.getsizeof(obj_no_slots.__dict__{'x': 1, 'y': 2, 'z': 3})28size_with_slots→ 56 = sys<module 'sys' (built-in)>.getsizeof(obj_with_slots⟨WithSlots L⟩)2930print(f"Without __slots__: {size_no_slots344} bytes")31print(f"With __slots__: {size_with_slots56} bytes")32print(f"Savings: {size_no_slots344 - size_with_slots56} bytes ({100 * (1 - size_with_slots/size_no_slots):.1f}%)")3334# Many instances35print("\nMany instances:")3637# Create many instances38count→ 100 = 1003940no_slots_list = [WithoutSlots(i, i+1, i+2) for i in range(count100)]41with_slots_list = [WithSlots(i, i+1, i+2) for i in range(count)]outputWithout __slots__: 344 bytes With __slots__: 56 bytes Savings: 288 bytes (83.7%) Many instances:no_slots_list ← [⟨WithoutSlots B⟩, ⟨WithoutSlots C⟩, ⟨WithoutSlots D⟩, ⟨WithoutSlots E⟩, ⟨WithoutSlots F⟩, ⟨WithoutSlots G⟩, ⟨WithoutSlots H⟩, ⟨WithoutSlots I⟩, ⟨WithoutSlots W⟩, ⟨WithoutSlots X⟩, ⟨WithoutSlots Y⟩, ⟨WithoutSlots Z⟩, ⟨WithoutSlots AA⟩, ⟨WithoutSlots AB⟩, ⟨WithoutSlots AC⟩, ⟨WithoutSlots AD⟩, ⟨WithoutSlots AE⟩, ⟨WithoutSlots AF⟩, ⟨WithoutSlots AG⟩, ⟨WithoutSlots AH⟩, ⟨WithoutSlots AI⟩, ⟨WithoutSlots AJ⟩, ⟨WithoutSlots AK⟩, ⟨WithoutSlots AL⟩, ⟨WithoutSlots AM⟩, ⟨WithoutSlots AN⟩, ⟨WithoutSlots AO⟩, ⟨WithoutSlots AP⟩, ⟨WithoutSlots AQ⟩, ⟨WithoutSlots AR⟩, ⟨WithoutSlots AS⟩, ⟨WithoutSlots AT⟩, ⟨WithoutSlots AU⟩, ⟨WithoutSlots AV⟩, ⟨WithoutSlots AW⟩, ⟨WithoutSlots AX⟩, ⟨WithoutSlots AY⟩, ⟨WithoutSlots AZ⟩, ⟨WithoutSlots BA⟩, ⟨WithoutSlots BB⟩, ⟨WithoutSlots BC⟩, ⟨WithoutSlots BD⟩, ⟨WithoutSlots BE⟩, ⟨WithoutSlots BF⟩, ⟨WithoutSlots BG⟩, ⟨WithoutSlots BH⟩, ⟨WithoutSlots BI⟩, ⟨WithoutSlots BJ⟩, ⟨WithoutSlots BK⟩, ⟨WithoutSlots BL⟩, ⟨WithoutSlots BM⟩, ⟨WithoutSlots BN⟩, ⟨WithoutSlots BO⟩, ⟨WithoutSlots BP⟩, ⟨WithoutSlots BQ⟩, ⟨WithoutSlots BR⟩, ⟨WithoutSlots BS⟩, ⟨WithoutSlots BT⟩, ⟨WithoutSlots BU⟩, ⟨WithoutSlots BV⟩, ⟨WithoutSlots BW⟩, ⟨WithoutSlots BX⟩, ⟨WithoutSlots BY⟩, ⟨WithoutSlots BZ⟩, ⟨WithoutSlots CA⟩, ⟨WithoutSlots CB⟩, ⟨WithoutSlots CC⟩, ⟨WithoutSlots CD⟩, ⟨WithoutSlots CE⟩, ⟨WithoutSlots CF⟩, ⟨WithoutSlots CG⟩, ⟨WithoutSlots CH⟩, ⟨WithoutSlots CI⟩, ⟨WithoutSlots CJ⟩, ⟨WithoutSlots CK⟩, ⟨WithoutSlots CL⟩, ⟨WithoutSlots CM⟩, ⟨WithoutSlots CN⟩, ⟨WithoutSlots CO⟩, ⟨WithoutSlots CP⟩, ⟨WithoutSlots CQ⟩, ⟨WithoutSlots CR⟩, ⟨WithoutSlots CS⟩, ⟨WithoutSlots CT⟩, ⟨WithoutSlots CU⟩, ⟨WithoutSlots CV⟩, ⟨WithoutSlots CW⟩, ⟨WithoutSlots CX⟩, ⟨WithoutSlots CY⟩, ⟨WithoutSlots CZ⟩, ⟨WithoutSlots DA⟩, ⟨WithoutSlots DB⟩, ⟨WithoutSlots DC⟩, ⟨WithoutSlots DD⟩, ⟨WithoutSlots DE⟩, ⟨WithoutSlots DF⟩, ⟨WithoutSlots DG⟩, ⟨WithoutSlots DH⟩, ⟨WithoutSlots J⟩, ⟨WithoutSlots K⟩]
40no_slots_list→ [⟨WithoutSlots B⟩, ⟨WithoutSlots C⟩, ⟨WithoutSlots D⟩, ⟨WithoutSlots E⟩, ⟨WithoutSlots F⟩, ⟨WithoutSlots G⟩, ⟨WithoutSlots H⟩, ⟨WithoutSlots I⟩, ⟨WithoutSlots W⟩, ⟨WithoutSlots X⟩, ⟨WithoutSlots Y⟩, ⟨WithoutSlots Z⟩, ⟨WithoutSlots AA⟩, ⟨WithoutSlots AB⟩, ⟨WithoutSlots AC⟩, ⟨WithoutSlots AD⟩, ⟨WithoutSlots AE⟩, ⟨WithoutSlots AF⟩, ⟨WithoutSlots AG⟩, ⟨WithoutSlots AH⟩, ⟨WithoutSlots AI⟩, ⟨WithoutSlots AJ⟩, ⟨WithoutSlots AK⟩, ⟨WithoutSlots AL⟩, ⟨WithoutSlots AM⟩, ⟨WithoutSlots AN⟩, ⟨WithoutSlots AO⟩, ⟨WithoutSlots AP⟩, ⟨WithoutSlots AQ⟩, ⟨WithoutSlots AR⟩, ⟨WithoutSlots AS⟩, ⟨WithoutSlots AT⟩, ⟨WithoutSlots AU⟩, ⟨WithoutSlots AV⟩, ⟨WithoutSlots AW⟩, ⟨WithoutSlots AX⟩, ⟨WithoutSlots AY⟩, ⟨WithoutSlots AZ⟩, ⟨WithoutSlots BA⟩, ⟨WithoutSlots BB⟩, ⟨WithoutSlots BC⟩, ⟨WithoutSlots BD⟩, ⟨WithoutSlots BE⟩, ⟨WithoutSlots BF⟩, ⟨WithoutSlots BG⟩, ⟨WithoutSlots BH⟩, ⟨WithoutSlots BI⟩, ⟨WithoutSlots BJ⟩, ⟨WithoutSlots BK⟩, ⟨WithoutSlots BL⟩, ⟨WithoutSlots BM⟩, ⟨WithoutSlots BN⟩, ⟨WithoutSlots BO⟩, ⟨WithoutSlots BP⟩, ⟨WithoutSlots BQ⟩, ⟨WithoutSlots BR⟩, ⟨WithoutSlots BS⟩, ⟨WithoutSlots BT⟩, ⟨WithoutSlots BU⟩, ⟨WithoutSlots BV⟩, ⟨WithoutSlots BW⟩, ⟨WithoutSlots BX⟩, ⟨WithoutSlots BY⟩, ⟨WithoutSlots BZ⟩, ⟨WithoutSlots CA⟩, ⟨WithoutSlots CB⟩, ⟨WithoutSlots CC⟩, ⟨WithoutSlots CD⟩, ⟨WithoutSlots CE⟩, ⟨WithoutSlots CF⟩, ⟨WithoutSlots CG⟩, ⟨WithoutSlots CH⟩, ⟨WithoutSlots CI⟩, ⟨WithoutSlots CJ⟩, ⟨WithoutSlots CK⟩, ⟨WithoutSlots CL⟩, ⟨WithoutSlots CM⟩, ⟨WithoutSlots CN⟩, ⟨WithoutSlots CO⟩, ⟨WithoutSlots CP⟩, ⟨WithoutSlots CQ⟩, ⟨WithoutSlots CR⟩, ⟨WithoutSlots CS⟩, ⟨WithoutSlots CT⟩, ⟨WithoutSlots CU⟩, ⟨WithoutSlots CV⟩, ⟨WithoutSlots CW⟩, ⟨WithoutSlots CX⟩, ⟨WithoutSlots CY⟩, ⟨WithoutSlots CZ⟩, ⟨WithoutSlots DA⟩, ⟨WithoutSlots DB⟩, ⟨WithoutSlots DC⟩, ⟨WithoutSlots DD⟩, ⟨WithoutSlots DE⟩, ⟨WithoutSlots DF⟩, ⟨WithoutSlots DG⟩, ⟨WithoutSlots DH⟩, ⟨WithoutSlots J⟩, ⟨WithoutSlots K⟩] = [WithoutSlots(i, i+1, i+2) for i in range(count100)]41with_slots_list = [WithSlots(i, i+1, i+2) for i in range(count100)]with_slots_list ← [⟨WithSlots M⟩, ⟨WithSlots N⟩, ⟨WithSlots O⟩, ⟨WithSlots P⟩, ⟨WithSlots Q⟩, ⟨WithSlots R⟩, ⟨WithSlots S⟩, ⟨WithSlots T⟩, ⟨WithSlots DI⟩, ⟨WithSlots DJ⟩, ⟨WithSlots DK⟩, ⟨WithSlots DL⟩, ⟨WithSlots DM⟩, ⟨WithSlots DN⟩, ⟨WithSlots DO⟩, ⟨WithSlots DP⟩, ⟨WithSlots DQ⟩, ⟨WithSlots DR⟩, ⟨WithSlots DS⟩, ⟨WithSlots DT⟩, ⟨WithSlots DU⟩, ⟨WithSlots DV⟩, ⟨WithSlots DW⟩, ⟨WithSlots DX⟩, ⟨WithSlots DY⟩, ⟨WithSlots DZ⟩, ⟨WithSlots EA⟩, ⟨WithSlots EB⟩, ⟨WithSlots EC⟩, ⟨WithSlots ED⟩, ⟨WithSlots EE⟩, ⟨WithSlots EF⟩, ⟨WithSlots EG⟩, ⟨WithSlots EH⟩, ⟨WithSlots EI⟩, ⟨WithSlots EJ⟩, ⟨WithSlots EK⟩, ⟨WithSlots EL⟩, ⟨WithSlots EM⟩, ⟨WithSlots EN⟩, ⟨WithSlots EO⟩, ⟨WithSlots EP⟩, ⟨WithSlots EQ⟩, ⟨WithSlots ER⟩, ⟨WithSlots ES⟩, ⟨WithSlots ET⟩, ⟨WithSlots EU⟩, ⟨WithSlots EV⟩, ⟨WithSlots EW⟩, ⟨WithSlots EX⟩, ⟨WithSlots EY⟩, ⟨WithSlots EZ⟩, ⟨WithSlots FA⟩, ⟨WithSlots FB⟩, ⟨WithSlots FC⟩, ⟨WithSlots FD⟩, ⟨WithSlots FE⟩, ⟨WithSlots FF⟩, ⟨WithSlots FG⟩, ⟨WithSlots FH⟩, ⟨WithSlots FI⟩, ⟨WithSlots FJ⟩, ⟨WithSlots FK⟩, ⟨WithSlots FL⟩, ⟨WithSlots FM⟩, ⟨WithSlots FN⟩, ⟨WithSlots FO⟩, ⟨WithSlots FP⟩, ⟨WithSlots FQ⟩, ⟨WithSlots FR⟩, ⟨WithSlots FS⟩, ⟨WithSlots FT⟩, ⟨WithSlots FU⟩, ⟨WithSlots FV⟩, ⟨WithSlots FW⟩, ⟨WithSlots FX⟩, ⟨WithSlots FY⟩, ⟨WithSlots FZ⟩, ⟨WithSlots GA⟩, ⟨WithSlots GB⟩, ⟨WithSlots GC⟩, ⟨WithSlots GD⟩, ⟨WithSlots GE⟩, ⟨WithSlots GF⟩, ⟨WithSlots GG⟩, ⟨WithSlots GH⟩, ⟨WithSlots GI⟩, ⟨WithSlots GJ⟩, ⟨WithSlots GK⟩, ⟨WithSlots GL⟩, ⟨WithSlots GM⟩, ⟨WithSlots GN⟩, ⟨WithSlots GO⟩, ⟨WithSlots GP⟩, ⟨WithSlots GQ⟩, ⟨WithSlots GR⟩, ⟨WithSlots GS⟩, ⟨WithSlots GT⟩, ⟨WithSlots U⟩, ⟨WithSlots V⟩]
40no_slots_list = [WithoutSlots(i, i+1, i+2) for i in range(count)]41with_slots_list→ [⟨WithSlots M⟩, ⟨WithSlots N⟩, ⟨WithSlots O⟩, ⟨WithSlots P⟩, ⟨WithSlots Q⟩, ⟨WithSlots R⟩, ⟨WithSlots S⟩, ⟨WithSlots T⟩, ⟨WithSlots DI⟩, ⟨WithSlots DJ⟩, ⟨WithSlots DK⟩, ⟨WithSlots DL⟩, ⟨WithSlots DM⟩, ⟨WithSlots DN⟩, ⟨WithSlots DO⟩, ⟨WithSlots DP⟩, ⟨WithSlots DQ⟩, ⟨WithSlots DR⟩, ⟨WithSlots DS⟩, ⟨WithSlots DT⟩, ⟨WithSlots DU⟩, ⟨WithSlots DV⟩, ⟨WithSlots DW⟩, ⟨WithSlots DX⟩, ⟨WithSlots DY⟩, ⟨WithSlots DZ⟩, ⟨WithSlots EA⟩, ⟨WithSlots EB⟩, ⟨WithSlots EC⟩, ⟨WithSlots ED⟩, ⟨WithSlots EE⟩, ⟨WithSlots EF⟩, ⟨WithSlots EG⟩, ⟨WithSlots EH⟩, ⟨WithSlots EI⟩, ⟨WithSlots EJ⟩, ⟨WithSlots EK⟩, ⟨WithSlots EL⟩, ⟨WithSlots EM⟩, ⟨WithSlots EN⟩, ⟨WithSlots EO⟩, ⟨WithSlots EP⟩, ⟨WithSlots EQ⟩, ⟨WithSlots ER⟩, ⟨WithSlots ES⟩, ⟨WithSlots ET⟩, ⟨WithSlots EU⟩, ⟨WithSlots EV⟩, ⟨WithSlots EW⟩, ⟨WithSlots EX⟩, ⟨WithSlots EY⟩, ⟨WithSlots EZ⟩, ⟨WithSlots FA⟩, ⟨WithSlots FB⟩, ⟨WithSlots FC⟩, ⟨WithSlots FD⟩, ⟨WithSlots FE⟩, ⟨WithSlots FF⟩, ⟨WithSlots FG⟩, ⟨WithSlots FH⟩, ⟨WithSlots FI⟩, ⟨WithSlots FJ⟩, ⟨WithSlots FK⟩, ⟨WithSlots FL⟩, ⟨WithSlots FM⟩, ⟨WithSlots FN⟩, ⟨WithSlots FO⟩, ⟨WithSlots FP⟩, ⟨WithSlots FQ⟩, ⟨WithSlots FR⟩, ⟨WithSlots FS⟩, ⟨WithSlots FT⟩, ⟨WithSlots FU⟩, ⟨WithSlots FV⟩, ⟨WithSlots FW⟩, ⟨WithSlots FX⟩, ⟨WithSlots FY⟩, ⟨WithSlots FZ⟩, ⟨WithSlots GA⟩, ⟨WithSlots GB⟩, ⟨WithSlots GC⟩, ⟨WithSlots GD⟩, ⟨WithSlots GE⟩, ⟨WithSlots GF⟩, ⟨WithSlots GG⟩, ⟨WithSlots GH⟩, ⟨WithSlots GI⟩, ⟨WithSlots GJ⟩, ⟨WithSlots GK⟩, ⟨WithSlots GL⟩, ⟨WithSlots GM⟩, ⟨WithSlots GN⟩, ⟨WithSlots GO⟩, ⟨WithSlots GP⟩, ⟨WithSlots GQ⟩, ⟨WithSlots GR⟩, ⟨WithSlots GS⟩, ⟨WithSlots GT⟩, ⟨WithSlots U⟩, ⟨WithSlots V⟩] = [WithSlots(i, i+1, i+2) for i in range(count100)]4243# Estimate total size44total_no_slots→ 14400.0 = sum(sys<module 'sys' (built-in)>.getsizeof(obj) + sys.getsizeof(obj.__dict__(empty)) for obj in no_slots_list[:100][⟨WithoutSlots B⟩, ⟨WithoutSlots C⟩, ⟨WithoutSlots D⟩, ⟨WithoutSlots E⟩, ⟨WithoutSlots F⟩, ⟨WithoutSlots G⟩, ⟨WithoutSlots H⟩, ⟨WithoutSlots I⟩, ⟨WithoutSlots W⟩, ⟨WithoutSlots X⟩, ⟨WithoutSlots Y⟩, ⟨WithoutSlots Z⟩, ⟨WithoutSlots AA⟩, ⟨WithoutSlots AB⟩, ⟨WithoutSlots AC⟩, ⟨WithoutSlots AD⟩, ⟨WithoutSlots AE⟩, ⟨WithoutSlots AF⟩, ⟨WithoutSlots AG⟩, ⟨WithoutSlots AH⟩, ⟨WithoutSlots AI⟩, ⟨WithoutSlots AJ⟩, ⟨WithoutSlots AK⟩, ⟨WithoutSlots AL⟩, ⟨WithoutSlots AM⟩, ⟨WithoutSlots AN⟩, ⟨WithoutSlots AO⟩, ⟨WithoutSlots AP⟩, ⟨WithoutSlots AQ⟩, ⟨WithoutSlots AR⟩, ⟨WithoutSlots AS⟩, ⟨WithoutSlots AT⟩, ⟨WithoutSlots AU⟩, ⟨WithoutSlots AV⟩, ⟨WithoutSlots AW⟩, ⟨WithoutSlots AX⟩, ⟨WithoutSlots AY⟩, ⟨WithoutSlots AZ⟩, ⟨WithoutSlots BA⟩, ⟨WithoutSlots BB⟩, ⟨WithoutSlots BC⟩, ⟨WithoutSlots BD⟩, ⟨WithoutSlots BE⟩, ⟨WithoutSlots BF⟩, ⟨WithoutSlots BG⟩, ⟨WithoutSlots BH⟩, ⟨WithoutSlots BI⟩, ⟨WithoutSlots BJ⟩, ⟨WithoutSlots BK⟩, ⟨WithoutSlots BL⟩, ⟨WithoutSlots BM⟩, ⟨WithoutSlots BN⟩, ⟨WithoutSlots BO⟩, ⟨WithoutSlots BP⟩, ⟨WithoutSlots BQ⟩, ⟨WithoutSlots BR⟩, ⟨WithoutSlots BS⟩, ⟨WithoutSlots BT⟩, ⟨WithoutSlots BU⟩, ⟨WithoutSlots BV⟩, ⟨WithoutSlots BW⟩, ⟨WithoutSlots BX⟩, ⟨WithoutSlots BY⟩, ⟨WithoutSlots BZ⟩, ⟨WithoutSlots CA⟩, ⟨WithoutSlots CB⟩, ⟨WithoutSlots CC⟩, ⟨WithoutSlots CD⟩, ⟨WithoutSlots CE⟩, ⟨WithoutSlots CF⟩, ⟨WithoutSlots CG⟩, ⟨WithoutSlots CH⟩, ⟨WithoutSlots CI⟩, ⟨WithoutSlots CJ⟩, ⟨WithoutSlots CK⟩, ⟨WithoutSlots CL⟩, ⟨WithoutSlots CM⟩, ⟨WithoutSlots CN⟩, ⟨WithoutSlots CO⟩, ⟨WithoutSlots CP⟩, ⟨WithoutSlots CQ⟩, ⟨WithoutSlots CR⟩, ⟨WithoutSlots CS⟩, ⟨WithoutSlots CT⟩, ⟨WithoutSlots CU⟩, ⟨WithoutSlots CV⟩, ⟨WithoutSlots CW⟩, ⟨WithoutSlots CX⟩, ⟨WithoutSlots CY⟩, ⟨WithoutSlots CZ⟩, ⟨WithoutSlots DA⟩, ⟨WithoutSlots DB⟩, ⟨WithoutSlots DC⟩, ⟨WithoutSlots DD⟩, ⟨WithoutSlots DE⟩, ⟨WithoutSlots DF⟩, ⟨WithoutSlots DG⟩, ⟨WithoutSlots DH⟩, ⟨WithoutSlots J⟩, ⟨WithoutSlots K⟩]) / 100 * count10045total_with_slots→ 5600.0 = sum(sys<module 'sys' (built-in)>.getsizeof(obj) for obj in with_slots_list[:100][⟨WithSlots M⟩, ⟨WithSlots N⟩, ⟨WithSlots O⟩, ⟨WithSlots P⟩, ⟨WithSlots Q⟩, ⟨WithSlots R⟩, ⟨WithSlots S⟩, ⟨WithSlots T⟩, ⟨WithSlots DI⟩, ⟨WithSlots DJ⟩, ⟨WithSlots DK⟩, ⟨WithSlots DL⟩, ⟨WithSlots DM⟩, ⟨WithSlots DN⟩, ⟨WithSlots DO⟩, ⟨WithSlots DP⟩, ⟨WithSlots DQ⟩, ⟨WithSlots DR⟩, ⟨WithSlots DS⟩, ⟨WithSlots DT⟩, ⟨WithSlots DU⟩, ⟨WithSlots DV⟩, ⟨WithSlots DW⟩, ⟨WithSlots DX⟩, ⟨WithSlots DY⟩, ⟨WithSlots DZ⟩, ⟨WithSlots EA⟩, ⟨WithSlots EB⟩, ⟨WithSlots EC⟩, ⟨WithSlots ED⟩, ⟨WithSlots EE⟩, ⟨WithSlots EF⟩, ⟨WithSlots EG⟩, ⟨WithSlots EH⟩, ⟨WithSlots EI⟩, ⟨WithSlots EJ⟩, ⟨WithSlots EK⟩, ⟨WithSlots EL⟩, ⟨WithSlots EM⟩, ⟨WithSlots EN⟩, ⟨WithSlots EO⟩, ⟨WithSlots EP⟩, ⟨WithSlots EQ⟩, ⟨WithSlots ER⟩, ⟨WithSlots ES⟩, ⟨WithSlots ET⟩, ⟨WithSlots EU⟩, ⟨WithSlots EV⟩, ⟨WithSlots EW⟩, ⟨WithSlots EX⟩, ⟨WithSlots EY⟩, ⟨WithSlots EZ⟩, ⟨WithSlots FA⟩, ⟨WithSlots FB⟩, ⟨WithSlots FC⟩, ⟨WithSlots FD⟩, ⟨WithSlots FE⟩, ⟨WithSlots FF⟩, ⟨WithSlots FG⟩, ⟨WithSlots FH⟩, ⟨WithSlots FI⟩, ⟨WithSlots FJ⟩, ⟨WithSlots FK⟩, ⟨WithSlots FL⟩, ⟨WithSlots FM⟩, ⟨WithSlots FN⟩, ⟨WithSlots FO⟩, ⟨WithSlots FP⟩, ⟨WithSlots FQ⟩, ⟨WithSlots FR⟩, ⟨WithSlots FS⟩, ⟨WithSlots FT⟩, ⟨WithSlots FU⟩, ⟨WithSlots FV⟩, ⟨WithSlots FW⟩, ⟨WithSlots FX⟩, ⟨WithSlots FY⟩, ⟨WithSlots FZ⟩, ⟨WithSlots GA⟩, ⟨WithSlots GB⟩, ⟨WithSlots GC⟩, ⟨WithSlots GD⟩, ⟨WithSlots GE⟩, ⟨WithSlots GF⟩, ⟨WithSlots GG⟩, ⟨WithSlots GH⟩, ⟨WithSlots GI⟩, ⟨WithSlots GJ⟩, ⟨WithSlots GK⟩, ⟨WithSlots GL⟩, ⟨WithSlots GM⟩, ⟨WithSlots GN⟩, ⟨WithSlots GO⟩, ⟨WithSlots GP⟩, ⟨WithSlots GQ⟩, ⟨WithSlots GR⟩, ⟨WithSlots GS⟩, ⟨WithSlots GT⟩, ⟨WithSlots U⟩, ⟨WithSlots V⟩]) / 100 * count1004647print(f"{count100} instances:")48print(f"Without __slots__: ~{total_no_slots14400.0/1024:.1f} KB")49print(f"With __slots__: ~{total_with_slots5600.0/1024:.1f} KB")50print(f"Estimated savings: ~{(total_no_slots14400.0 - total_with_slots5600.0)/1024:.1f} KB")5152# Simple data class53print("\nSimple data class:")5455class Point:56 __slots__ = ['x', 'y']57 58 def __init__(self, x, y):59 self.x = x60 self.y = y6162# Create many points63points = [Point(i, i*2) for i in range(100)]output100 instances: Without __slots__: ~14.1 KB With __slots__: ~5.5 KB Estimated savings: ~8.6 KB Simple data class:self.x ← 0, self.y ← 0
pass 1 of 10058def __init__(self⟨Point GU⟩, x0, y0):59 self.x→ 0 = x060 self.y→ 0 = y0100 passes — pass 1 is the card above pass selfxyself.xself.y1 ⟨Point GU⟩ 0 0 0 0 2 ⟨Point GV⟩ 1 2 1 2 3 ⟨Point GW⟩ 2 4 2 4 4 ⟨Point GX⟩ 3 6 3 6 5 ⟨Point GY⟩ 4 8 4 8 6 ⟨Point GZ⟩ 5 10 5 10 7 ⟨Point HA⟩ 6 12 6 12 8 ⟨Point HB⟩ 7 14 7 14 9 ⟨Point HC⟩ 8 16 8 16 ⋯ 89 more passes ⋯ 99 ⟨Point HD⟩ 98 196 98 196 100 ⟨Point HE⟩ 99 198 99 198 points ← [⟨Point GU⟩, ⟨Point GV⟩, ⟨Point GW⟩, ⟨Point GX⟩, ⟨Point GY⟩, ⟨Point GZ⟩, ⟨Point HA⟩, ⟨Point HB⟩, ⟨Point HC⟩, ⟨Point HF⟩, ⟨Point HG⟩, ⟨Point HH⟩, ⟨Point HI⟩, ⟨Point HJ⟩, ⟨Point HK⟩, ⟨Point HL⟩, ⟨Point HM⟩, ⟨Point HN⟩, ⟨Point HO⟩, ⟨Point HP⟩, ⟨Point HQ⟩, ⟨Point HR⟩, ⟨Point HS⟩, ⟨Point HT⟩, ⟨Point HU⟩, ⟨Point HV⟩, ⟨Point HW⟩, ⟨Point HX⟩, ⟨Point HY⟩, ⟨Point HZ⟩, ⟨Point IA⟩, ⟨Point IB⟩, ⟨Point IC⟩, ⟨Point ID⟩, ⟨Point IE⟩, ⟨Point IF⟩, ⟨Point IG⟩, ⟨Point IH⟩, ⟨Point II⟩, ⟨Point IJ⟩, ⟨Point IK⟩, ⟨Point IL⟩, ⟨Point IM⟩, ⟨Point IN⟩, ⟨Point IO⟩, ⟨Point IP⟩, ⟨Point IQ⟩, ⟨Point IR⟩, ⟨Point IS⟩, ⟨Point IT⟩, ⟨Point IU⟩, ⟨Point IV⟩, ⟨Point IW⟩, ⟨Point IX⟩, ⟨Point IY⟩, ⟨Point IZ⟩, ⟨Point JA⟩, ⟨Point JB⟩, ⟨Point JC⟩, ⟨Point JD⟩, ⟨Point JE⟩, ⟨Point JF⟩, ⟨Point JG⟩, ⟨Point JH⟩, ⟨Point JI⟩, ⟨Point JJ⟩, ⟨Point JK⟩, ⟨Point JL⟩, ⟨Point JM⟩, ⟨Point JN⟩, ⟨Point JO⟩, ⟨Point JP⟩, ⟨Point JQ⟩, ⟨Point JR⟩, ⟨Point JS⟩, ⟨Point JT⟩, ⟨Point JU⟩, ⟨Point JV⟩, ⟨Point JW⟩, ⟨Point JX⟩, ⟨Point JY⟩, ⟨Point JZ⟩, ⟨Point KA⟩, ⟨Point KB⟩, ⟨Point KC⟩, ⟨Point KD⟩, ⟨Point KE⟩, ⟨Point KF⟩, ⟨Point KG⟩, ⟨Point KH⟩, ⟨Point KI⟩, ⟨Point KJ⟩, ⟨Point KK⟩, ⟨Point KL⟩, ⟨Point KM⟩, ⟨Point KN⟩, ⟨Point KO⟩, ⟨Point KP⟩, ⟨Point HD⟩, ⟨Point HE⟩]
62# Create many points63points→ [⟨Point GU⟩, ⟨Point GV⟩, ⟨Point GW⟩, ⟨Point GX⟩, ⟨Point GY⟩, ⟨Point GZ⟩, ⟨Point HA⟩, ⟨Point HB⟩, ⟨Point HC⟩, ⟨Point HF⟩, ⟨Point HG⟩, ⟨Point HH⟩, ⟨Point HI⟩, ⟨Point HJ⟩, ⟨Point HK⟩, ⟨Point HL⟩, ⟨Point HM⟩, ⟨Point HN⟩, ⟨Point HO⟩, ⟨Point HP⟩, ⟨Point HQ⟩, ⟨Point HR⟩, ⟨Point HS⟩, ⟨Point HT⟩, ⟨Point HU⟩, ⟨Point HV⟩, ⟨Point HW⟩, ⟨Point HX⟩, ⟨Point HY⟩, ⟨Point HZ⟩, ⟨Point IA⟩, ⟨Point IB⟩, ⟨Point IC⟩, ⟨Point ID⟩, ⟨Point IE⟩, ⟨Point IF⟩, ⟨Point IG⟩, ⟨Point IH⟩, ⟨Point II⟩, ⟨Point IJ⟩, ⟨Point IK⟩, ⟨Point IL⟩, ⟨Point IM⟩, ⟨Point IN⟩, ⟨Point IO⟩, ⟨Point IP⟩, ⟨Point IQ⟩, ⟨Point IR⟩, ⟨Point IS⟩, ⟨Point IT⟩, ⟨Point IU⟩, ⟨Point IV⟩, ⟨Point IW⟩, ⟨Point IX⟩, ⟨Point IY⟩, ⟨Point IZ⟩, ⟨Point JA⟩, ⟨Point JB⟩, ⟨Point JC⟩, ⟨Point JD⟩, ⟨Point JE⟩, ⟨Point JF⟩, ⟨Point JG⟩, ⟨Point JH⟩, ⟨Point JI⟩, ⟨Point JJ⟩, ⟨Point JK⟩, ⟨Point JL⟩, ⟨Point JM⟩, ⟨Point JN⟩, ⟨Point JO⟩, ⟨Point JP⟩, ⟨Point JQ⟩, ⟨Point JR⟩, ⟨Point JS⟩, ⟨Point JT⟩, ⟨Point JU⟩, ⟨Point JV⟩, ⟨Point JW⟩, ⟨Point JX⟩, ⟨Point JY⟩, ⟨Point JZ⟩, ⟨Point KA⟩, ⟨Point KB⟩, ⟨Point KC⟩, ⟨Point KD⟩, ⟨Point KE⟩, ⟨Point KF⟩, ⟨Point KG⟩, ⟨Point KH⟩, ⟨Point KI⟩, ⟨Point KJ⟩, ⟨Point KK⟩, ⟨Point KL⟩, ⟨Point KM⟩, ⟨Point KN⟩, ⟨Point KO⟩, ⟨Point KP⟩, ⟨Point HD⟩, ⟨Point HE⟩] = [Point(i, i*2) for i in range(100)]6465# Sample memory usage66sample_size→ 48 = sys<module 'sys' (built-in)>.getsizeof(points[0]⟨Point GU⟩)67print(f"Point with __slots__: {sample_size48} bytes each")68print(f"100 points: ~{sample_size48 * 100 / 1024:.1f} KB")6970# Complex object71print("\nComplex object:")7273class PersonNoSlots:74 def __init__(self, name, age, email, city):75 self.name = name76 self.age = age77 self.email = email78 self.city = city7980class PersonWithSlots:81 __slots__ = ['name', 'age', 'email', 'city']82 83 def __init__(self, name, age, email, city):84 self.name = name85 self.age = age86 self.email = email87 self.city = city8889p1 = PersonNoSlots("Alice", 30, "alice@example.com", "NYC")90p2 = PersonWithSlots("Alice", 30, "alice@example.com", "NYC")outputPoint with __slots__: 48 bytes each 100 points: ~4.7 KB Complex object:self.name ← Alice, self.age ← 30, self.email ← alice@example.com
73class PersonNoSlots:74 def __init__(self⟨PersonNoSlots KQ⟩, nameAlice, age30, emailalice@example.com, cityNYC):75 self.name→ Alice = nameAlice76 self.age→ 30 = age3077 self.email→ alice@example.com = emailalice@example.com78 self.city→ NYC = cityNYCp1 ← ⟨PersonNoSlots KQ⟩
89p1→ ⟨PersonNoSlots KQ⟩ = PersonNoSlots("Alice", 30, "alice@example.com", "NYC")90p2 = PersonWithSlots("Alice", 30, "alice@example.com", "NYC")self.name ← Alice, self.age ← 30, self.email ← alice@example.com
83def __init__(self⟨PersonWithSlots KR⟩, nameAlice, age30, emailalice@example.com, cityNYC):84 self.name→ Alice = nameAlice85 self.age→ 30 = age3086 self.email→ alice@example.com = emailalice@example.com87 self.city→ NYC = cityNYCp2 ← ⟨PersonWithSlots KR⟩, size1 ← 344, size2 ← 64, dataset_size ← 10000
89p1 = PersonNoSlots("Alice", 30, "alice@example.com", "NYC")90p2→ ⟨PersonWithSlots KR⟩ = PersonWithSlots("Alice", 30, "alice@example.com", "NYC")9192size1→ 344 = sys<module 'sys' (built-in)>.getsizeof(p1⟨PersonNoSlots KQ⟩) + sys.getsizeof(p1.__dict__{'name': 'Alice', 'age': 30, 'email': 'alice@example.com', 'city': 'NYC'})93size2→ 64 = sys<module 'sys' (built-in)>.getsizeof(p2⟨PersonWithSlots KR⟩)9495print(f"PersonNoSlots: {size1344} bytes")96print(f"PersonWithSlots: {size264} bytes")97print(f"Savings per instance: {size1344 - size264} bytes")9899# Large dataset100print("\nLarge dataset:")101102class Record:103 __slots__ = ['id', 'timestamp', 'value', 'status']104 105 def __init__(self, id, timestamp, value, status):106 self.id = id107 self.timestamp = timestamp108 self.value = value109 self.status = status110111# Simulate large dataset112dataset_size→ 10000 = 10000113print(f"Creating {dataset_size10000} records...")114115# Estimate memory (based on sample)116sample = Record(1, 1234567890, 42.5, "active")117record_size = sys.getsizeof(sample)outputPersonNoSlots: 344 bytes PersonWithSlots: 64 bytes Savings per instance: 280 bytes Large dataset: Creating 10000 records...self.id ← 1, self.timestamp ← 1234567890, self.value ← 42.5, self.status ← active
105def __init__(self⟨Record KS⟩, id1, timestamp1234567890, value42.5, statusactive):106 self.id→ 1 = id1107 self.timestamp→ 1234567890 = timestamp1234567890108 self.value→ 42.5 = value42.5109 self.status→ active = statusactivesample ← ⟨Record KS⟩, record_size ← 64, minutes_per_year ← 525600
115# Estimate memory (based on sample)116sample→ ⟨Record KS⟩ = Record(1, 1234567890, 42.5, "active")117record_size→ 64 = sys<module 'sys' (built-in)>.getsizeof(sample⟨Record KS⟩)118119print(f"Size per record: {record_size64} bytes")120print(f"Total for {dataset_size10000} records: ~{record_size64 * dataset_size / 1024 / 1024:.1f} MB")121122# Time series data123print("\nTime series data:")124125class DataPoint:126 __slots__ = ['timestamp', 'value']127 128 def __init__(self, timestamp, value):129 self.timestamp = timestamp130 self.value = value131132# Simulate 1 year of per-minute data133minutes_per_year→ 525600 = 365 * 24 * 60134point_size = sys<module 'sys' (built-in)>.getsizeof(DataPoint(0, 0.0))outputSize per record: 64 bytes Total for 10000 records: ~0.6 MB Time series data:self.timestamp ← 0, self.value ← 0.0
128def __init__(self⟨DataPoint KT⟩, timestamp0, value0.0):129 self.timestamp→ 0 = timestamp0130 self.value→ 0.0 = value0.0point_size ← 48, entity_count ← 1000
133minutes_per_year = 365 * 24 * 60134point_size→ 48 = sys<module 'sys' (built-in)>.getsizeof(DataPoint(0, 0.0))135136print(f"Data point size: {point_size48} bytes")137print(f"1 year (minute resolution): ~{point_size48 * minutes_per_year525600 / 1024 / 1024:.1f} MB")138139# Practical comparison140print("\nPractical comparison:")141142# Coordinates for game143class CoordNoSlots:144 def __init__(self, x, y, z):145 self.x = x146 self.y = y147 self.z = z148149class CoordWithSlots:150 __slots__ = ['x', 'y', 'z']151 152 def __init__(self, x, y, z):153 self.x = x154 self.y = y155 self.z = z156157# Simulate game world with many entities158entity_count→ 1000 = 1000159160# Sample sizes161no_slots = CoordNoSlots(0, 0, 0)162with_slots = CoordWithSlots(0, 0, 0)outputData point size: 48 bytes 1 year (minute resolution): ~24.1 MB Practical comparison:self.x ← 0, self.y ← 0, self.z ← 0
143class CoordNoSlots:144 def __init__(self⟨CoordNoSlots KU⟩, x0, y0, z0):145 self.x→ 0 = x0146 self.y→ 0 = y0147 self.z→ 0 = z0no_slots ← ⟨CoordNoSlots KU⟩
160# Sample sizes161no_slots→ ⟨CoordNoSlots KU⟩ = CoordNoSlots(0, 0, 0)162with_slots = CoordWithSlots(0, 0, 0)self.x ← 0, self.y ← 0, self.z ← 0
152def __init__(self⟨CoordWithSlots KV⟩, x0, y0, z0):153 self.x→ 0 = x0154 self.y→ 0 = y0155 self.z→ 0 = z0with_slots ← ⟨CoordWithSlots KV⟩, size_no ← 344, size_with ← 56
161no_slots = CoordNoSlots(0, 0, 0)162with_slots→ ⟨CoordWithSlots KV⟩ = CoordWithSlots(0, 0, 0)163164size_no→ 344 = sys<module 'sys' (built-in)>.getsizeof(no_slots⟨CoordNoSlots KU⟩) + sys.getsizeof(no_slots.__dict__{'x': 0, 'y': 0, 'z': 0})165size_with→ 56 = sys<module 'sys' (built-in)>.getsizeof(with_slots⟨CoordWithSlots KV⟩)166167print(f"{entity_count1000} game entities:")168print(f"Without __slots__: ~{size_no344 * entity_count1000 / 1024:.1f} KB")169print(f"With __slots__: ~{size_with56 * entity_count1000 / 1024:.1f} KB")170print(f"Memory saved: ~{(size_no344 - size_with56) * entity_count1000 / 1024:.1f} KB")output1000 game entities: Without __slots__: ~335.9 KB With __slots__: ~54.7 KB Memory saved: ~281.2 KB
The savings multiply quickly: 10,000 objects might save hundreds of kilobytes. For millions of objects, the difference can be gigabytes.
No Dynamic Attributes
"""No dynamic attributes with __slots__"""
# Dynamic attributes blocked
print("Dynamic attributes blocked:")
class User:
__slots__ = ['name', 'email']
def __init__(self, name, email):
self.name = name
self.email = email
user = User("Alice", "alice@example.com")
# Allowed attributes work
print(f"Name: {user.name}")
print(f"Email: {user.email}")
# Modifying allowed attributes works
user.name = "Alice Smith"
print(f"Updated name: {user.name}")
# Adding new attribute fails
try:
user.age = 30
except AttributeError as e:
print(f"Error adding 'age': {e}")
try:
user.city = "NYC"
except AttributeError as e:
print(f"Error adding 'city': {e}")
# No __dict__
print("\nNo __dict__:")
class NoDict:
__slots__ = ['x', 'y']
def __init__(self, x, y):
self.x = x
self.y = y
obj = NoDict(10, 20)
# __dict__ doesn't exist
print(f"Has __dict__: {hasattr(obj, '__dict__')}")
# Can't access __dict__
try:
print(obj.__dict__)
except AttributeError as e:
print(f"Error: {e}")
# __slots__ is available
print(f"__slots__: {obj.__slots__}")
# Deleting attributes
print("\nDeleting attributes:")
class Point:
__slots__ = ['x', 'y']
def __init__(self, x, y):
self.x = x
self.y = y
p = Point(5, 10)
print(f"Point: ({p.x}, {p.y})")
# Can delete slotted attributes
del p.x
print(f"Has x: {hasattr(p, 'x')}")
# Accessing deleted attribute fails
try:
print(p.x)
except AttributeError as e:
print(f"Error: {e}")
# Can reassign
p.x = 15
print(f"Reassigned x: {p.x}")
# Class attributes still work
print("\nClass attributes still work:")
class Config:
__slots__ = ['name']
# Class attributes are fine
DEFAULT_TIMEOUT = 30
VERSION = "1.0"
def __init__(self, name):
self.name = name
config = Config("prod")
print(f"Instance name: {config.name}")
print(f"Class DEFAULT_TIMEOUT: {config.DEFAULT_TIMEOUT}")
print(f"Class VERSION: {config.VERSION}")
# Can modify class attributes
Config.VERSION = "1.1"
print(f"Updated VERSION: {config.VERSION}")
# Methods still work
print("\nMethods still work:")
class Rectangle:
__slots__ = ['width', 'height']
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width * self.height
def perimeter(self):
return 2 * (self.width + self.height)
rect = Rectangle(10, 5)
print(f"Area: {rect.area()}")
print(f"Perimeter: {rect.perimeter()}")
# Properties work
print("\nProperties work:")
class Temperature:
__slots__ = ['_celsius']
def __init__(self, celsius):
self._celsius = celsius
@property
def celsius(self):
return self._celsius
@celsius.setter
def celsius(self, value):
self._celsius = value
@property
def fahrenheit(self):
return self._celsius * 9/5 + 32
temp = Temperature(25)
print(f"Celsius: {temp.celsius}")
print(f"Fahrenheit: {temp.fahrenheit}")
temp.celsius = 30
print(f"Updated - Celsius: {temp.celsius}, Fahrenheit: {temp.fahrenheit}")
# Weakref support
print("\nWeakref support:")
import weakref
# Without __weakref__ in __slots__, weakref fails
class NoWeakref:
__slots__ = ['value']
def __init__(self, value):
self.value = value
obj1 = NoWeakref(42)
try:
ref = weakref.ref(obj1)
except TypeError as e:
print(f"Error without __weakref__: {e}")
# Add __weakref__ to support weak references
class WithWeakref:
__slots__ = ['value', '__weakref__']
def __init__(self, value):
self.value = value
obj2 = WithWeakref(42)
ref = weakref.ref(obj2)
print(f"Weakref created: {ref()}")
print(f"Weakref value: {ref().value}")
# Pickle support
print("\nPickle support:")
import pickle
class PickleSlots:
__slots__ = ['name', 'value']
def __init__(self, name, value):
self.name = name
self.value = value
obj = PickleSlots("test", 123)
# Pickle and unpickle
pickled = pickle.dumps(obj)
restored = pickle.loads(pickled)
print(f"Original: {obj.name}, {obj.value}")
print(f"Restored: {restored.name}, {restored.value}")
# Practical example
print("\nPractical example:")
class ImmutablePoint:
__slots__ = ['_x', '_y']
def __init__(self, x, y):
object.__setattr__(self, '_x', x)
object.__setattr__(self, '_y', y)
@property
def x(self):
return self._x
@property
def y(self):
return self._y
def __setattr__(self, name, value):
raise AttributeError(f"Cannot modify immutable attribute '{name}'")
def __repr__(self):
return f"ImmutablePoint({self._x}, {self._y})"
p = ImmutablePoint(10, 20)
print(f"Point: {p}")
print(f"x={p.x}, y={p.y}")
# Cannot modify
try:
p.x = 30
except AttributeError as e:
print(f"Error: {e}")
# Cannot add attributes
try:
p.z = 40
except AttributeError as e:
print(f"Error: {e}")
"""No dynamic attributes with __slots__"""
1"""No dynamic attributes with __slots__"""23# Dynamic attributes blocked4print("Dynamic attributes blocked:")56class User:7 __slots__ = ['name', 'email']8 9 def __init__(self, name, email):10 self.name = name11 self.email = email1213user = User("Alice", "alice@example.com")outputDynamic attributes blocked:self.name ← Alice, self.email ← alice@example.com
9def __init__(self⟨User A⟩, nameAlice, emailalice@example.com):10 self.name→ Alice = nameAlice11 self.email→ alice@example.com = emailalice@example.comuser ← ⟨User A⟩, user.name ← Alice Smith
13user→ ⟨User A⟩ = User("Alice", "alice@example.com")1415# Allowed attributes work16print(f"Name: {user.nameAlice}")17print(f"Email: {user.emailalice@example.com}")1819# Modifying allowed attributes works20user.name→ Alice Smith = "Alice Smith"21print(f"Updated name: {user.nameAlice Smith}")outputName: Alice Email: alice@example.com Updated name: Alice Smithexcept AttributeError as e:
25 user.age = 3026except AttributeError as e:27 print(f"Error adding 'age': {e'User' object has no attribute 'age'}")outputError adding 'age': 'User' object has no attribute 'age'except AttributeError as e:
30 user.city = "NYC"31except AttributeError as e:32 print(f"Error adding 'city': {e'User' object has no attribute 'city'}")outputError adding 'city': 'User' object has no attribute 'city'print(" No __dict__:")
34# No __dict__35print("\nNo __dict__:")3637class NoDict:38 __slots__ = ['x', 'y']39 40 def __init__(self, x, y):41 self.x = x42 self.y = y4344obj = NoDict(10, 20)output No __dict__:self.x ← 10, self.y ← 20
40def __init__(self⟨NoDict B⟩, x10, y20):41 self.x→ 10 = x1042 self.y→ 20 = y20obj ← ⟨NoDict B⟩
44obj→ ⟨NoDict B⟩ = NoDict(10, 20)4546# __dict__ doesn't exist47print(f"Has __dict__: {hasattr(obj⟨NoDict B⟩, '__dict__')}")outputHas __dict__: Falsetry:
49# Can't access __dict__50try:51 print(obj.__dict__(empty))52except AttributeError as e:except AttributeError as e:
51 print(obj.__dict__)52except AttributeError as e:53 print(f"Error: {e'NoDict' object has no attribute '__dict__'}")outputError: 'NoDict' object has no attribute '__dict__'print(f"__slots__: {obj.__slots__}")
55# __slots__ is available56print(f"__slots__: {obj.__slots__['x', 'y']}")5758# Deleting attributes59print("\nDeleting attributes:")6061class Point:62 __slots__ = ['x', 'y']63 64 def __init__(self, x, y):65 self.x = x66 self.y = y6768p = Point(5, 10)69print(f"Point: ({p.x}, {p.y})")output__slots__: ['x', 'y'] Deleting attributes:self.x ← 5, self.y ← 10
64def __init__(self⟨Point C⟩, x5, y10):65 self.x→ 5 = x566 self.y→ 10 = y10p ← ⟨Point C⟩
68p→ ⟨Point C⟩ = Point(5, 10)69print(f"Point: ({p.x5}, {p.y10})")7071# Can delete slotted attributes72del p.x73print(f"Has x: {hasattr(p⟨Point C⟩, 'x')}")outputPoint: (5, 10) Has x: Falsetry:
75# Accessing deleted attribute fails76try:77 print(p.x(empty))78except AttributeError as e:except AttributeError as e:
77 print(p.x)78except AttributeError as e:79 print(f"Error: {e'Point' object has no attribute 'x'}")outputError: 'Point' object has no attribute 'x'p.x ← 15, DEFAULT_TIMEOUT ← (empty), VERSION ← (empty)
81# Can reassign82p.x→ 15 = 1583print(f"Reassigned x: {p.x15}")8485# Class attributes still work86print("\nClass attributes still work:")8788class Config:89 __slots__ = ['name']90 91 # Class attributes are fine92 DEFAULT_TIMEOUT→ (empty) = 3093 VERSION→ (empty) = "1.0"94 95 def __init__(self, name):96 self.name = name9798config = Config("prod")99print(f"Instance name: {config.name}")outputReassigned x: 15 Class attributes still work:self.name ← prod
95def __init__(self⟨Config D⟩, nameprod):96 self.name→ prod = nameprodconfig ← ⟨Config D⟩, Config.VERSION ← 1.1
98config→ ⟨Config D⟩ = Config("prod")99print(f"Instance name: {config.nameprod}")100print(f"Class DEFAULT_TIMEOUT: {config.DEFAULT_TIMEOUT30}")101print(f"Class VERSION: {config.VERSION1.0}")102103# Can modify class attributes104Config.VERSION→ 1.1 = "1.1"105print(f"Updated VERSION: {config.VERSION1.1}")106107# Methods still work108print("\nMethods still work:")109110class Rectangle:111 __slots__ = ['width', 'height']112 113 def __init__(self, width, height):114 self.width = width115 self.height = height116 117 def area(self):118 return self.width * self.height119 120 def perimeter(self):121 return 2 * (self.width + self.height)122123rect = Rectangle(10, 5)124print(f"Area: {rect.area()}")outputInstance name: prod Class DEFAULT_TIMEOUT: 30 Class VERSION: 1.0 Updated VERSION: 1.1 Methods still work:self.width ← 10, self.height ← 5
113def __init__(self⟨Rectangle E⟩, width10, height5):114 self.width→ 10 = width10115 self.height→ 5 = height5rect ← ⟨Rectangle E⟩
123rect→ ⟨Rectangle E⟩ = Rectangle(10, 5)124print(f"Area: {rect⟨Rectangle E⟩.area()}")125print(f"Perimeter: {rect.perimeter()}")def area(self):
117def area(self⟨Rectangle E⟩):118 return self.width10 * self.height5print(f"Area: {rect.area()}")
123rect = Rectangle(10, 5)124print(f"Area: {rect⟨Rectangle E⟩.area()}")125print(f"Perimeter: {rect⟨Rectangle E⟩.perimeter()}")outputArea: 50def perimeter(self):
120def perimeter(self⟨Rectangle E⟩):121 return 2 * (self.width10 + self.height5)print(f"Perimeter: {rect.perimeter()}")
124print(f"Area: {rect.area()}")125print(f"Perimeter: {rect⟨Rectangle E⟩.perimeter()}")126127# Properties work128print("\nProperties work:")129130class Temperature:131 __slots__ = ['_celsius']132 133 def __init__(self, celsius):134 self._celsius = celsius135 136 @property137 def celsius(self):138 return self._celsius139 140 @celsius.setter141 def celsius(self, value):142 self._celsius = value143 144 @property145 def fahrenheit(self):146 return self._celsius * 9/5 + 32147148temp = Temperature(25)149print(f"Celsius: {temp.celsius}")outputPerimeter: 30 Properties work:self._celsius ← 25
133def __init__(self⟨Temperature F⟩, celsius25):134 self._celsius→ 25 = celsius25temp ← ⟨Temperature F⟩
148temp→ ⟨Temperature F⟩ = Temperature(25)149print(f"Celsius: {temp.celsius25}")150print(f"Fahrenheit: {temp.fahrenheit}")def celsius(self):
pass 1 of 2136@property137def celsius(self⟨Temperature F⟩):138 return self._celsius25print(f"Celsius: {temp.celsius}")
148temp = Temperature(25)149print(f"Celsius: {temp.celsius25}")150print(f"Fahrenheit: {temp.fahrenheit77.0}")outputCelsius: 25def fahrenheit(self):
pass 1 of 2144@property145def fahrenheit(self⟨Temperature F⟩):146 return self._celsius25 * 9/5 + 32print(f"Fahrenheit: {temp.fahrenheit}")
149print(f"Celsius: {temp.celsius}")150print(f"Fahrenheit: {temp.fahrenheit77.0}")151152temp.celsius = 30153print(f"Updated - Celsius: {temp.celsius}, Fahrenheit: {temp.fahrenheit}")outputFahrenheit: 77.0self._celsius ← 30
140@celsius.setter141def celsius(self⟨Temperature F⟩, value30):142 self._celsius→ 30 = value30temp.celsius ← 30
152temp.celsius→ 30 = 30153print(f"Updated - Celsius: {temp.celsius30}, Fahrenheit: {temp.fahrenheit86.0}")def celsius(self):
pass 2 of 2136@property137def celsius(self⟨Temperature F⟩):138 return self._celsius30def fahrenheit(self):
pass 2 of 2144@property145def fahrenheit(self⟨Temperature F⟩):146 return self._celsius30 * 9/5 + 32print(f"Updated - Celsius: {temp.celsius}, Fahrenheit: {temp.fahrenhei…
152temp.celsius = 30153print(f"Updated - Celsius: {temp.celsius30}, Fahrenheit: {temp.fahrenheit86.0}")154155# Weakref support156print("\nWeakref support:")157158import weakref159160# Without __weakref__ in __slots__, weakref fails161class NoWeakref:162 __slots__ = ['value']163 164 def __init__(self, value):165 self.value = value166167obj1 = NoWeakref(42)outputUpdated - Celsius: 30, Fahrenheit: 86.0 Weakref support:self.value ← 42
164def __init__(self⟨NoWeakref G⟩, value42):165 self.value→ 42 = value42obj1 ← ⟨NoWeakref G⟩
167obj1→ ⟨NoWeakref G⟩ = NoWeakref(42)try:
169try:170 ref = weakref<module 'weakref' from '/usr/local/lib/python3.12/weakref.py'>.ref(obj1⟨NoWeakref G⟩)171except TypeError as e:except TypeError as e:
170 ref = weakref.ref(obj1)171except TypeError as e:172 print(f"Error without __weakref__: {ecannot create weak reference to 'NoWeakref' object}")outputError without __weakref__: cannot create weak reference to 'NoWeakref' object__slots__ = ['value', '__weakref__']
175class WithWeakref:176 __slots__ = ['value', '__weakref__']177 178 def __init__(self, value):179 self.value = value180181obj2 = WithWeakref(42)182ref = weakref.ref(obj2)self.value ← 42
178def __init__(self⟨WithWeakref H⟩, value42):179 self.value→ 42 = value42obj2 ← ⟨WithWeakref H⟩, ref ← ⟨weakref at ⟨addr I⟩; to 'WithWeakref' H⟩
181obj2→ ⟨WithWeakref H⟩ = WithWeakref(42)182ref→ ⟨weakref at ⟨addr I⟩; to 'WithWeakref' H⟩ = weakref<module 'weakref' from '/usr/local/lib/python3.12/weakref.py'>.ref(obj2⟨WithWeakref H⟩)183print(f"Weakref created: {ref()}")184print(f"Weakref value: {ref().value}")185186# Pickle support187print("\nPickle support:")188189import pickle190191class PickleSlots:192 __slots__ = ['name', 'value']193 194 def __init__(self, name, value):195 self.name = name196 self.value = value197198obj = PickleSlots("test", 123)outputWeakref created: ⟨WithWeakref H⟩ Weakref value: 42 Pickle support:self.name ← test, self.value ← 123
194def __init__(self⟨PickleSlots J⟩, nametest, value123):195 self.name→ test = nametest196 self.value→ 123 = value123obj ← ⟨PickleSlots J⟩, pickled ← b'\x80\x04\x95?\x00\x00\x00\x00\x00\x00\x00\x8c\x08__main__\x94\x8c\x0bPickleSlots\x94\x93\x94)\x81\x94N}\x94(\x8c\x04name\x94\x8c\x04test\x94\x8c\x05value\x94K{u\x86\x94b.'
198obj→ ⟨PickleSlots J⟩ = PickleSlots("test", 123)199200# Pickle and unpickle201pickled→ b'\x80\x04\x95?\x00\x00\x00\x00\x00\x00\x00\x8c\x08__main__\x94\x8c\x0bPickleSlots\x94\x93\x94)\x81\x94N}\x94(\x8c\x04name\x94\x8c\x04test\x94\x8c\x05value\x94K{u\x86\x94b.' = pickle<module 'pickle' from '/usr/local/lib/python3.12/pickle.py'>.dumps(obj⟨PickleSlots J⟩)202restored→ ⟨PickleSlots B⟩ = pickle<module 'pickle' from '/usr/local/lib/python3.12/pickle.py'>.loads(pickledb'\x80\x04\x95?\x00\x00\x00\x00\x00\x00\x00\x8c\x08__main__\x94\x8c\x0bPickleSlots\x94\x93\x94)\x81\x94N}\x94(\x8c\x04name\x94\x8c\x04test\x94\x8c\x05value\x94K{u\x86\x94b.')203204print(f"Original: {obj.nametest}, {obj.value123}")205print(f"Restored: {restored.nametest}, {restored.value123}")206207# Practical example208print("\nPractical example:")209210class ImmutablePoint:211 __slots__ = ['_x', '_y']212 213 def __init__(self, x, y):214 object.__setattr__(self, '_x', x)215 object.__setattr__(self, '_y', y)216 217 @property218 def x(self):219 return self._x220 221 @property222 def y(self):223 return self._y224 225 def __setattr__(self, name, value):226 raise AttributeError(f"Cannot modify immutable attribute '{name}'")227 228 def __repr__(self):229 return f"ImmutablePoint({self._x}, {self._y})"230231p = ImmutablePoint(10, 20)232print(f"Point: {p}")outputOriginal: test, 123 Restored: test, 123 Practical example:def __init__(self, x, y):
213def __init__(self(empty), x10, y20):214 object.__setattr__(self, '_x', x10)215 object.__setattr__(self, '_y', y20)p ← ImmutablePoint(10, 20)
231p→ ImmutablePoint(10, 20) = ImmutablePoint(10, 20)232print(f"Point: {pImmutablePoint(10, 20)}")233print(f"x={p.x10}, y={p.y20}")outputPoint: ImmutablePoint(10, 20)def x(self):
217@property218def x(selfImmutablePoint(10, 20)):219 return self._x10def y(self):
221@property222def y(selfImmutablePoint(10, 20)):223 return self._y20print(f"x={p.x}, y={p.y}")
232print(f"Point: {p}")233print(f"x={p.x10}, y={p.y20}")outputx=10, y=20def __setattr__(self, name, value):
pass 1 of 2225def __setattr__(selfImmutablePoint(10, 20), namex, value30):226 raise AttributeError(f"Cannot modify immutable attribute '{namex}'")except AttributeError as e:
237 p.x = 30238except AttributeError as e:239 print(f"Error: {eCannot modify immutable attribute 'x'}")outputError: Cannot modify immutable attribute 'x'def __setattr__(self, name, value):
pass 2 of 2225def __setattr__(selfImmutablePoint(10, 20), namez, value40):226 raise AttributeError(f"Cannot modify immutable attribute '{namez}'")except AttributeError as e:
243 p.z = 40244except AttributeError as e:245 print(f"Error: {eCannot modify immutable attribute 'z'}")outputError: Cannot modify immutable attribute 'z'
This restriction is both a benefit (catches typos, enforces structure) and a limitation (no monkey-patching, no dynamic attributes).
Inheritance with __slots__
"""__slots__ with inheritance"""
# Basic inheritance
print("Basic inheritance:")
class Base:
__slots__ = ['x']
def __init__(self, x):
self.x = x
class Derived(Base):
__slots__ = ['y'] # Only add new slots
def __init__(self, x, y):
super().__init__(x)
self.y = y
obj = Derived(10, 20)
print(f"x={obj.x}, y={obj.y}")
print(f"Base __slots__: {Base.__slots__}")
print(f"Derived __slots__: {Derived.__slots__}")
# Combined slots are inherited
try:
obj.z = 30
except AttributeError as e:
print(f"Error: {e}")
# Empty slots in derived
print("\nEmpty slots in derived:")
class BaseClass:
__slots__ = ['a', 'b']
def __init__(self, a, b):
self.a = a
self.b = b
class DerivedClass(BaseClass):
__slots__ = [] # No new slots
def method(self):
return self.a + self.b
obj = DerivedClass(5, 10)
print(f"a={obj.a}, b={obj.b}")
print(f"method()={obj.method()}")
# Parent without __slots__
print("\nParent without __slots__:")
class ParentNoSlots:
def __init__(self, x):
self.x = x
class ChildWithSlots(ParentNoSlots):
__slots__ = ['y']
def __init__(self, x, y):
super().__init__(x)
self.y = y
obj = ChildWithSlots(10, 20)
# Parent has __dict__, child has slots
print(f"Has __dict__: {hasattr(obj, '__dict__')}")
print(f"__dict__: {obj.__dict__}") # Contains parent attributes
# Can add attributes to parent's __dict__
obj.z = 30
print(f"Added z: {obj.z}")
# But child's slotted attributes are separate
print(f"y (slotted): {obj.y}")
# Child without __slots__
print("\nChild without __slots__:")
class ParentWithSlots:
__slots__ = ['x']
def __init__(self, x):
self.x = x
class ChildNoSlots(ParentWithSlots):
# No __slots__ means __dict__ is created
def __init__(self, x, y):
super().__init__(x)
self.y = y # Stored in __dict__
obj = ChildNoSlots(10, 20)
print(f"x (slotted): {obj.x}")
print(f"y (dict): {obj.y}")
print(f"Has __dict__: {hasattr(obj, '__dict__')}")
# Can add dynamic attributes
obj.z = 30
print(f"Added z: {obj.z}")
# Multiple inheritance
print("\nMultiple inheritance:")
class A:
__slots__ = ['a']
class B(A):
__slots__ = ['b']
class C(B):
__slots__ = ['c']
def __init__(self, a, b, c):
self.a = a
self.b = b
self.c = c
obj = C(1, 2, 3)
print(f"a={obj.a}, b={obj.b}, c={obj.c}")
# Diamond inheritance
print("\nDiamond inheritance:")
class Base2:
__slots__ = ['value']
class Left(Base2):
__slots__ = ['left_value']
# For diamond to work, only one branch can have non-empty __slots__
class Right(Base2):
__slots__ = [] # Empty slots - avoids layout conflict
class Diamond(Left, Right):
__slots__ = ['diamond_value']
def __init__(self, value, left, diamond):
self.value = value
self.left_value = left
self.diamond_value = diamond
obj = Diamond(1, 2, 3)
print(f"value={obj.value}, left={obj.left_value}, diamond={obj.diamond_value}")
# Override with __dict__
print("\nOverride with __dict__:")
class Parent:
__slots__ = ['x']
class Child(Parent):
__slots__ = ['y', '__dict__'] # Add __dict__ explicitly
def __init__(self, x, y):
self.x = x
self.y = y
obj = Child(10, 20)
print(f"x={obj.x}, y={obj.y}")
# Can now add dynamic attributes
obj.z = 30
print(f"Added z: {obj.z}")
print(f"__dict__: {obj.__dict__}")
# Mixin classes
print("\nMixin classes:")
class SlottedBase:
__slots__ = ['id', 'name']
class Mixin:
def get_info(self):
return f"{self.name} (ID: {self.id})"
class ConcreteClass(SlottedBase, Mixin):
__slots__ = ['email']
def __init__(self, id, name, email):
self.id = id
self.name = name
self.email = email
obj = ConcreteClass(1, "Alice", "alice@example.com")
print(f"Info: {obj.get_info()}")
print(f"Email: {obj.email}")
# Practical example
print("\nPractical example:")
# Shape hierarchy
class Shape:
__slots__ = ['color']
def __init__(self, color):
self.color = color
class Circle(Shape):
__slots__ = ['radius']
def __init__(self, color, radius):
super().__init__(color)
self.radius = radius
def area(self):
import math
return math.pi * self.radius ** 2
class Rectangle(Shape):
__slots__ = ['width', 'height']
def __init__(self, color, width, height):
super().__init__(color)
self.width = width
self.height = height
def area(self):
return self.width * self.height
circle = Circle("red", 5)
rectangle = Rectangle("blue", 10, 20)
print(f"Circle: color={circle.color}, radius={circle.radius}, area={circle.area():.2f}")
print(f"Rectangle: color={rectangle.color}, width={rectangle.width}, height={rectangle.height}, area={rectangle.area()}")
"""__slots__ with inheritance"""
1"""__slots__ with inheritance"""23# Basic inheritance4print("Basic inheritance:")56class Base:7 __slots__ = ['x']8 9 def __init__(self, x):10 self.x = x1112class Derived(Base):13 __slots__ = ['y'] # Only add new slots14 15 def __init__(self, x, y):16 super().__init__(x)17 self.y = y1819obj = Derived(10, 20)20print(f"x={obj.x}, y={obj.y}")outputBasic inheritance:def __init__(self, x, y):
15def __init__(self⟨Derived A⟩, x10, y20):16 super().__init__(x)17 self.y = yself.x ← 10
9def __init__(self⟨Derived A⟩, x10):10 self.x→ 10 = x10self.y ← 20
16super().__init__(x)17self.y→ 20 = y20obj ← ⟨Derived A⟩
19obj→ ⟨Derived A⟩ = Derived(10, 20)20print(f"x={obj.x10}, y={obj.y20}")21print(f"Base __slots__: {Base.__slots__['x']}")22print(f"Derived __slots__: {Derived.__slots__['y']}")outputx=10, y=20 Base __slots__: ['x'] Derived __slots__: ['y']except AttributeError as e:
26 obj.z = 3027except AttributeError as e:28 print(f"Error: {e'Derived' object has no attribute 'z'}")outputError: 'Derived' object has no attribute 'z'print(" Empty slots in derived:")
30# Empty slots in derived31print("\nEmpty slots in derived:")3233class BaseClass:34 __slots__ = ['a', 'b']35 36 def __init__(self, a, b):37 self.a = a38 self.b = b3940class DerivedClass(BaseClass):41 __slots__ = [] # No new slots42 43 def method(self):44 return self.a + self.b4546obj = DerivedClass(5, 10)47print(f"a={obj.a}, b={obj.b}")output Empty slots in derived:self.a ← 5, self.b ← 10
36def __init__(self⟨DerivedClass B⟩, a5, b10):37 self.a→ 5 = a538 self.b→ 10 = b10obj ← ⟨DerivedClass B⟩
46obj→ ⟨DerivedClass B⟩ = DerivedClass(5, 10)47print(f"a={obj.a5}, b={obj.b10}")48print(f"method()={obj⟨DerivedClass B⟩.method()}")outputa=5, b=10def method(self):
43def method(self⟨DerivedClass B⟩):44 return self.a5 + self.b10print(f"method()={obj.method()}")
47print(f"a={obj.a}, b={obj.b}")48print(f"method()={obj⟨DerivedClass B⟩.method()}")4950# Parent without __slots__51print("\nParent without __slots__:")5253class ParentNoSlots:54 def __init__(self, x):55 self.x = x5657class ChildWithSlots(ParentNoSlots):58 __slots__ = ['y']59 60 def __init__(self, x, y):61 super().__init__(x)62 self.y = y6364obj = ChildWithSlots(10, 20)outputmethod()=15 Parent without __slots__:def __init__(self, x, y):
60def __init__(self⟨ChildWithSlots C⟩, x10, y20):61 super().__init__(x)62 self.y = yself.x ← 10
53class ParentNoSlots:54 def __init__(self⟨ChildWithSlots C⟩, x10):55 self.x→ 10 = x10self.y ← 20
61super().__init__(x)62self.y→ 20 = y20obj ← ⟨ChildWithSlots C⟩, obj.z ← 30
64obj→ ⟨ChildWithSlots C⟩ = ChildWithSlots(10, 20)6566# Parent has __dict__, child has slots67print(f"Has __dict__: {hasattr(obj⟨ChildWithSlots C⟩, '__dict__')}")68print(f"__dict__: {obj.__dict__{'x': 10}}") # Contains parent attributes6970# Can add attributes to parent's __dict__71obj.z→ 30 = 3072print(f"Added z: {obj.z30}")7374# But child's slotted attributes are separate75print(f"y (slotted): {obj.y20}")7677# Child without __slots__78print("\nChild without __slots__:")7980class ParentWithSlots:81 __slots__ = ['x']82 83 def __init__(self, x):84 self.x = x8586class ChildNoSlots(ParentWithSlots):87 # No __slots__ means __dict__ is created88 def __init__(self, x, y):89 super().__init__(x)90 self.y = y # Stored in __dict__9192obj = ChildNoSlots(10, 20)93print(f"x (slotted): {obj.x}")outputHas __dict__: True __dict__: {'x': 10} Added z: 30 y (slotted): 20 Child without __slots__:def __init__(self, x, y):
87# No __slots__ means __dict__ is created88def __init__(self⟨ChildNoSlots D⟩, x10, y20):89 super().__init__(x)90 self.y = y # Stored in __dict__self.x ← 10
83def __init__(self⟨ChildNoSlots D⟩, x10):84 self.x→ 10 = x10self.y ← 20
89super().__init__(x)90self.y→ 20 = y20 # Stored in __dict__obj ← ⟨ChildNoSlots D⟩, obj.z ← 30
92obj→ ⟨ChildNoSlots D⟩ = ChildNoSlots(10, 20)93print(f"x (slotted): {obj.x10}")94print(f"y (dict): {obj.y20}")95print(f"Has __dict__: {hasattr(obj⟨ChildNoSlots D⟩, '__dict__')}")9697# Can add dynamic attributes98obj.z→ 30 = 3099print(f"Added z: {obj.z30}")100101# Multiple inheritance102print("\nMultiple inheritance:")103104class A:105 __slots__ = ['a']106107class B(A):108 __slots__ = ['b']109110class C(B):111 __slots__ = ['c']112113 def __init__(self, a, b, c):114 self.a = a115 self.b = b116 self.c = c117118obj = C(1, 2, 3)119print(f"a={obj.a}, b={obj.b}, c={obj.c}")outputx (slotted): 10 y (dict): 20 Has __dict__: True Added z: 30 Multiple inheritance:self.a ← 1, self.b ← 2, self.c ← 3
113def __init__(self⟨C E⟩, a1, b2, c3):114 self.a→ 1 = a1115 self.b→ 2 = b2116 self.c→ 3 = c3obj ← ⟨C E⟩
118obj→ ⟨C E⟩ = C(1, 2, 3)119print(f"a={obj.a1}, b={obj.b2}, c={obj.c3}")120121# Diamond inheritance122print("\nDiamond inheritance:")123124class Base2:125 __slots__ = ['value']126127class Left(Base2):128 __slots__ = ['left_value']129130# For diamond to work, only one branch can have non-empty __slots__131class Right(Base2):132 __slots__ = [] # Empty slots - avoids layout conflict133134class Diamond(Left, Right):135 __slots__ = ['diamond_value']136137 def __init__(self, value, left, diamond):138 self.value = value139 self.left_value = left140 self.diamond_value = diamond141142obj = Diamond(1, 2, 3)143print(f"value={obj.value}, left={obj.left_value}, diamond={obj.diamond_value}")outputa=1, b=2, c=3 Diamond inheritance:self.value ← 1, self.left_value ← 2, self.diamond_value ← 3
137def __init__(self⟨Diamond F⟩, value1, left2, diamond3):138 self.value→ 1 = value1139 self.left_value→ 2 = left2140 self.diamond_value→ 3 = diamond3obj ← ⟨Diamond F⟩
142obj→ ⟨Diamond F⟩ = Diamond(1, 2, 3)143print(f"value={obj.value1}, left={obj.left_value2}, diamond={obj.diamond_value3}")144145# Override with __dict__146print("\nOverride with __dict__:")147148class Parent:149 __slots__ = ['x']150151class Child(Parent):152 __slots__ = ['y', '__dict__'] # Add __dict__ explicitly153 154 def __init__(self, x, y):155 self.x = x156 self.y = y157158obj = Child(10, 20)159print(f"x={obj.x}, y={obj.y}")outputvalue=1, left=2, diamond=3 Override with __dict__:self.x ← 10, self.y ← 20
154def __init__(self⟨Child G⟩, x10, y20):155 self.x→ 10 = x10156 self.y→ 20 = y20obj ← ⟨Child G⟩, obj.z ← 30
158obj→ ⟨Child G⟩ = Child(10, 20)159print(f"x={obj.x10}, y={obj.y20}")160161# Can now add dynamic attributes162obj.z→ 30 = 30163print(f"Added z: {obj.z30}")164print(f"__dict__: {obj.__dict__{'z': 30}}")165166# Mixin classes167print("\nMixin classes:")168169class SlottedBase:170 __slots__ = ['id', 'name']171172class Mixin:173 def get_info(self):174 return f"{self.name} (ID: {self.id})"175176class ConcreteClass(SlottedBase, Mixin):177 __slots__ = ['email']178 179 def __init__(self, id, name, email):180 self.id = id181 self.name = name182 self.email = email183184obj = ConcreteClass(1, "Alice", "alice@example.com")185print(f"Info: {obj.get_info()}")outputx=10, y=20 Added z: 30 __dict__: {'z': 30} Mixin classes:self.id ← 1, self.name ← Alice, self.email ← alice@example.com
179def __init__(self⟨ConcreteClass H⟩, id1, nameAlice, emailalice@example.com):180 self.id→ 1 = id1181 self.name→ Alice = nameAlice182 self.email→ alice@example.com = emailalice@example.comobj ← ⟨ConcreteClass H⟩
184obj→ ⟨ConcreteClass H⟩ = ConcreteClass(1, "Alice", "alice@example.com")185print(f"Info: {obj⟨ConcreteClass H⟩.get_info()}")186print(f"Email: {obj.email}")def get_info(self):
172class Mixin:173 def get_info(self⟨ConcreteClass H⟩):174 return f"{self.nameAlice} (ID: {self.id1})"print(f"Info: {obj.get_info()}")
184obj = ConcreteClass(1, "Alice", "alice@example.com")185print(f"Info: {obj⟨ConcreteClass H⟩.get_info()}")186print(f"Email: {obj.emailalice@example.com}")187188# Practical example189print("\nPractical example:")190191# Shape hierarchy192class Shape:193 __slots__ = ['color']194 195 def __init__(self, color):196 self.color = color197198class Circle(Shape):199 __slots__ = ['radius']200 201 def __init__(self, color, radius):202 super().__init__(color)203 self.radius = radius204 205 def area(self):206 import math207 return math.pi * self.radius ** 2208209class Rectangle(Shape):210 __slots__ = ['width', 'height']211 212 def __init__(self, color, width, height):213 super().__init__(color)214 self.width = width215 self.height = height216 217 def area(self):218 return self.width * self.height219220circle = Circle("red", 5)221rectangle = Rectangle("blue", 10, 20)outputInfo: Alice (ID: 1) Email: alice@example.com Practical example:def __init__(self, color, radius):
201def __init__(self⟨Circle I⟩, colorred, radius5):202 super().__init__(color)203 self.radius = radiusself.color ← red
pass 1 of 2195def __init__(self⟨Circle I⟩, colorred):196 self.color→ red = colorredself.radius ← 5
202super().__init__(color)203self.radius→ 5 = radius5circle ← ⟨Circle I⟩
220circle→ ⟨Circle I⟩ = Circle("red", 5)221rectangle = Rectangle("blue", 10, 20)def __init__(self, color, width, height):
212def __init__(self⟨Rectangle J⟩, colorblue, width10, height20):213 super().__init__(color)214 self.width = widthself.color ← blue
pass 2 of 2195def __init__(self⟨Rectangle J⟩, colorblue):196 self.color→ blue = colorblueself.width ← 10, self.height ← 20
213super().__init__(color)214self.width→ 10 = width10215self.height→ 20 = height20rectangle ← ⟨Rectangle J⟩
220circle = Circle("red", 5)221rectangle→ ⟨Rectangle J⟩ = Rectangle("blue", 10, 20)222223print(f"Circle: color={circle.colorred}, radius={circle.radius5}, area={circle⟨Circle I⟩.area():.2f}")224print(f"Rectangle: color={rectangle.color}, width={rectangle.width}, height={rectangle.height}, area={rectangle.area()}")def area(self):
205def area(self⟨Circle I⟩):206 import math207 return math.pi3.141592653589793 * self.radius5 ** 2print(f"Circle: color={circle.color}, radius={circle.radius}, area={ci…
223print(f"Circle: color={circle.colorred}, radius={circle.radius5}, area={circle⟨Circle I⟩.area():.2f}")224print(f"Rectangle: color={rectangle.colorblue}, width={rectangle.width10}, height={rectangle.height20}, area={rectangle⟨Rectangle J⟩.area()}")outputCircle: color=red, radius=5, area=78.54def area(self):
217def area(self⟨Rectangle J⟩):218 return self.width10 * self.height20print(f"Rectangle: color={rectangle.color}, width={rectangle.width}, h…
223print(f"Circle: color={circle.color}, radius={circle.radius}, area={circle.area():.2f}")224print(f"Rectangle: color={rectangle.colorblue}, width={rectangle.width10}, height={rectangle.height20}, area={rectangle⟨Rectangle J⟩.area()}")outputRectangle: color=blue, width=10, height=20, area=200
Be careful: if any class in the hierarchy lacks __slots__, instances get a __dict__ and lose the memory benefits.
When to Use __slots__
"""When to use __slots__"""
# When to use __slots__
print("When to use __slots__:")
# 1. Many instances
class Particle:
__slots__ = ['x', 'y', 'vx', 'vy']
def __init__(self, x, y, vx, vy):
self.x = x
self.y = y
self.vx = vx
self.vy = vy
# Useful when creating thousands/millions
particles = [Particle(i, i*2, i*3, i*4) for i in range(100)]
print(f"✓ Good: Created {len(particles)} particles with __slots__")
# Fixed attributes
print("\nFixed attributes:")
class DatabaseRecord:
__slots__ = ['id', 'timestamp', 'user_id', 'action', 'data']
def __init__(self, id, timestamp, user_id, action, data):
self.id = id
self.timestamp = timestamp
self.user_id = user_id
self.action = action
self.data = data
record = DatabaseRecord(1, 1234567890, 42, "login", {"ip": "127.0.0.1"})
print(f"✓ Good: Fixed schema prevents typos")
# Data classes
print("\nData classes:")
class Point3D:
__slots__ = ['x', 'y', 'z']
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
def __repr__(self):
return f"Point3D({self.x}, {self.y}, {self.z})"
def distance_from_origin(self):
return (self.x**2 + self.y**2 + self.z**2) ** 0.5
p = Point3D(3, 4, 5)
print(f"✓ Good: Simple data container")
print(f" Point: {p}, distance: {p.distance_from_origin():.2f}")
# When NOT to use __slots__
print("\nWhen NOT to use __slots__:")
# 1. Dynamic attributes needed
class FlexibleConfig:
# Don't use __slots__ here
def __init__(self):
self.settings = {}
def set(self, key, value):
self.settings[key] = value
config = FlexibleConfig()
config.debug = True # Need this flexibility
config.timeout = 30
print(f"✗ Bad for __slots__: Dynamic attributes needed")
# Few instances
print("\nFew instances:")
# Don't use __slots__ for singletons or few instances
class AppConfig:
# No need for __slots__ - only one instance
def __init__(self):
self.host = "localhost"
self.port = 8080
self.debug = False
config = AppConfig()
print(f"✗ Bad for __slots__: Only a few instances")
# Complex inheritance
print("\nComplex inheritance:")
# Avoid __slots__ with complex inheritance hierarchies
class Base:
def __init__(self):
self.base_attr = "base"
class Mixin1:
def method1(self):
return "mixin1"
class Mixin2:
def method2(self):
return "mixin2"
class ComplexClass(Base, Mixin1, Mixin2):
# Don't add __slots__ here - too complex
def __init__(self):
super().__init__()
self.extra = "extra"
obj = ComplexClass()
print(f"✗ Bad for __slots__: Complex inheritance")
# Performance-critical code
print("\nPerformance-critical code:")
class Vector:
__slots__ = ['x', 'y']
def __init__(self, x, y):
self.x = x
self.y = y
def __add__(self, other):
return Vector(self.x + other.x, self.y + other.y)
def dot(self, other):
return self.x * other.x + self.y * other.y
# Good for tight loops
v1 = Vector(1, 2)
v2 = Vector(3, 4)
print(f"✓ Good: Performance-critical math operations")
# Large collections
print("\nLarge collections:")
class LogEntry:
__slots__ = ['timestamp', 'level', 'message']
def __init__(self, timestamp, level, message):
self.timestamp = timestamp
self.level = level
self.message = message
# Good for storing millions of log entries in memory
logs = [LogEntry(i, "INFO", f"Message {i}") for i in range(100)]
print(f"✓ Good: Large collections ({len(logs)} entries)")
# Embedded systems
print("\nEmbedded systems:")
class SensorReading:
__slots__ = ['sensor_id', 'value', 'unit']
def __init__(self, sensor_id, value, unit):
self.sensor_id = sensor_id
self.value = value
self.unit = unit
reading = SensorReading(1, 23.5, "C")
print(f"✓ Good: Memory-constrained environments")
# Game development
print("\nGame development:")
class Entity:
__slots__ = ['id', 'x', 'y', 'sprite', 'health']
def __init__(self, id, x, y, sprite, health):
self.id = id
self.x = x
self.y = y
self.sprite = sprite
self.health = health
# Good for thousands of game entities
entities = [Entity(i, i*10, i*20, f"sprite{i}", 100) for i in range(100)]
print(f"✓ Good: Game with {len(entities)} entities")
# Practical decision guide
print("\nPractical decision guide:")
print("\nUse __slots__ when:")
print(" ✓ Creating many instances (>1000)")
print(" ✓ Attributes are fixed and known")
print(" ✓ Memory is constrained")
print(" ✓ Attribute access speed matters")
print(" ✓ Preventing attribute typos is valuable")
print("\nAvoid __slots__ when:")
print(" ✗ Dynamic attributes are needed")
print(" ✗ Only a few instances exist")
print(" ✗ Complex inheritance hierarchies")
print(" ✗ Need __dict__ for introspection")
print(" ✗ Using libraries that expect __dict__")
# Real-world example
print("\nReal-world example:")
# Time series data storage
class TimeSeriesPoint:
__slots__ = ['timestamp', 'value']
def __init__(self, timestamp, value):
self.timestamp = timestamp
self.value = value
# Simulate 1 day of per-second data
seconds_per_day = 86400
timeseries = [TimeSeriesPoint(i, i * 0.1) for i in range(100)] # Sample
print(f"✓ Excellent use case: Time series with {len(timeseries)} data points")
print(f" Each point: timestamp + value")
print(f" Fixed schema, many instances, memory-efficient")
"""When to use __slots__"""
1"""When to use __slots__"""23# When to use __slots__4print("When to use __slots__:")56# 1. Many instances7class Particle:8 __slots__ = ['x', 'y', 'vx', 'vy']9 10 def __init__(self, x, y, vx, vy):11 self.x = x12 self.y = y13 self.vx = vx14 self.vy = vy1516# Useful when creating thousands/millions17particles = [Particle(i, i*2, i*3, i*4) for i in range(100)]18print(f"✓ Good: Created {len(particles)} particles with __slots__")outputWhen to use __slots__:self.x ← 0, self.y ← 0, self.vx ← 0, self.vy ← 0
pass 1 of 10010def __init__(self⟨Particle A⟩, x0, y0, vx0, vy0):11 self.x→ 0 = x012 self.y→ 0 = y013 self.vx→ 0 = vx014 self.vy→ 0 = vy0100 passes — pass 1 is the card above pass selfxyvxvyself.xself.yself.vxself.vy1 ⟨Particle A⟩ 0 0 0 0 0 0 0 0 2 ⟨Particle B⟩ 1 2 3 4 1 2 3 4 3 ⟨Particle C⟩ 2 4 6 8 2 4 6 8 4 ⟨Particle D⟩ 3 6 9 12 3 6 9 12 5 ⟨Particle E⟩ 4 8 12 16 4 8 12 16 6 ⟨Particle F⟩ 5 10 15 20 5 10 15 20 7 ⟨Particle G⟩ 6 12 18 24 6 12 18 24 8 ⟨Particle H⟩ 7 14 21 28 7 14 21 28 9 ⟨Particle I⟩ 8 16 24 32 8 16 24 32 ⋯ 89 more passes ⋯ 99 ⟨Particle J⟩ 98 196 294 392 98 196 294 392 100 ⟨Particle K⟩ 99 198 297 396 99 198 297 396 particles ← [⟨Particle A⟩, ⟨Particle B⟩, ⟨Particle C⟩, ⟨Particle D⟩, ⟨Particle E⟩, ⟨Particle F⟩, ⟨Particle G⟩, ⟨Particle H⟩, ⟨Particle I⟩, ⟨Particle L⟩, ⟨Particle M⟩, ⟨Particle N⟩, ⟨Particle O⟩, ⟨Particle P⟩, ⟨Particle Q⟩, ⟨Particle R⟩, ⟨Particle S⟩, ⟨Particle T⟩, ⟨Particle U⟩, ⟨Particle V⟩, ⟨Particle W⟩, ⟨Particle X⟩, ⟨Particle Y⟩, ⟨Particle Z⟩, ⟨Particle AA⟩, ⟨Particle AB⟩, ⟨Particle AC⟩, ⟨Particle AD⟩, ⟨Particle AE⟩, ⟨Particle AF⟩, ⟨Particle AG⟩, ⟨Particle AH⟩, ⟨Particle AI⟩, ⟨Particle AJ⟩, ⟨Particle AK⟩, ⟨Particle AL⟩, ⟨Particle AM⟩, ⟨Particle AN⟩, ⟨Particle AO⟩, ⟨Particle AP⟩, ⟨Particle AQ⟩, ⟨Particle AR⟩, ⟨Particle AS⟩, ⟨Particle AT⟩, ⟨Particle AU⟩, ⟨Particle AV⟩, ⟨Particle AW⟩, ⟨Particle AX⟩, ⟨Particle AY⟩, ⟨Particle AZ⟩, ⟨Particle BA⟩, ⟨Particle BB⟩, ⟨Particle BC⟩, ⟨Particle BD⟩, ⟨Particle BE⟩, ⟨Particle BF⟩, ⟨Particle BG⟩, ⟨Particle BH⟩, ⟨Particle BI⟩, ⟨Particle BJ⟩, ⟨Particle BK⟩, ⟨Particle BL⟩, ⟨Particle BM⟩, ⟨Particle BN⟩, ⟨Particle BO⟩, ⟨Particle BP⟩, ⟨Particle BQ⟩, ⟨Particle BR⟩, ⟨Particle BS⟩, ⟨Particle BT⟩, ⟨Particle BU⟩, ⟨Particle BV⟩, ⟨Particle BW⟩, ⟨Particle BX⟩, ⟨Particle BY⟩, ⟨Particle BZ⟩, ⟨Particle CA⟩, ⟨Particle CB⟩, ⟨Particle CC⟩, ⟨Particle CD⟩, ⟨Particle CE⟩, ⟨Particle CF⟩, ⟨Particle CG⟩, ⟨Particle CH⟩, ⟨Particle CI⟩, ⟨Particle CJ⟩, ⟨Particle CK⟩, ⟨Particle CL⟩, ⟨Particle CM⟩, ⟨Particle CN⟩, ⟨Particle CO⟩, ⟨Particle CP⟩, ⟨Particle CQ⟩, ⟨Particle CR⟩, ⟨Particle CS⟩, ⟨Particle CT⟩, ⟨Particle CU⟩, ⟨Particle CV⟩, ⟨Particle J⟩, ⟨Particle K⟩]
16# Useful when creating thousands/millions17particles→ [⟨Particle A⟩, ⟨Particle B⟩, ⟨Particle C⟩, ⟨Particle D⟩, ⟨Particle E⟩, ⟨Particle F⟩, ⟨Particle G⟩, ⟨Particle H⟩, ⟨Particle I⟩, ⟨Particle L⟩, ⟨Particle M⟩, ⟨Particle N⟩, ⟨Particle O⟩, ⟨Particle P⟩, ⟨Particle Q⟩, ⟨Particle R⟩, ⟨Particle S⟩, ⟨Particle T⟩, ⟨Particle U⟩, ⟨Particle V⟩, ⟨Particle W⟩, ⟨Particle X⟩, ⟨Particle Y⟩, ⟨Particle Z⟩, ⟨Particle AA⟩, ⟨Particle AB⟩, ⟨Particle AC⟩, ⟨Particle AD⟩, ⟨Particle AE⟩, ⟨Particle AF⟩, ⟨Particle AG⟩, ⟨Particle AH⟩, ⟨Particle AI⟩, ⟨Particle AJ⟩, ⟨Particle AK⟩, ⟨Particle AL⟩, ⟨Particle AM⟩, ⟨Particle AN⟩, ⟨Particle AO⟩, ⟨Particle AP⟩, ⟨Particle AQ⟩, ⟨Particle AR⟩, ⟨Particle AS⟩, ⟨Particle AT⟩, ⟨Particle AU⟩, ⟨Particle AV⟩, ⟨Particle AW⟩, ⟨Particle AX⟩, ⟨Particle AY⟩, ⟨Particle AZ⟩, ⟨Particle BA⟩, ⟨Particle BB⟩, ⟨Particle BC⟩, ⟨Particle BD⟩, ⟨Particle BE⟩, ⟨Particle BF⟩, ⟨Particle BG⟩, ⟨Particle BH⟩, ⟨Particle BI⟩, ⟨Particle BJ⟩, ⟨Particle BK⟩, ⟨Particle BL⟩, ⟨Particle BM⟩, ⟨Particle BN⟩, ⟨Particle BO⟩, ⟨Particle BP⟩, ⟨Particle BQ⟩, ⟨Particle BR⟩, ⟨Particle BS⟩, ⟨Particle BT⟩, ⟨Particle BU⟩, ⟨Particle BV⟩, ⟨Particle BW⟩, ⟨Particle BX⟩, ⟨Particle BY⟩, ⟨Particle BZ⟩, ⟨Particle CA⟩, ⟨Particle CB⟩, ⟨Particle CC⟩, ⟨Particle CD⟩, ⟨Particle CE⟩, ⟨Particle CF⟩, ⟨Particle CG⟩, ⟨Particle CH⟩, ⟨Particle CI⟩, ⟨Particle CJ⟩, ⟨Particle CK⟩, ⟨Particle CL⟩, ⟨Particle CM⟩, ⟨Particle CN⟩, ⟨Particle CO⟩, ⟨Particle CP⟩, ⟨Particle CQ⟩, ⟨Particle CR⟩, ⟨Particle CS⟩, ⟨Particle CT⟩, ⟨Particle CU⟩, ⟨Particle CV⟩, ⟨Particle J⟩, ⟨Particle K⟩] = [Particle(i, i*2, i*3, i*4) for i in range(100)]18print(f"✓ Good: Created {len(particles[⟨Particle A⟩, ⟨Particle B⟩, ⟨Particle C⟩, ⟨Particle D⟩, ⟨Particle E⟩, ⟨Particle F⟩, ⟨Particle G⟩, ⟨Particle H⟩, ⟨Particle I⟩, ⟨Particle L⟩, ⟨Particle M⟩, ⟨Particle N⟩, ⟨Particle O⟩, ⟨Particle P⟩, ⟨Particle Q⟩, ⟨Particle R⟩, ⟨Particle S⟩, ⟨Particle T⟩, ⟨Particle U⟩, ⟨Particle V⟩, ⟨Particle W⟩, ⟨Particle X⟩, ⟨Particle Y⟩, ⟨Particle Z⟩, ⟨Particle AA⟩, ⟨Particle AB⟩, ⟨Particle AC⟩, ⟨Particle AD⟩, ⟨Particle AE⟩, ⟨Particle AF⟩, ⟨Particle AG⟩, ⟨Particle AH⟩, ⟨Particle AI⟩, ⟨Particle AJ⟩, ⟨Particle AK⟩, ⟨Particle AL⟩, ⟨Particle AM⟩, ⟨Particle AN⟩, ⟨Particle AO⟩, ⟨Particle AP⟩, ⟨Particle AQ⟩, ⟨Particle AR⟩, ⟨Particle AS⟩, ⟨Particle AT⟩, ⟨Particle AU⟩, ⟨Particle AV⟩, ⟨Particle AW⟩, ⟨Particle AX⟩, ⟨Particle AY⟩, ⟨Particle AZ⟩, ⟨Particle BA⟩, ⟨Particle BB⟩, ⟨Particle BC⟩, ⟨Particle BD⟩, ⟨Particle BE⟩, ⟨Particle BF⟩, ⟨Particle BG⟩, ⟨Particle BH⟩, ⟨Particle BI⟩, ⟨Particle BJ⟩, ⟨Particle BK⟩, ⟨Particle BL⟩, ⟨Particle BM⟩, ⟨Particle BN⟩, ⟨Particle BO⟩, ⟨Particle BP⟩, ⟨Particle BQ⟩, ⟨Particle BR⟩, ⟨Particle BS⟩, ⟨Particle BT⟩, ⟨Particle BU⟩, ⟨Particle BV⟩, ⟨Particle BW⟩, ⟨Particle BX⟩, ⟨Particle BY⟩, ⟨Particle BZ⟩, ⟨Particle CA⟩, ⟨Particle CB⟩, ⟨Particle CC⟩, ⟨Particle CD⟩, ⟨Particle CE⟩, ⟨Particle CF⟩, ⟨Particle CG⟩, ⟨Particle CH⟩, ⟨Particle CI⟩, ⟨Particle CJ⟩, ⟨Particle CK⟩, ⟨Particle CL⟩, ⟨Particle CM⟩, ⟨Particle CN⟩, ⟨Particle CO⟩, ⟨Particle CP⟩, ⟨Particle CQ⟩, ⟨Particle CR⟩, ⟨Particle CS⟩, ⟨Particle CT⟩, ⟨Particle CU⟩, ⟨Particle CV⟩, ⟨Particle J⟩, ⟨Particle K⟩])} particles with __slots__")1920# Fixed attributes21print("\nFixed attributes:")2223class DatabaseRecord:24 __slots__ = ['id', 'timestamp', 'user_id', 'action', 'data']output✓ Good: Created 100 particles with __slots__ Fixed attributes:self.id ← 1, self.timestamp ← 1234567890, self.user_id ← 42, self.action ← login
26def __init__(self⟨DatabaseRecord CW⟩, id1, timestamp1234567890, user_id42, actionlogin, data{'ip': '127.0.0.1'}):27 self.id→ 1 = id128 self.timestamp→ 1234567890 = timestamp123456789029 self.user_id→ 42 = user_id4230 self.action→ login = actionlogin31 self.data→ {'ip': '127.0.0.1'} = data{'ip': '127.0.0.1'}print(f"✓ Good: Fixed schema prevents typos")
33record = DatabaseRecord(1, 1234567890, 42, "login", {"ip": "127.0.0.1"})34print(f"✓ Good: Fixed schema prevents typos")3536# Data classes37print("\nData classes:")3839class Point3D:40 __slots__ = ['x', 'y', 'z']41 42 def __init__(self, x, y, z):43 self.x = x44 self.y = y45 self.z = z46 47 def __repr__(self):48 return f"Point3D({self.x}, {self.y}, {self.z})"49 50 def distance_from_origin(self):51 return (self.x**2 + self.y**2 + self.z**2) ** 0.55253p = Point3D(3, 4, 5)54print(f"✓ Good: Simple data container")output✓ Good: Fixed schema prevents typos Data classes:self.x ← 3, self.y ← 4, self.z ← 5
42def __init__(self(empty), x3, y4, z5):43 self.x→ 3 = x344 self.y→ 4 = y445 self.z→ 5 = z5p ← Point3D(3, 4, 5)
53p→ Point3D(3, 4, 5) = Point3D(3, 4, 5)54print(f"✓ Good: Simple data container")55print(f" Point: {pPoint3D(3, 4, 5)}, distance: {p.distance_from_origin():.2f}")output✓ Good: Simple data containerdef distance_from_origin(self):
50def distance_from_origin(selfPoint3D(3, 4, 5)):51 return (self.x3**2 + self.y4**2 + self.z5**2) ** 0.5print(f" Point: {p}, distance: {p.distance_from_origin():.2f}")
54print(f"✓ Good: Simple data container")55print(f" Point: {pPoint3D(3, 4, 5)}, distance: {p.distance_from_origin():.2f}")5657# When NOT to use __slots__58print("\nWhen NOT to use __slots__:")5960# 1. Dynamic attributes needed61class FlexibleConfig:62 # Don't use __slots__ here63 def __init__(self):64 self.settings = {}65 66 def set(self, key, value):67 self.settings[key] = value6869config = FlexibleConfig()70config.debug = True # Need this flexibilityoutput Point: Point3D(3, 4, 5), distance: 7.07 When NOT to use __slots__:self.settings ← {}
62# Don't use __slots__ here63def __init__(self⟨FlexibleConfig CX⟩):64 self.settings→ {} = {}config ← ⟨FlexibleConfig CX⟩, config.debug ← True, config.timeout ← 30
69config→ ⟨FlexibleConfig CX⟩ = FlexibleConfig()70config.debug→ True = True # Need this flexibility71config.timeout→ 30 = 3072print(f"✗ Bad for __slots__: Dynamic attributes needed")7374# Few instances75print("\nFew instances:")7677# Don't use __slots__ for singletons or few instances78class AppConfig:79 # No need for __slots__ - only one instance80 def __init__(self):81 self.host = "localhost"82 self.port = 808083 self.debug = False8485config = AppConfig()86print(f"✗ Bad for __slots__: Only a few instances")output✗ Bad for __slots__: Dynamic attributes needed Few instances:self.host ← localhost, self.port ← 8080, self.debug ← False
79# No need for __slots__ - only one instance80def __init__(self⟨AppConfig CY⟩):81 self.host→ localhost = "localhost"82 self.port→ 8080 = 808083 self.debug→ False = Falseconfig ← ⟨AppConfig CY⟩
85config→ ⟨AppConfig CY⟩ = AppConfig()86print(f"✗ Bad for __slots__: Only a few instances")8788# Complex inheritance89print("\nComplex inheritance:")9091# Avoid __slots__ with complex inheritance hierarchies92class Base:93 def __init__(self):94 self.base_attr = "base"9596class Mixin1:97 def method1(self):98 return "mixin1"99100class Mixin2:101 def method2(self):102 return "mixin2"103104class ComplexClass(Base, Mixin1, Mixin2):105 # Don't add __slots__ here - too complex106 def __init__(self):107 super().__init__()108 self.extra = "extra"109110obj = ComplexClass()111print(f"✗ Bad for __slots__: Complex inheritance")output✗ Bad for __slots__: Only a few instances Complex inheritance:def __init__(self):
105# Don't add __slots__ here - too complex106def __init__(self⟨ComplexClass CZ⟩):107 super().__init__()108 self.extra = "extra"self.base_attr ← base
92class Base:93 def __init__(self⟨ComplexClass CZ⟩):94 self.base_attr→ base = "base"self.extra ← extra
107super().__init__()108self.extra→ extra = "extra"obj ← ⟨ComplexClass CZ⟩
110obj→ ⟨ComplexClass CZ⟩ = ComplexClass()111print(f"✗ Bad for __slots__: Complex inheritance")112113# Performance-critical code114print("\nPerformance-critical code:")115116class Vector:117 __slots__ = ['x', 'y']118 119 def __init__(self, x, y):120 self.x = x121 self.y = y122 123 def __add__(self, other):124 return Vector(self.x + other.x, self.y + other.y)125 126 def dot(self, other):127 return self.x * other.x + self.y * other.y128129# Good for tight loops130v1 = Vector(1, 2)131v2 = Vector(3, 4)output✗ Bad for __slots__: Complex inheritance Performance-critical code:self.x ← 1, self.y ← 2
pass 1 of 2119def __init__(self⟨Vector DA⟩, x1, y2):120 self.x→ 1 = x1121 self.y→ 2 = y2v1 ← ⟨Vector DA⟩
129# Good for tight loops130v1→ ⟨Vector DA⟩ = Vector(1, 2)131v2 = Vector(3, 4)132print(f"✓ Good: Performance-critical math operations")self.x ← 3, self.y ← 4
pass 2 of 2119def __init__(self⟨Vector DB⟩, x3, y4):120 self.x→ 3 = x3121 self.y→ 4 = y4v2 ← ⟨Vector DB⟩
130v1 = Vector(1, 2)131v2→ ⟨Vector DB⟩ = Vector(3, 4)132print(f"✓ Good: Performance-critical math operations")133134# Large collections135print("\nLarge collections:")136137class LogEntry:138 __slots__ = ['timestamp', 'level', 'message']139 140 def __init__(self, timestamp, level, message):141 self.timestamp = timestamp142 self.level = level143 self.message = message144145# Good for storing millions of log entries in memory146logs = [LogEntry(i, "INFO", f"Message {i}") for i in range(100)]147print(f"✓ Good: Large collections ({len(logs)} entries)")output✓ Good: Performance-critical math operations Large collections:self.timestamp ← 0, self.level ← INFO, self.message ← Message 0
pass 1 of 100140def __init__(self⟨LogEntry DC⟩, timestamp0, levelINFO, messageMessage 0):141 self.timestamp→ 0 = timestamp0142 self.level→ INFO = levelINFO143 self.message→ Message 0 = messageMessage 0100 passes — pass 1 is the card above pass selftimestampmessageself.timestampself.levelself.message1 ⟨LogEntry DC⟩ 0 Message 0 0 INFO Message 0 2 ⟨LogEntry DD⟩ 1 Message 1 1 INFO Message 1 3 ⟨LogEntry DE⟩ 2 Message 2 2 INFO Message 2 4 ⟨LogEntry DF⟩ 3 Message 3 3 INFO Message 3 5 ⟨LogEntry DG⟩ 4 Message 4 4 INFO Message 4 6 ⟨LogEntry DH⟩ 5 Message 5 5 INFO Message 5 7 ⟨LogEntry DI⟩ 6 Message 6 6 INFO Message 6 8 ⟨LogEntry DJ⟩ 7 Message 7 7 INFO Message 7 9 ⟨LogEntry DK⟩ 8 Message 8 8 INFO Message 8 ⋯ 89 more passes ⋯ 99 ⟨LogEntry DL⟩ 98 Message 98 98 INFO Message 98 100 ⟨LogEntry DM⟩ 99 Message 99 99 INFO Message 99 logs ← [⟨LogEntry DC⟩, ⟨LogEntry DD⟩, ⟨LogEntry DE⟩, ⟨LogEntry DF⟩, ⟨LogEntry DG⟩, ⟨LogEntry DH⟩, ⟨LogEntry DI⟩, ⟨LogEntry DJ⟩, ⟨LogEntry DK⟩, ⟨LogEntry DN⟩, ⟨LogEntry DO⟩, ⟨LogEntry DP⟩, ⟨LogEntry DQ⟩, ⟨LogEntry DR⟩, ⟨LogEntry DS⟩, ⟨LogEntry DT⟩, ⟨LogEntry DU⟩, ⟨LogEntry DV⟩, ⟨LogEntry DW⟩, ⟨LogEntry DX⟩, ⟨LogEntry DY⟩, ⟨LogEntry DZ⟩, ⟨LogEntry EA⟩, ⟨LogEntry EB⟩, ⟨LogEntry EC⟩, ⟨LogEntry ED⟩, ⟨LogEntry EE⟩, ⟨LogEntry EF⟩, ⟨LogEntry EG⟩, ⟨LogEntry EH⟩, ⟨LogEntry EI⟩, ⟨LogEntry EJ⟩, ⟨LogEntry EK⟩, ⟨LogEntry EL⟩, ⟨LogEntry EM⟩, ⟨LogEntry EN⟩, ⟨LogEntry EO⟩, ⟨LogEntry EP⟩, ⟨LogEntry EQ⟩, ⟨LogEntry ER⟩, ⟨LogEntry ES⟩, ⟨LogEntry ET⟩, ⟨LogEntry EU⟩, ⟨LogEntry EV⟩, ⟨LogEntry EW⟩, ⟨LogEntry EX⟩, ⟨LogEntry EY⟩, ⟨LogEntry EZ⟩, ⟨LogEntry FA⟩, ⟨LogEntry FB⟩, ⟨LogEntry FC⟩, ⟨LogEntry FD⟩, ⟨LogEntry FE⟩, ⟨LogEntry FF⟩, ⟨LogEntry FG⟩, ⟨LogEntry FH⟩, ⟨LogEntry FI⟩, ⟨LogEntry FJ⟩, ⟨LogEntry FK⟩, ⟨LogEntry FL⟩, ⟨LogEntry FM⟩, ⟨LogEntry FN⟩, ⟨LogEntry FO⟩, ⟨LogEntry FP⟩, ⟨LogEntry FQ⟩, ⟨LogEntry FR⟩, ⟨LogEntry FS⟩, ⟨LogEntry FT⟩, ⟨LogEntry FU⟩, ⟨LogEntry FV⟩, ⟨LogEntry FW⟩, ⟨LogEntry FX⟩, ⟨LogEntry FY⟩, ⟨LogEntry FZ⟩, ⟨LogEntry GA⟩, ⟨LogEntry GB⟩, ⟨LogEntry GC⟩, ⟨LogEntry GD⟩, ⟨LogEntry GE⟩, ⟨LogEntry GF⟩, ⟨LogEntry GG⟩, ⟨LogEntry GH⟩, ⟨LogEntry GI⟩, ⟨LogEntry GJ⟩, ⟨LogEntry GK⟩, ⟨LogEntry GL⟩, ⟨LogEntry GM⟩, ⟨LogEntry GN⟩, ⟨LogEntry GO⟩, ⟨LogEntry GP⟩, ⟨LogEntry GQ⟩, ⟨LogEntry GR⟩, ⟨LogEntry GS⟩, ⟨LogEntry GT⟩, ⟨LogEntry GU⟩, ⟨LogEntry GV⟩, ⟨LogEntry GW⟩, ⟨LogEntry GX⟩, ⟨LogEntry DL⟩, ⟨LogEntry DM⟩]
145# Good for storing millions of log entries in memory146logs→ [⟨LogEntry DC⟩, ⟨LogEntry DD⟩, ⟨LogEntry DE⟩, ⟨LogEntry DF⟩, ⟨LogEntry DG⟩, ⟨LogEntry DH⟩, ⟨LogEntry DI⟩, ⟨LogEntry DJ⟩, ⟨LogEntry DK⟩, ⟨LogEntry DN⟩, ⟨LogEntry DO⟩, ⟨LogEntry DP⟩, ⟨LogEntry DQ⟩, ⟨LogEntry DR⟩, ⟨LogEntry DS⟩, ⟨LogEntry DT⟩, ⟨LogEntry DU⟩, ⟨LogEntry DV⟩, ⟨LogEntry DW⟩, ⟨LogEntry DX⟩, ⟨LogEntry DY⟩, ⟨LogEntry DZ⟩, ⟨LogEntry EA⟩, ⟨LogEntry EB⟩, ⟨LogEntry EC⟩, ⟨LogEntry ED⟩, ⟨LogEntry EE⟩, ⟨LogEntry EF⟩, ⟨LogEntry EG⟩, ⟨LogEntry EH⟩, ⟨LogEntry EI⟩, ⟨LogEntry EJ⟩, ⟨LogEntry EK⟩, ⟨LogEntry EL⟩, ⟨LogEntry EM⟩, ⟨LogEntry EN⟩, ⟨LogEntry EO⟩, ⟨LogEntry EP⟩, ⟨LogEntry EQ⟩, ⟨LogEntry ER⟩, ⟨LogEntry ES⟩, ⟨LogEntry ET⟩, ⟨LogEntry EU⟩, ⟨LogEntry EV⟩, ⟨LogEntry EW⟩, ⟨LogEntry EX⟩, ⟨LogEntry EY⟩, ⟨LogEntry EZ⟩, ⟨LogEntry FA⟩, ⟨LogEntry FB⟩, ⟨LogEntry FC⟩, ⟨LogEntry FD⟩, ⟨LogEntry FE⟩, ⟨LogEntry FF⟩, ⟨LogEntry FG⟩, ⟨LogEntry FH⟩, ⟨LogEntry FI⟩, ⟨LogEntry FJ⟩, ⟨LogEntry FK⟩, ⟨LogEntry FL⟩, ⟨LogEntry FM⟩, ⟨LogEntry FN⟩, ⟨LogEntry FO⟩, ⟨LogEntry FP⟩, ⟨LogEntry FQ⟩, ⟨LogEntry FR⟩, ⟨LogEntry FS⟩, ⟨LogEntry FT⟩, ⟨LogEntry FU⟩, ⟨LogEntry FV⟩, ⟨LogEntry FW⟩, ⟨LogEntry FX⟩, ⟨LogEntry FY⟩, ⟨LogEntry FZ⟩, ⟨LogEntry GA⟩, ⟨LogEntry GB⟩, ⟨LogEntry GC⟩, ⟨LogEntry GD⟩, ⟨LogEntry GE⟩, ⟨LogEntry GF⟩, ⟨LogEntry GG⟩, ⟨LogEntry GH⟩, ⟨LogEntry GI⟩, ⟨LogEntry GJ⟩, ⟨LogEntry GK⟩, ⟨LogEntry GL⟩, ⟨LogEntry GM⟩, ⟨LogEntry GN⟩, ⟨LogEntry GO⟩, ⟨LogEntry GP⟩, ⟨LogEntry GQ⟩, ⟨LogEntry GR⟩, ⟨LogEntry GS⟩, ⟨LogEntry GT⟩, ⟨LogEntry GU⟩, ⟨LogEntry GV⟩, ⟨LogEntry GW⟩, ⟨LogEntry GX⟩, ⟨LogEntry DL⟩, ⟨LogEntry DM⟩] = [LogEntry(i, "INFO", f"Message {i}") for i in range(100)]147print(f"✓ Good: Large collections ({len(logs[⟨LogEntry DC⟩, ⟨LogEntry DD⟩, ⟨LogEntry DE⟩, ⟨LogEntry DF⟩, ⟨LogEntry DG⟩, ⟨LogEntry DH⟩, ⟨LogEntry DI⟩, ⟨LogEntry DJ⟩, ⟨LogEntry DK⟩, ⟨LogEntry DN⟩, ⟨LogEntry DO⟩, ⟨LogEntry DP⟩, ⟨LogEntry DQ⟩, ⟨LogEntry DR⟩, ⟨LogEntry DS⟩, ⟨LogEntry DT⟩, ⟨LogEntry DU⟩, ⟨LogEntry DV⟩, ⟨LogEntry DW⟩, ⟨LogEntry DX⟩, ⟨LogEntry DY⟩, ⟨LogEntry DZ⟩, ⟨LogEntry EA⟩, ⟨LogEntry EB⟩, ⟨LogEntry EC⟩, ⟨LogEntry ED⟩, ⟨LogEntry EE⟩, ⟨LogEntry EF⟩, ⟨LogEntry EG⟩, ⟨LogEntry EH⟩, ⟨LogEntry EI⟩, ⟨LogEntry EJ⟩, ⟨LogEntry EK⟩, ⟨LogEntry EL⟩, ⟨LogEntry EM⟩, ⟨LogEntry EN⟩, ⟨LogEntry EO⟩, ⟨LogEntry EP⟩, ⟨LogEntry EQ⟩, ⟨LogEntry ER⟩, ⟨LogEntry ES⟩, ⟨LogEntry ET⟩, ⟨LogEntry EU⟩, ⟨LogEntry EV⟩, ⟨LogEntry EW⟩, ⟨LogEntry EX⟩, ⟨LogEntry EY⟩, ⟨LogEntry EZ⟩, ⟨LogEntry FA⟩, ⟨LogEntry FB⟩, ⟨LogEntry FC⟩, ⟨LogEntry FD⟩, ⟨LogEntry FE⟩, ⟨LogEntry FF⟩, ⟨LogEntry FG⟩, ⟨LogEntry FH⟩, ⟨LogEntry FI⟩, ⟨LogEntry FJ⟩, ⟨LogEntry FK⟩, ⟨LogEntry FL⟩, ⟨LogEntry FM⟩, ⟨LogEntry FN⟩, ⟨LogEntry FO⟩, ⟨LogEntry FP⟩, ⟨LogEntry FQ⟩, ⟨LogEntry FR⟩, ⟨LogEntry FS⟩, ⟨LogEntry FT⟩, ⟨LogEntry FU⟩, ⟨LogEntry FV⟩, ⟨LogEntry FW⟩, ⟨LogEntry FX⟩, ⟨LogEntry FY⟩, ⟨LogEntry FZ⟩, ⟨LogEntry GA⟩, ⟨LogEntry GB⟩, ⟨LogEntry GC⟩, ⟨LogEntry GD⟩, ⟨LogEntry GE⟩, ⟨LogEntry GF⟩, ⟨LogEntry GG⟩, ⟨LogEntry GH⟩, ⟨LogEntry GI⟩, ⟨LogEntry GJ⟩, ⟨LogEntry GK⟩, ⟨LogEntry GL⟩, ⟨LogEntry GM⟩, ⟨LogEntry GN⟩, ⟨LogEntry GO⟩, ⟨LogEntry GP⟩, ⟨LogEntry GQ⟩, ⟨LogEntry GR⟩, ⟨LogEntry GS⟩, ⟨LogEntry GT⟩, ⟨LogEntry GU⟩, ⟨LogEntry GV⟩, ⟨LogEntry GW⟩, ⟨LogEntry GX⟩, ⟨LogEntry DL⟩, ⟨LogEntry DM⟩])} entries)")148149# Embedded systems150print("\nEmbedded systems:")151152class SensorReading:153 __slots__ = ['sensor_id', 'value', 'unit']154 155 def __init__(self, sensor_id, value, unit):156 self.sensor_id = sensor_id157 self.value = value158 self.unit = unit159160reading = SensorReading(1, 23.5, "C")161print(f"✓ Good: Memory-constrained environments")output✓ Good: Large collections (100 entries) Embedded systems:self.sensor_id ← 1, self.value ← 23.5, self.unit ← C
155def __init__(self⟨SensorReading GY⟩, sensor_id1, value23.5, unitC):156 self.sensor_id→ 1 = sensor_id1157 self.value→ 23.5 = value23.5158 self.unit→ C = unitCreading ← ⟨SensorReading GY⟩
160reading→ ⟨SensorReading GY⟩ = SensorReading(1, 23.5, "C")161print(f"✓ Good: Memory-constrained environments")162163# Game development164print("\nGame development:")165166class Entity:167 __slots__ = ['id', 'x', 'y', 'sprite', 'health']168 169 def __init__(self, id, x, y, sprite, health):170 self.id = id171 self.x = x172 self.y = y173 self.sprite = sprite174 self.health = health175176# Good for thousands of game entities177entities = [Entity(i, i*10, i*20, f"sprite{i}", 100) for i in range(100)]178print(f"✓ Good: Game with {len(entities)} entities")output✓ Good: Memory-constrained environments Game development:self.id ← 0, self.x ← 0, self.y ← 0, self.sprite ← sprite0, self.health ← 100
pass 1 of 100169def __init__(self⟨Entity GZ⟩, id0, x0, y0, spritesprite0, health100):170 self.id→ 0 = id0171 self.x→ 0 = x0172 self.y→ 0 = y0173 self.sprite→ sprite0 = spritesprite0174 self.health→ 100 = health100100 passes — pass 1 is the card above pass selfidxyspriteself.idself.xself.yself.spriteself.health1 ⟨Entity GZ⟩ 0 0 0 sprite0 0 0 0 sprite0 100 2 ⟨Entity HA⟩ 1 10 20 sprite1 1 10 20 sprite1 100 3 ⟨Entity HB⟩ 2 20 40 sprite2 2 20 40 sprite2 100 4 ⟨Entity HC⟩ 3 30 60 sprite3 3 30 60 sprite3 100 5 ⟨Entity HD⟩ 4 40 80 sprite4 4 40 80 sprite4 100 6 ⟨Entity HE⟩ 5 50 100 sprite5 5 50 100 sprite5 100 7 ⟨Entity HF⟩ 6 60 120 sprite6 6 60 120 sprite6 100 8 ⟨Entity HG⟩ 7 70 140 sprite7 7 70 140 sprite7 100 9 ⟨Entity HH⟩ 8 80 160 sprite8 8 80 160 sprite8 100 ⋯ 89 more passes ⋯ 99 ⟨Entity HI⟩ 98 980 1960 sprite98 98 980 1960 sprite98 100 100 ⟨Entity HJ⟩ 99 990 1980 sprite99 99 990 1980 sprite99 100 entities ← [⟨Entity GZ⟩, ⟨Entity HA⟩, ⟨Entity HB⟩, ⟨Entity HC⟩, ⟨Entity HD⟩, ⟨Entity HE⟩, ⟨Entity HF⟩, ⟨Entity HG⟩, ⟨Entity HH⟩, ⟨Entity HK⟩, ⟨Entity HL⟩, ⟨Entity HM⟩, ⟨Entity HN⟩, ⟨Entity HO⟩, ⟨Entity HP⟩, ⟨Entity HQ⟩, ⟨Entity HR⟩, ⟨Entity HS⟩, ⟨Entity HT⟩, ⟨Entity HU⟩, ⟨Entity HV⟩, ⟨Entity HW⟩, ⟨Entity HX⟩, ⟨Entity HY⟩, ⟨Entity HZ⟩, ⟨Entity IA⟩, ⟨Entity IB⟩, ⟨Entity IC⟩, ⟨Entity ID⟩, ⟨Entity IE⟩, ⟨Entity IF⟩, ⟨Entity IG⟩, ⟨Entity IH⟩, ⟨Entity II⟩, ⟨Entity IJ⟩, ⟨Entity IK⟩, ⟨Entity IL⟩, ⟨Entity IM⟩, ⟨Entity IN⟩, ⟨Entity IO⟩, ⟨Entity IP⟩, ⟨Entity IQ⟩, ⟨Entity IR⟩, ⟨Entity IS⟩, ⟨Entity IT⟩, ⟨Entity IU⟩, ⟨Entity IV⟩, ⟨Entity IW⟩, ⟨Entity IX⟩, ⟨Entity IY⟩, ⟨Entity IZ⟩, ⟨Entity JA⟩, ⟨Entity JB⟩, ⟨Entity JC⟩, ⟨Entity JD⟩, ⟨Entity JE⟩, ⟨Entity JF⟩, ⟨Entity JG⟩, ⟨Entity JH⟩, ⟨Entity JI⟩, ⟨Entity JJ⟩, ⟨Entity JK⟩, ⟨Entity JL⟩, ⟨Entity JM⟩, ⟨Entity JN⟩, ⟨Entity JO⟩, ⟨Entity JP⟩, ⟨Entity JQ⟩, ⟨Entity JR⟩, ⟨Entity JS⟩, ⟨Entity JT⟩, ⟨Entity JU⟩, ⟨Entity JV⟩, ⟨Entity JW⟩, ⟨Entity JX⟩, ⟨Entity JY⟩, ⟨Entity JZ⟩, ⟨Entity KA⟩, ⟨Entity KB⟩, ⟨Entity KC⟩, ⟨Entity KD⟩, ⟨Entity KE⟩, ⟨Entity KF⟩, ⟨Entity KG⟩, ⟨Entity KH⟩, ⟨Entity KI⟩, ⟨Entity KJ⟩, ⟨Entity KK⟩, ⟨Entity KL⟩, ⟨Entity KM⟩, ⟨Entity KN⟩, ⟨Entity KO⟩, ⟨Entity KP⟩, ⟨Entity KQ⟩, ⟨Entity KR⟩, ⟨Entity KS⟩, ⟨Entity KT⟩, ⟨Entity KU⟩, ⟨Entity HI⟩, ⟨Entity HJ⟩]
176# Good for thousands of game entities177entities→ [⟨Entity GZ⟩, ⟨Entity HA⟩, ⟨Entity HB⟩, ⟨Entity HC⟩, ⟨Entity HD⟩, ⟨Entity HE⟩, ⟨Entity HF⟩, ⟨Entity HG⟩, ⟨Entity HH⟩, ⟨Entity HK⟩, ⟨Entity HL⟩, ⟨Entity HM⟩, ⟨Entity HN⟩, ⟨Entity HO⟩, ⟨Entity HP⟩, ⟨Entity HQ⟩, ⟨Entity HR⟩, ⟨Entity HS⟩, ⟨Entity HT⟩, ⟨Entity HU⟩, ⟨Entity HV⟩, ⟨Entity HW⟩, ⟨Entity HX⟩, ⟨Entity HY⟩, ⟨Entity HZ⟩, ⟨Entity IA⟩, ⟨Entity IB⟩, ⟨Entity IC⟩, ⟨Entity ID⟩, ⟨Entity IE⟩, ⟨Entity IF⟩, ⟨Entity IG⟩, ⟨Entity IH⟩, ⟨Entity II⟩, ⟨Entity IJ⟩, ⟨Entity IK⟩, ⟨Entity IL⟩, ⟨Entity IM⟩, ⟨Entity IN⟩, ⟨Entity IO⟩, ⟨Entity IP⟩, ⟨Entity IQ⟩, ⟨Entity IR⟩, ⟨Entity IS⟩, ⟨Entity IT⟩, ⟨Entity IU⟩, ⟨Entity IV⟩, ⟨Entity IW⟩, ⟨Entity IX⟩, ⟨Entity IY⟩, ⟨Entity IZ⟩, ⟨Entity JA⟩, ⟨Entity JB⟩, ⟨Entity JC⟩, ⟨Entity JD⟩, ⟨Entity JE⟩, ⟨Entity JF⟩, ⟨Entity JG⟩, ⟨Entity JH⟩, ⟨Entity JI⟩, ⟨Entity JJ⟩, ⟨Entity JK⟩, ⟨Entity JL⟩, ⟨Entity JM⟩, ⟨Entity JN⟩, ⟨Entity JO⟩, ⟨Entity JP⟩, ⟨Entity JQ⟩, ⟨Entity JR⟩, ⟨Entity JS⟩, ⟨Entity JT⟩, ⟨Entity JU⟩, ⟨Entity JV⟩, ⟨Entity JW⟩, ⟨Entity JX⟩, ⟨Entity JY⟩, ⟨Entity JZ⟩, ⟨Entity KA⟩, ⟨Entity KB⟩, ⟨Entity KC⟩, ⟨Entity KD⟩, ⟨Entity KE⟩, ⟨Entity KF⟩, ⟨Entity KG⟩, ⟨Entity KH⟩, ⟨Entity KI⟩, ⟨Entity KJ⟩, ⟨Entity KK⟩, ⟨Entity KL⟩, ⟨Entity KM⟩, ⟨Entity KN⟩, ⟨Entity KO⟩, ⟨Entity KP⟩, ⟨Entity KQ⟩, ⟨Entity KR⟩, ⟨Entity KS⟩, ⟨Entity KT⟩, ⟨Entity KU⟩, ⟨Entity HI⟩, ⟨Entity HJ⟩] = [Entity(i, i*10, i*20, f"sprite{i}", 100) for i in range(100)]178print(f"✓ Good: Game with {len(entities[⟨Entity GZ⟩, ⟨Entity HA⟩, ⟨Entity HB⟩, ⟨Entity HC⟩, ⟨Entity HD⟩, ⟨Entity HE⟩, ⟨Entity HF⟩, ⟨Entity HG⟩, ⟨Entity HH⟩, ⟨Entity HK⟩, ⟨Entity HL⟩, ⟨Entity HM⟩, ⟨Entity HN⟩, ⟨Entity HO⟩, ⟨Entity HP⟩, ⟨Entity HQ⟩, ⟨Entity HR⟩, ⟨Entity HS⟩, ⟨Entity HT⟩, ⟨Entity HU⟩, ⟨Entity HV⟩, ⟨Entity HW⟩, ⟨Entity HX⟩, ⟨Entity HY⟩, ⟨Entity HZ⟩, ⟨Entity IA⟩, ⟨Entity IB⟩, ⟨Entity IC⟩, ⟨Entity ID⟩, ⟨Entity IE⟩, ⟨Entity IF⟩, ⟨Entity IG⟩, ⟨Entity IH⟩, ⟨Entity II⟩, ⟨Entity IJ⟩, ⟨Entity IK⟩, ⟨Entity IL⟩, ⟨Entity IM⟩, ⟨Entity IN⟩, ⟨Entity IO⟩, ⟨Entity IP⟩, ⟨Entity IQ⟩, ⟨Entity IR⟩, ⟨Entity IS⟩, ⟨Entity IT⟩, ⟨Entity IU⟩, ⟨Entity IV⟩, ⟨Entity IW⟩, ⟨Entity IX⟩, ⟨Entity IY⟩, ⟨Entity IZ⟩, ⟨Entity JA⟩, ⟨Entity JB⟩, ⟨Entity JC⟩, ⟨Entity JD⟩, ⟨Entity JE⟩, ⟨Entity JF⟩, ⟨Entity JG⟩, ⟨Entity JH⟩, ⟨Entity JI⟩, ⟨Entity JJ⟩, ⟨Entity JK⟩, ⟨Entity JL⟩, ⟨Entity JM⟩, ⟨Entity JN⟩, ⟨Entity JO⟩, ⟨Entity JP⟩, ⟨Entity JQ⟩, ⟨Entity JR⟩, ⟨Entity JS⟩, ⟨Entity JT⟩, ⟨Entity JU⟩, ⟨Entity JV⟩, ⟨Entity JW⟩, ⟨Entity JX⟩, ⟨Entity JY⟩, ⟨Entity JZ⟩, ⟨Entity KA⟩, ⟨Entity KB⟩, ⟨Entity KC⟩, ⟨Entity KD⟩, ⟨Entity KE⟩, ⟨Entity KF⟩, ⟨Entity KG⟩, ⟨Entity KH⟩, ⟨Entity KI⟩, ⟨Entity KJ⟩, ⟨Entity KK⟩, ⟨Entity KL⟩, ⟨Entity KM⟩, ⟨Entity KN⟩, ⟨Entity KO⟩, ⟨Entity KP⟩, ⟨Entity KQ⟩, ⟨Entity KR⟩, ⟨Entity KS⟩, ⟨Entity KT⟩, ⟨Entity KU⟩, ⟨Entity HI⟩, ⟨Entity HJ⟩])} entities")179180# Practical decision guide181print("\nPractical decision guide:")182183print("\nUse __slots__ when:")184print(" ✓ Creating many instances (>1000)")185print(" ✓ Attributes are fixed and known")186print(" ✓ Memory is constrained")187print(" ✓ Attribute access speed matters")188print(" ✓ Preventing attribute typos is valuable")189190print("\nAvoid __slots__ when:")191print(" ✗ Dynamic attributes are needed")192print(" ✗ Only a few instances exist")193print(" ✗ Complex inheritance hierarchies")194print(" ✗ Need __dict__ for introspection")195print(" ✗ Using libraries that expect __dict__")196197# Real-world example198print("\nReal-world example:")199200# Time series data storage201class TimeSeriesPoint:202 __slots__ = ['timestamp', 'value']203 204 def __init__(self, timestamp, value):205 self.timestamp = timestamp206 self.value = value207208# Simulate 1 day of per-second data209seconds_per_day→ 86400 = 86400210timeseries = [TimeSeriesPoint(i, i * 0.1) for i in range(100)] # Sampleoutput✓ Good: Game with 100 entities Practical decision guide: Use __slots__ when: ✓ Creating many instances (>1000) ✓ Attributes are fixed and known ✓ Memory is constrained ✓ Attribute access speed matters ✓ Preventing attribute typos is valuable Avoid __slots__ when: ✗ Dynamic attributes are needed ✗ Only a few instances exist ✗ Complex inheritance hierarchies ✗ Need __dict__ for introspection ✗ Using libraries that expect __dict__ Real-world example:self.timestamp ← 0, self.value ← 0.0
pass 1 of 100204def __init__(self⟨TimeSeriesPoint KV⟩, timestamp0, value0.0):205 self.timestamp→ 0 = timestamp0206 self.value→ 0.0 = value0.0100 passes — pass 1 is the card above pass selftimestampvalueself.timestampself.value1 ⟨TimeSeriesPoint KV⟩ 0 0.0 0 0.0 2 ⟨TimeSeriesPoint KW⟩ 1 0.1 1 0.1 3 ⟨TimeSeriesPoint KX⟩ 2 0.2 2 0.2 4 ⟨TimeSeriesPoint KY⟩ 3 0.30000000000000004 3 0.30000000000000004 5 ⟨TimeSeriesPoint KZ⟩ 4 0.4 4 0.4 6 ⟨TimeSeriesPoint LA⟩ 5 0.5 5 0.5 7 ⟨TimeSeriesPoint LB⟩ 6 0.6000000000000001 6 0.6000000000000001 8 ⟨TimeSeriesPoint LC⟩ 7 0.7000000000000001 7 0.7000000000000001 9 ⟨TimeSeriesPoint LD⟩ 8 0.8 8 0.8 ⋯ 89 more passes ⋯ 99 ⟨TimeSeriesPoint LE⟩ 98 9.8 98 9.8 100 ⟨TimeSeriesPoint LF⟩ 99 9.9 99 9.9 timeseries ← [⟨TimeSeriesPoint KV⟩, ⟨TimeSeriesPoint KW⟩, ⟨TimeSeriesPoint KX⟩, ⟨TimeSeriesPoint KY⟩, ⟨TimeSeriesPoint KZ⟩, ⟨TimeSeriesPoint LA⟩, ⟨TimeSeriesPoint LB⟩, ⟨TimeSeriesPoint LC⟩, ⟨TimeSeriesPoint LD⟩, ⟨TimeSeriesPoint LG⟩, ⟨TimeSeriesPoint LH⟩, ⟨TimeSeriesPoint LI⟩, ⟨TimeSeriesPoint LJ⟩, ⟨TimeSeriesPoint LK⟩, ⟨TimeSeriesPoint LL⟩, ⟨TimeSeriesPoint LM⟩, ⟨TimeSeriesPoint LN⟩, ⟨TimeSeriesPoint LO⟩, ⟨TimeSeriesPoint LP⟩, ⟨TimeSeriesPoint LQ⟩, ⟨TimeSeriesPoint LR⟩, ⟨TimeSeriesPoint LS⟩, ⟨TimeSeriesPoint LT⟩, ⟨TimeSeriesPoint LU⟩, ⟨TimeSeriesPoint LV⟩, ⟨TimeSeriesPoint LW⟩, ⟨TimeSeriesPoint LX⟩, ⟨TimeSeriesPoint LY⟩, ⟨TimeSeriesPoint LZ⟩, ⟨TimeSeriesPoint MA⟩, ⟨TimeSeriesPoint MB⟩, ⟨TimeSeriesPoint MC⟩, ⟨TimeSeriesPoint MD⟩, ⟨TimeSeriesPoint ME⟩, ⟨TimeSeriesPoint MF⟩, ⟨TimeSeriesPoint MG⟩, ⟨TimeSeriesPoint MH⟩, ⟨TimeSeriesPoint MI⟩, ⟨TimeSeriesPoint MJ⟩, ⟨TimeSeriesPoint MK⟩, ⟨TimeSeriesPoint ML⟩, ⟨TimeSeriesPoint MM⟩, ⟨TimeSeriesPoint MN⟩, ⟨TimeSeriesPoint MO⟩, ⟨TimeSeriesPoint MP⟩, ⟨TimeSeriesPoint MQ⟩, ⟨TimeSeriesPoint MR⟩, ⟨TimeSeriesPoint MS⟩, ⟨TimeSeriesPoint MT⟩, ⟨TimeSeriesPoint MU⟩, ⟨TimeSeriesPoint MV⟩, ⟨TimeSeriesPoint MW⟩, ⟨TimeSeriesPoint MX⟩, ⟨TimeSeriesPoint MY⟩, ⟨TimeSeriesPoint MZ⟩, ⟨TimeSeriesPoint NA⟩, ⟨TimeSeriesPoint NB⟩, ⟨TimeSeriesPoint NC⟩, ⟨TimeSeriesPoint ND⟩, ⟨TimeSeriesPoint NE⟩, ⟨TimeSeriesPoint NF⟩, ⟨TimeSeriesPoint NG⟩, ⟨TimeSeriesPoint NH⟩, ⟨TimeSeriesPoint NI⟩, ⟨TimeSeriesPoint NJ⟩, ⟨TimeSeriesPoint NK⟩, ⟨TimeSeriesPoint NL⟩, ⟨TimeSeriesPoint NM⟩, ⟨TimeSeriesPoint NN⟩, ⟨TimeSeriesPoint NO⟩, ⟨TimeSeriesPoint NP⟩, ⟨TimeSeriesPoint NQ⟩, ⟨TimeSeriesPoint NR⟩, ⟨TimeSeriesPoint NS⟩, ⟨TimeSeriesPoint NT⟩, ⟨TimeSeriesPoint NU⟩, ⟨TimeSeriesPoint NV⟩, ⟨TimeSeriesPoint NW⟩, ⟨TimeSeriesPoint NX⟩, ⟨TimeSeriesPoint NY⟩, ⟨TimeSeriesPoint NZ⟩, ⟨TimeSeriesPoint OA⟩, ⟨TimeSeriesPoint OB⟩, ⟨TimeSeriesPoint OC⟩, ⟨TimeSeriesPoint OD⟩, ⟨TimeSeriesPoint OE⟩, ⟨TimeSeriesPoint OF⟩, ⟨TimeSeriesPoint OG⟩, ⟨TimeSeriesPoint OH⟩, ⟨TimeSeriesPoint OI⟩, ⟨TimeSeriesPoint OJ⟩, ⟨TimeSeriesPoint OK⟩, ⟨TimeSeriesPoint OL⟩, ⟨TimeSeriesPoint OM⟩, ⟨TimeSeriesPoint ON⟩, ⟨TimeSeriesPoint OO⟩, ⟨TimeSeriesPoint OP⟩, ⟨TimeSeriesPoint OQ⟩, ⟨TimeSeriesPoint LE⟩, ⟨TimeSeriesPoint LF⟩]
209seconds_per_day = 86400210timeseries→ [⟨TimeSeriesPoint KV⟩, ⟨TimeSeriesPoint KW⟩, ⟨TimeSeriesPoint KX⟩, ⟨TimeSeriesPoint KY⟩, ⟨TimeSeriesPoint KZ⟩, ⟨TimeSeriesPoint LA⟩, ⟨TimeSeriesPoint LB⟩, ⟨TimeSeriesPoint LC⟩, ⟨TimeSeriesPoint LD⟩, ⟨TimeSeriesPoint LG⟩, ⟨TimeSeriesPoint LH⟩, ⟨TimeSeriesPoint LI⟩, ⟨TimeSeriesPoint LJ⟩, ⟨TimeSeriesPoint LK⟩, ⟨TimeSeriesPoint LL⟩, ⟨TimeSeriesPoint LM⟩, ⟨TimeSeriesPoint LN⟩, ⟨TimeSeriesPoint LO⟩, ⟨TimeSeriesPoint LP⟩, ⟨TimeSeriesPoint LQ⟩, ⟨TimeSeriesPoint LR⟩, ⟨TimeSeriesPoint LS⟩, ⟨TimeSeriesPoint LT⟩, ⟨TimeSeriesPoint LU⟩, ⟨TimeSeriesPoint LV⟩, ⟨TimeSeriesPoint LW⟩, ⟨TimeSeriesPoint LX⟩, ⟨TimeSeriesPoint LY⟩, ⟨TimeSeriesPoint LZ⟩, ⟨TimeSeriesPoint MA⟩, ⟨TimeSeriesPoint MB⟩, ⟨TimeSeriesPoint MC⟩, ⟨TimeSeriesPoint MD⟩, ⟨TimeSeriesPoint ME⟩, ⟨TimeSeriesPoint MF⟩, ⟨TimeSeriesPoint MG⟩, ⟨TimeSeriesPoint MH⟩, ⟨TimeSeriesPoint MI⟩, ⟨TimeSeriesPoint MJ⟩, ⟨TimeSeriesPoint MK⟩, ⟨TimeSeriesPoint ML⟩, ⟨TimeSeriesPoint MM⟩, ⟨TimeSeriesPoint MN⟩, ⟨TimeSeriesPoint MO⟩, ⟨TimeSeriesPoint MP⟩, ⟨TimeSeriesPoint MQ⟩, ⟨TimeSeriesPoint MR⟩, ⟨TimeSeriesPoint MS⟩, ⟨TimeSeriesPoint MT⟩, ⟨TimeSeriesPoint MU⟩, ⟨TimeSeriesPoint MV⟩, ⟨TimeSeriesPoint MW⟩, ⟨TimeSeriesPoint MX⟩, ⟨TimeSeriesPoint MY⟩, ⟨TimeSeriesPoint MZ⟩, ⟨TimeSeriesPoint NA⟩, ⟨TimeSeriesPoint NB⟩, ⟨TimeSeriesPoint NC⟩, ⟨TimeSeriesPoint ND⟩, ⟨TimeSeriesPoint NE⟩, ⟨TimeSeriesPoint NF⟩, ⟨TimeSeriesPoint NG⟩, ⟨TimeSeriesPoint NH⟩, ⟨TimeSeriesPoint NI⟩, ⟨TimeSeriesPoint NJ⟩, ⟨TimeSeriesPoint NK⟩, ⟨TimeSeriesPoint NL⟩, ⟨TimeSeriesPoint NM⟩, ⟨TimeSeriesPoint NN⟩, ⟨TimeSeriesPoint NO⟩, ⟨TimeSeriesPoint NP⟩, ⟨TimeSeriesPoint NQ⟩, ⟨TimeSeriesPoint NR⟩, ⟨TimeSeriesPoint NS⟩, ⟨TimeSeriesPoint NT⟩, ⟨TimeSeriesPoint NU⟩, ⟨TimeSeriesPoint NV⟩, ⟨TimeSeriesPoint NW⟩, ⟨TimeSeriesPoint NX⟩, ⟨TimeSeriesPoint NY⟩, ⟨TimeSeriesPoint NZ⟩, ⟨TimeSeriesPoint OA⟩, ⟨TimeSeriesPoint OB⟩, ⟨TimeSeriesPoint OC⟩, ⟨TimeSeriesPoint OD⟩, ⟨TimeSeriesPoint OE⟩, ⟨TimeSeriesPoint OF⟩, ⟨TimeSeriesPoint OG⟩, ⟨TimeSeriesPoint OH⟩, ⟨TimeSeriesPoint OI⟩, ⟨TimeSeriesPoint OJ⟩, ⟨TimeSeriesPoint OK⟩, ⟨TimeSeriesPoint OL⟩, ⟨TimeSeriesPoint OM⟩, ⟨TimeSeriesPoint ON⟩, ⟨TimeSeriesPoint OO⟩, ⟨TimeSeriesPoint OP⟩, ⟨TimeSeriesPoint OQ⟩, ⟨TimeSeriesPoint LE⟩, ⟨TimeSeriesPoint LF⟩] = [TimeSeriesPoint(i, i * 0.1) for i in range(100)] # Sample211212print(f"✓ Excellent use case: Time series with {len(timeseries[⟨TimeSeriesPoint KV⟩, ⟨TimeSeriesPoint KW⟩, ⟨TimeSeriesPoint KX⟩, ⟨TimeSeriesPoint KY⟩, ⟨TimeSeriesPoint KZ⟩, ⟨TimeSeriesPoint LA⟩, ⟨TimeSeriesPoint LB⟩, ⟨TimeSeriesPoint LC⟩, ⟨TimeSeriesPoint LD⟩, ⟨TimeSeriesPoint LG⟩, ⟨TimeSeriesPoint LH⟩, ⟨TimeSeriesPoint LI⟩, ⟨TimeSeriesPoint LJ⟩, ⟨TimeSeriesPoint LK⟩, ⟨TimeSeriesPoint LL⟩, ⟨TimeSeriesPoint LM⟩, ⟨TimeSeriesPoint LN⟩, ⟨TimeSeriesPoint LO⟩, ⟨TimeSeriesPoint LP⟩, ⟨TimeSeriesPoint LQ⟩, ⟨TimeSeriesPoint LR⟩, ⟨TimeSeriesPoint LS⟩, ⟨TimeSeriesPoint LT⟩, ⟨TimeSeriesPoint LU⟩, ⟨TimeSeriesPoint LV⟩, ⟨TimeSeriesPoint LW⟩, ⟨TimeSeriesPoint LX⟩, ⟨TimeSeriesPoint LY⟩, ⟨TimeSeriesPoint LZ⟩, ⟨TimeSeriesPoint MA⟩, ⟨TimeSeriesPoint MB⟩, ⟨TimeSeriesPoint MC⟩, ⟨TimeSeriesPoint MD⟩, ⟨TimeSeriesPoint ME⟩, ⟨TimeSeriesPoint MF⟩, ⟨TimeSeriesPoint MG⟩, ⟨TimeSeriesPoint MH⟩, ⟨TimeSeriesPoint MI⟩, ⟨TimeSeriesPoint MJ⟩, ⟨TimeSeriesPoint MK⟩, ⟨TimeSeriesPoint ML⟩, ⟨TimeSeriesPoint MM⟩, ⟨TimeSeriesPoint MN⟩, ⟨TimeSeriesPoint MO⟩, ⟨TimeSeriesPoint MP⟩, ⟨TimeSeriesPoint MQ⟩, ⟨TimeSeriesPoint MR⟩, ⟨TimeSeriesPoint MS⟩, ⟨TimeSeriesPoint MT⟩, ⟨TimeSeriesPoint MU⟩, ⟨TimeSeriesPoint MV⟩, ⟨TimeSeriesPoint MW⟩, ⟨TimeSeriesPoint MX⟩, ⟨TimeSeriesPoint MY⟩, ⟨TimeSeriesPoint MZ⟩, ⟨TimeSeriesPoint NA⟩, ⟨TimeSeriesPoint NB⟩, ⟨TimeSeriesPoint NC⟩, ⟨TimeSeriesPoint ND⟩, ⟨TimeSeriesPoint NE⟩, ⟨TimeSeriesPoint NF⟩, ⟨TimeSeriesPoint NG⟩, ⟨TimeSeriesPoint NH⟩, ⟨TimeSeriesPoint NI⟩, ⟨TimeSeriesPoint NJ⟩, ⟨TimeSeriesPoint NK⟩, ⟨TimeSeriesPoint NL⟩, ⟨TimeSeriesPoint NM⟩, ⟨TimeSeriesPoint NN⟩, ⟨TimeSeriesPoint NO⟩, ⟨TimeSeriesPoint NP⟩, ⟨TimeSeriesPoint NQ⟩, ⟨TimeSeriesPoint NR⟩, ⟨TimeSeriesPoint NS⟩, ⟨TimeSeriesPoint NT⟩, ⟨TimeSeriesPoint NU⟩, ⟨TimeSeriesPoint NV⟩, ⟨TimeSeriesPoint NW⟩, ⟨TimeSeriesPoint NX⟩, ⟨TimeSeriesPoint NY⟩, ⟨TimeSeriesPoint NZ⟩, ⟨TimeSeriesPoint OA⟩, ⟨TimeSeriesPoint OB⟩, ⟨TimeSeriesPoint OC⟩, ⟨TimeSeriesPoint OD⟩, ⟨TimeSeriesPoint OE⟩, ⟨TimeSeriesPoint OF⟩, ⟨TimeSeriesPoint OG⟩, ⟨TimeSeriesPoint OH⟩, ⟨TimeSeriesPoint OI⟩, ⟨TimeSeriesPoint OJ⟩, ⟨TimeSeriesPoint OK⟩, ⟨TimeSeriesPoint OL⟩, ⟨TimeSeriesPoint OM⟩, ⟨TimeSeriesPoint ON⟩, ⟨TimeSeriesPoint OO⟩, ⟨TimeSeriesPoint OP⟩, ⟨TimeSeriesPoint OQ⟩, ⟨TimeSeriesPoint LE⟩, ⟨TimeSeriesPoint LF⟩])} data points")213print(f" Each point: timestamp + value")214print(f" Fixed schema, many instances, memory-efficient")output✓ Excellent use case: Time series with 100 data points Each point: timestamp + value Fixed schema, many instances, memory-efficient
The decision comes down to: Do you have many instances? Are attributes fixed and known? Is memory or access speed a concern?
Benefits
- Memory savings: ~40-50% reduction for simple classes
- Faster attribute access: No dict lookup overhead
- Type safety: Prevents typos in attribute names
Limitations
- No dynamic attributes after instantiation
- Inheritance requires care (all classes need
__slots__) - No
__dict__by default (breaks some libraries) - Cannot use with multiple inheritance from slotted classes with non-empty slots
Exercise: slots_practice.py
Create a Point class with __slots__ and compare its memory usage to a regular class