Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions python-dict-attribute/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Using Python's `.__dict__` to Work With Attributes

This folder provides the code examples for the Real Python tutorial [Using Python's `.__dict__` to Work With Attributes](https://realpython.com/python-dict-attribute/).
16 changes: 16 additions & 0 deletions python-dict-attribute/class_inheritance.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
class Parent:
def __init__(self):
self.parent_attr = "parent"


class Child(Parent):
def __init__(self):
super().__init__()
self.child_attr = "child"


parent = Parent()
print(parent.__dict__)

child = Child()
print(child.__dict__)
16 changes: 16 additions & 0 deletions python-dict-attribute/config_v1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
class Config:
def __init__(self, **kwargs):
self.__dict__.update(kwargs)

update = __init__

def __str__(self):
return str(self.__dict__)


config = Config(theme="light", font_size=12, language="English")
print(config)

user = {"theme": "dark", "font_size": 14, "language": "Spanish"}
config.update(**user)
print(config)
33 changes: 33 additions & 0 deletions python-dict-attribute/config_v2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
class Config:
def __init__(self, name):
self.name = name

def set_option(self, key, value):
self.__dict__[key] = value

def get_option(self, key):
return self.__dict__.get(key, None)

def remove_option(self, key):
if key in self.__dict__:
del self.__dict__[key]
# self.__dict__.pop(key)
print(f"'{key}' removed!")
else:
print(f"'{key}' does not exist.")

def clear(self):
self.__dict__.clear()
print("All options removed!")


conf = Config("GUI App")
conf.set_option("theme", "dark")
conf.set_option("size", "200x400")
print(conf.__dict__)
conf.remove_option("size")
print(conf.__dict__)
conf.remove_option("autosave")
print(conf.__dict__)
conf.clear()
print(conf.__dict__)
33 changes: 33 additions & 0 deletions python-dict-attribute/config_v3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
class Config:
def __init__(self, name):
self.name = name

def set_option(self, key, value):
setattr(self, key, value)

def get_option(self, key):
return getattr(self, key, None)

def remove_option(self, key):
if hasattr(self, key):
delattr(self, key)
print(f"'{key}' removed!")
else:
print(f"'{key}' does not exist.")

def clear(self):
for key in list(self.__dict__.keys()):
delattr(self, key)
print("All options removed!")


conf = Config("GUI App")
conf.set_option("theme", "dark")
conf.set_option("size", "200x400")
print(conf.__dict__)
conf.remove_option("size")
print(conf.__dict__)
conf.remove_option("autosave") # Raises KeyError
print(conf.__dict__)
conf.clear()
print(conf.__dict__)
13 changes: 13 additions & 0 deletions python-dict-attribute/demo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
class DemoClass:
class_attr = "This is a class attribute"

def __init__(self):
self.instance_attr = "This is an instance attribute"

def method(self):
return "This is a method"


print(DemoClass.__dict__)
demo_object = DemoClass()
print(demo_object.__dict__)
27 changes: 27 additions & 0 deletions python-dict-attribute/fibonacci.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import time


def fibonacci_of_v1(n):
if n <= 1:
return n
return fibonacci_of_v1(n - 1) + fibonacci_of_v1(n - 2)


start = time.perf_counter()
fibonacci_of_v1(35)
end = time.perf_counter()
print(f"{end - start:.3f} seconds")


def fibonacci_of_v2(n):
cache = fibonacci_of_v2.__dict__.setdefault("cache", {})
if n in cache:
return cache[n]
cache[n] = n if n <= 1 else fibonacci_of_v2(n - 1) + fibonacci_of_v2(n - 2)
return cache[n]


start = time.perf_counter()
fibonacci_of_v2(35)
end = time.perf_counter()
print(f"{end - start:.3f} seconds")
29 changes: 29 additions & 0 deletions python-dict-attribute/person.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
class Person:
def __init__(self, first_name, last_name, age):
self.first_name = first_name
self.last_name = last_name
self.age = age

def __str__(self):
return "{first_name} {last_name} is {age} years old".format(
**self.__dict__
)

def __repr__(self):
return "{cls}('{first_name}', '{last_name}', {age})".format(
cls=type(self).__name__,
**self.__dict__,
)

def as_dict(self):
return self.__dict__

def as_tuple(self):
return tuple(self.__dict__.values())


john = Person("John", "Doe", 30)
print(repr(john))
print(john)
print(john.as_dict())
print(john.as_tuple())
48 changes: 48 additions & 0 deletions python-dict-attribute/record.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import logging

logging.basicConfig(level=logging.INFO, format="%(message)s")


class Record:
def __init__(self, **fields):
logging.info(f"[INIT] Creating record with fields: {fields}")
self.__dict__.update(fields)

def __getattribute__(self, key):
if key == "__dict__":
return super().__getattribute__(key)
value = super().__getattribute__(key)
logging.info(f"[GET] Accessing '{key}' → {value}")
return value

def __setattr__(self, key, value):
if key in self.__dict__:
logging.info(f"[UPDATE] Modifying '{key}' → {value}")
else:
logging.info(f"[SET] Creating '{key}' → {value}")
self.__dict__[key] = value

def __delattr__(self, key):
if key in self.__dict__:
logging.info(f"[DEL] Deleting '{key}'")
del self.__dict__[key]
else:
logging.warning(
f"[DEL] Attempted to delete non-existent field '{key}'"
)


jane = Record(first_name="Jane", last_name="Doe", age=25)

# Access
print(jane.first_name)
print(jane.age)

# Mutations
jane.age = 26
jane.job = "Software Engineer"
print(jane.__dict__)

# Deletion
del jane.age
print(jane.__dict__)
14 changes: 14 additions & 0 deletions python-dict-attribute/salary.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
class Employee:
def __init__(self, name, department, salary):
self.name = name
self.department = department
self.salary = salary

def give_raise(self, amount):
self.salery = self.salary + amount # Typo here: self.salery


john = Employee("John", "Engineering", 70000)
john.give_raise(5000)
print(john.salary)
print(john.__dict__)
10 changes: 10 additions & 0 deletions python-dict-attribute/track_calls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
def track_calls():
track_calls.__dict__["calls"] = track_calls.__dict__.get("calls", 0) + 1
print(f"Calls: {track_calls.calls}")


track_calls()
track_calls()
track_calls()

print(track_calls.calls)