Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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)
21 changes: 21 additions & 0 deletions python-dict-attribute/config_v2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
class Config:
Comment thread
martin-martin marked this conversation as resolved.
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!")
Comment thread
martin-martin marked this conversation as resolved.
21 changes: 21 additions & 0 deletions python-dict-attribute/config_v3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
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!")
11 changes: 11 additions & 0 deletions python-dict-attribute/demo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
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__)
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_v1.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())


person = Person("John", "Doe", 30)
print(repr(person))
print(person)
print(person.as_dict())
print(person.as_tuple())
26 changes: 26 additions & 0 deletions python-dict-attribute/person_v2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
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())

def from_dict(self, data):
self.__dict__.update(data)
return self
26 changes: 26 additions & 0 deletions python-dict-attribute/plain_record.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
class Record:
"""Hold a record of data."""


john = {
"name": "John Doe",
"position": "Python Developer",
"department": "Engineering",
"salary": 80000,
"hire_date": "2020-01-01",
"is_manager": False,
}


def as_dict(self):
return self.__dict__


Record.as_dict = as_dict
print(Record.__dict__)

john_record = Record()
john_record.__dict__.update(john)
print(john_record.name)
print(john_record.department)
print(john_record.as_dict())
32 changes: 32 additions & 0 deletions python-dict-attribute/record.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
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}'"
)
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)