Skip to content
Open
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
11 changes: 11 additions & 0 deletions python-metaclasses/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Python Metaclasses

This folder provides the code examples for the Real Python tutorial [Python Metaclasses](https://realpython.com/python-metaclasses/).

The tutorial demonstrates its examples in the interactive interpreter, so each
REPL sequence is collected here as a runnable script that prints the output the
tutorial shows. Run any of them with Python 3.14:

```sh
$ python custom_metaclass.py
```
25 changes: 25 additions & 0 deletions python-metaclasses/class_decorator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
def decorator(cls):
class NewClass(cls):
attr = 100

return NewClass


@decorator
class X:
pass


@decorator
class Y:
pass


@decorator
class Z:
pass


print(X.attr)
print(Y.attr)
print(Z.attr)
24 changes: 24 additions & 0 deletions python-metaclasses/class_factory.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
class Meta(type):
def __init__(cls, name, bases, dct):
cls.attr = 100


class X(metaclass=Meta):
pass


print(X.attr)


class Y(metaclass=Meta):
pass


print(Y.attr)


class Z(metaclass=Meta):
pass


print(Z.attr)
23 changes: 23 additions & 0 deletions python-metaclasses/custom_metaclass.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
class Meta(type):
def __new__(cls, name, bases, dct):
x = super().__new__(cls, name, bases, dct)
x.attr = 100
return x


class Foo(metaclass=Meta):
pass


print(Foo.attr)


class Bar(metaclass=Meta):
pass


class Qux(metaclass=Meta):
pass


print((Bar.attr, Qux.attr))
17 changes: 17 additions & 0 deletions python-metaclasses/custom_new_method.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
class Foo:
pass


def new(cls):
x = object.__new__(cls)
x.attr = 100
return x


Foo.__new__ = new

f = Foo()
print(f.attr)

g = Foo()
print(g.attr)
14 changes: 14 additions & 0 deletions python-metaclasses/dynamic_class_example_1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Defining the class dynamically with type()
Foo = type("Foo", (), {})

x = Foo()
print(x)


# The same class defined the usual way, with the class statement
class Foo:
pass


x = Foo()
print(x)
21 changes: 21 additions & 0 deletions python-metaclasses/dynamic_class_example_2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Foo comes from Example 1
Foo = type("Foo", (), {})

# Defining the class dynamically with type()
Bar = type("Bar", (Foo,), dict(attr=100))

x = Bar()
print(x.attr)
print(x.__class__)
print(x.__class__.__bases__)


# The same class defined the usual way, with the class statement
class Bar(Foo):
attr = 100


x = Bar()
print(x.attr)
print(x.__class__)
print(x.__class__.__bases__)
19 changes: 19 additions & 0 deletions python-metaclasses/dynamic_class_example_3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Defining the class dynamically with type()
Foo = type("Foo", (), {"attr": 100, "attr_val": lambda x: x.attr})

x = Foo()
print(x.attr)
print(x.attr_val())


# The same class defined the usual way, with the class statement
class Foo:
attr = 100

def attr_val(self):
return self.attr


x = Foo()
print(x.attr)
print(x.attr_val())
21 changes: 21 additions & 0 deletions python-metaclasses/dynamic_class_example_4.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
def f(obj):
print("attr =", obj.attr)


# Defining the class dynamically with type()
Foo = type("Foo", (), {"attr": 100, "attr_val": f})

x = Foo()
print(x.attr)
x.attr_val()


# The same class defined the usual way, with the class statement
class Foo:
attr = 100
attr_val = f


x = Foo()
print(x.attr)
x.attr_val()
15 changes: 15 additions & 0 deletions python-metaclasses/new_style_classes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
class Foo:
pass


obj = Foo()
print(obj.__class__)
print(type(obj))
print(obj.__class__ is type(obj))

n = 5
d = {"x": 1, "y": 2}
x = Foo()

for obj in (n, d, x):
print(type(obj) is obj.__class__)
13 changes: 13 additions & 0 deletions python-metaclasses/object_factory.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
class Foo:
def __init__(self):
self.attr = 100


x = Foo()
print(x.attr)

y = Foo()
print(y.attr)

z = Foo()
print(z.attr)
11 changes: 11 additions & 0 deletions python-metaclasses/reassigning_type_new.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Spoiler alert: This doesn't work!
def new(cls):
x = type.__new__(cls)
x.attr = 100
return x


try:
type.__new__ = new
except TypeError as ex:
print(ex)
19 changes: 19 additions & 0 deletions python-metaclasses/simple_inheritance.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
class Base:
attr = 100


class X(Base):
pass


class Y(Base):
pass


class Z(Base):
pass


print(X.attr)
print(Y.attr)
print(Z.attr)
12 changes: 12 additions & 0 deletions python-metaclasses/type_and_class.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
class Foo:
pass


x = Foo()
print(type(x))
print(type(Foo))

for t in int, float, dict, list, tuple:
print(type(t))

print(type(type))
12 changes: 12 additions & 0 deletions python-metaclasses/type_with_one_argument.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
print(type(3))
print(type(["foo", "bar", "baz"]))

t = (1, 2, 3, 4, 5)
print(type(t))


class Foo:
pass


print(type(Foo()))
Loading