0% found this document useful (0 votes)
26 views

Python Class Constructors

The document discusses Python class constructors and how they control object instantiation through the __new__ and __init__ methods. __new__ controls the creation of a new object instance while __init__ initializes the internal state of the new object instance.

Uploaded by

Nikos Leounakis
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
26 views

Python Class Constructors

The document discusses Python class constructors and how they control object instantiation through the __new__ and __init__ methods. __new__ controls the creation of a new object instance while __init__ initializes the internal state of the new object instance.

Uploaded by

Nikos Leounakis
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 18

Python Class Constructors: Control Your Object Instantiation – Real Python https://realpython.com/python-class-constructor/#:~:text=Class%20constructors%20are%20a%20fu...

1 of 18 4/1/2022, 9:18 PM
Python Class Constructors: Control Your Object Instantiation – Real Python https://realpython.com/python-class-constructor/#:~:text=Class%20constructors%20are%20a%20fu...

.__init__()

.__new__()

class

>>> class SomeClass:


... pass
...

>>> # Call the class to construct an object


>>> SomeClass()
<__main__.SomeClass object at 0x7fecf442a140>

SomeClass class
pass

SomeClass

2 of 18 4/1/2022, 9:18 PM
Python Class Constructors: Control Your Object Instantiation – Real Python https://realpython.com/python-class-constructor/#:~:text=Class%20constructors%20are%20a%20fu...

.__call__()

.__new__()
.__init__()

.__init__() self

.__new__()
.__init__()

Point
.__new__() .__init__()

# point.py

class Point:
def __new__(cls, *args, **kwargs):
print("1. Create a new instance of Point.")
return super().__new__(cls)

def __init__(self, x, y):


print("2. Initialize the new instance of Point.")
self.x = x
self.y = y

def __repr__(self) -> str:


return f"{type(self).__name__}(x={self.x}, y={self.y})"

Point class

.__new__() cls
self *args
**kwargs

.__new__()

Point .__new__() cls


object super()
.__init__()

.__init__() self
x y
.x .y
Point()

3 of 18 4/1/2022, 9:18 PM
Python Class Constructors: Control Your Object Instantiation – Real Python https://realpython.com/python-class-constructor/#:~:text=Class%20constructors%20are%20a%20fu...

.__init__()

.x .y x y

.__repr__() Point

Point point.py

>>> from point import Point

>>> point = Point(21, 42)


1. Create a new instance of Point.
2. Initialize the new instance of Point.

>>> point
Point(x=21, y=42)

Point()
point

.__new__() .__init__() Point

>>> from point import Point

>>> point = Point.__new__(Point)


1. Create a new instance of Point.

>>> # The point object is not initialized


>>> point.x
Traceback (most recent call last):
...
AttributeError: 'Point' object has no attribute 'x'
>>> point.y
Traceback (most recent call last):
...
AttributeError: 'Point' object has no attribute 'y'

>>> point.__init__(21, 42)


2. Initialize the new instance of Point.

>>> # Now point is properly initialized


>>> point
Point(x=21, y=42)

.__new__() Point

.__init__()

.__init__()
Point

.__new__()

4 of 18 4/1/2022, 9:18 PM
Python Class Constructors: Control Your Object Instantiation – Real Python https://realpython.com/python-class-constructor/#:~:text=Class%20constructors%20are%20a%20fu...

.__init__()

.__new__() B A

# ab_classes.py

class A:
def __init__(self, a_value):
print("Initialize the new instance of A.")
self.a_value = a_value

class B:
def __new__(cls, *args, **kwargs):
return A(42)

def __init__(self, b_value):


print("Initialize the new instance of B.")
self.b_value = b_value

B.__new__() B.__init__()
ab_classes.py

>>> from ab_classes import B

>>> b = B(21)
Initialize the new instance of A.

>>> b.b_value
Traceback (most recent call last):
...
AttributeError: 'A' object has no attribute 'b_value'

>>> isinstance(b, B)
False
>>> isinstance(b, A)
True

>>> b.a_value
42

B() B.__new__() A B B.__init__()


b .b_value b .a_value 42

.__init__() .__new__()

.__init__()
.__init__()
.__init__()

.__init__()

5 of 18 4/1/2022, 9:18 PM
Python Class Constructors: Control Your Object Instantiation – Real Python https://realpython.com/python-class-constructor/#:~:text=Class%20constructors%20are%20a%20fu...

.__init__()
Rectangle .width .height

>>> class Rectangle:


... def __init__(self, width, height):
... self.width = width
... self.height = height
...

>>> rectangle = Rectangle(21, 42)


>>> rectangle.width
21
>>> rectangle.height
42

.__init__() self
.__new__() .__init__()
.width .height width height
.__init__()

self .__init__()
.__init__()

.__init__() None TypeError

>>> class Rectangle:


... def __init__(self, width, height):
... self.width = width
... self.height = height
... return 42
...

>>> rectangle = Rectangle(21, 42)


Traceback (most recent call last):
...
TypeError: __init__() should return None, not 'int'

.__init__() TypeError

.__init__() None None


return None

.__init__() .width .height

.__init__()
Rectangle width height

6 of 18 4/1/2022, 9:18 PM
Python Class Constructors: Control Your Object Instantiation – Real Python https://realpython.com/python-class-constructor/#:~:text=Class%20constructors%20are%20a%20fu...

>>> class Rectangle:


... def __init__(self, width, height):
... if not (isinstance(width, (int, float)) and width > 0):
... raise ValueError(f"positive width expected, got {width}")
... self.width = width
... if not (isinstance(height, (int, float)) and height > 0):
... raise ValueError(f"positive height expected, got {height}")
... self.height = height
...

>>> rectangle = Rectangle(-21, 42)


Traceback (most recent call last):
...
ValueError: positive width expected, got -21

.__init__() width height


.width .height ValueError

.__init__() .__init__()
super()

>>> class Person:


... def __init__(self, name, birth_date):
... self.name = name
... self.birth_date = birth_date
...

>>> class Employee(Person):


... def __init__(self, name, birth_date, position):
... super().__init__(name, birth_date)
... self.position = position
...

>>> john = Employee("John Doe", "2001-02-07", "Python Developer")

>>> john.name
'John Doe'
>>> john.birth_date
'2001-02-07'
>>> john.position
'Python Developer'

.__init__() Employee super().__init__() name birth_date


.name .birth_date Person

.__init__() object
.__init__()

7 of 18 4/1/2022, 9:18 PM
Python Class Constructors: Control Your Object Instantiation – Real Python https://realpython.com/python-class-constructor/#:~:text=Class%20constructors%20are%20a%20fu...

.__init__()

Greeter

# greet.py

class Greeter:
def __init__(self, name, formal=False):
self.name = name
self.formal = formal

def greet(self):
if self.formal:
print(f"Good morning, {self.name}!")
else:
print(f"Hello, {self.name}!")

.__init__() name formal


False formal

formal False
.greet()

Greeter greet.py

>>> from greet import Greeter

>>> informal_greeter = Greeter("Pythonista")


>>> informal_greeter.greet()
Hello, Pythonista!

>>> formal_greeter = Greeter("Pythonista", formal=True)


>>> formal_greeter.greet()
Good morning, Pythonista!

informal_greeter name
formal .greet() informal_greeter

name formal Greeter formal True


.greet()

.__init__()
.__new__()

.__new__()
.__new__()
object

.__new__()

8 of 18 4/1/2022, 9:18 PM
Python Class Constructors: Control Your Object Instantiation – Real Python https://realpython.com/python-class-constructor/#:~:text=Class%20constructors%20are%20a%20fu...

int float tuple str

.__new__()

.__new__()

super().__new__()

class SomeClass:
def __new__(cls, *args, **kwargs):
instance = super().__new__(cls)
# Customize your instance here...
return instance

.__new__() .__new__()
cls

*args **kwargs
.__new__() *args **kwargs

.__new__() .__new__()
.__new__() super()
object.__new__() .__new__()

object

object.__new__()
object.__new__() TypeError

>>> class SomeClass:


... def __new__(cls, *args, **kwargs):
... return super().__new__(cls, *args, **kwargs)
... def __init__(self, value):
... self.value = value
...

>>> SomeClass(42)
Traceback (most recent call last):
...
TypeError: object.__new__() takes exactly one argument (the type to instantiate)

*args **kwargs super().__new__()


object.__new__() TypeError

object.__new__() .__init__()

9 of 18 4/1/2022, 9:18 PM
Python Class Constructors: Control Your Object Instantiation – Real Python https://realpython.com/python-class-constructor/#:~:text=Class%20constructors%20are%20a%20fu...

.__new__() SomeClass

>>> class SomeClass:


... def __init__(self, value):
... self.value = value
...

>>> some_obj = SomeClass(42)


>>> some_obj
<__main__.SomeClass object at 0x7f67db8d0ac0>
>>> some_obj.value
42

SomeClass .__new__() object.__new__()


value SomeClass.__init__()
SomeClass some_obj

.__new__()

.__new__()
Distance float

.__init__()

>>> class Distance(float):


... def __init__(self, value, unit):
... super().__init__(value)
... self.unit = unit
...

>>> in_miles = Distance(42.0, "Miles")


Traceback (most recent call last):
...
TypeError: float expected at most 1 argument, got 2

float.__new__()
object.__new__()

.__new__() .__init__()

10 of 18 4/1/2022, 9:18 PM
Python Class Constructors: Control Your Object Instantiation – Real Python https://realpython.com/python-class-constructor/#:~:text=Class%20constructors%20are%20a%20fu...

>>> class Distance(float):


... def __new__(cls, value, unit):
... instance = super().__new__(cls, value)
... instance.unit = unit
... return instance
...

>>> in_miles = Distance(42.0, "Miles")


>>> in_miles
42.0
>>> in_miles.unit
'Miles'
>>> in_miles + 42.0
84.0

>>> dir(in_miles)
['__abs__', '__add__', ..., 'real', 'unit']

.__new__()
cls super().__new__() float.__new__()
value .unit

Distance
Distance(10, "km") + Distance(20, "miles")

Distance
Distance .unit
dir()
float

.__new__()

Pet .__new__()

11 of 18 4/1/2022, 9:18 PM
Python Class Constructors: Control Your Object Instantiation – Real Python https://realpython.com/python-class-constructor/#:~:text=Class%20constructors%20are%20a%20fu...

# pets.py

from random import choice

class Pet:
def __new__(cls):
other = choice([Dog, Cat, Python])
instance = super().__new__(other)
print(f"I'm a {type(instance).__name__}!")
return instance

def __init__(self):
print("Never runs!")

class Dog:
def communicate(self):
print("woof! woof!")

class Cat:
def communicate(self):
print("meow! meow!")

class Python:
def communicate(self):
print("hiss! hiss!")

Pet .__new__()

Pet

>>> from pets import Pet

>>> pet = Pet()


I'm a Dog!
>>> pet.communicate()
woof! woof!
>>> isinstance(pet, Pet)
False
>>> isinstance(pet, Dog)
True

>>> another_pet = Pet()


I'm a Python!
>>> another_pet.communicate()
hiss! hiss!

Pet
.__new__() .__new__()

.__init__() Pet Pet.__new__()


Pet

.__new__()

12 of 18 4/1/2022, 9:18 PM
Python Class Constructors: Control Your Object Instantiation – Real Python https://realpython.com/python-class-constructor/#:~:text=Class%20constructors%20are%20a%20fu...

Singleton .__new__()
.__new__()

>>> class Singleton(object):


... _instance = None
... def __new__(cls, *args, **kwargs):
... if cls._instance is None:
... cls._instance = super().__new__(cls)
... return cls._instance
...

>>> first = Singleton()


>>> second = Singleton()
>>> first is second
True

Singleton ._instance None


.__new__() cls._instance is None

Singleton .__init__()
.__init__() Singleton()

if Singleton cls._instance

Singleton first second


is first second
Singleton

collections.namedtuple
.__new__()
collections.namedtuple() namedtuple() tuple

named_tuple_factory()
.__new__() NamedTuple

13 of 18 4/1/2022, 9:18 PM
Python Class Constructors: Control Your Object Instantiation – Real Python https://realpython.com/python-class-constructor/#:~:text=Class%20constructors%20are%20a%20fu...

# named_tuple.py

from operator import itemgetter

def named_tuple_factory(type_name, *fields):


num_fields = len(fields)

class NamedTuple(tuple):
__slots__ = ()

def __new__(cls, *args):


if len(args) != num_fields:
raise TypeError(
f"{type_name} expected exactly {num_fields} arguments,"
f" got {len(args)}"
)
cls.__name__ = type_name
for index, field in enumerate(fields):
setattr(cls, field, property(itemgetter(index)))
return super().__new__(cls, args)

def __repr__(self):
return f"""{type_name}({", ".join(repr(arg) for arg in self)})"""

return NamedTuple

itemgetter() operators

named_tuple_factory() type_name
*fields

NamedTuple tuple

.__slots__
.__dict__

.__new__() cls *args

TypeError

.__name__ type_name

for itemgetter()
index setattr() enumerate()
index

super().__new__()

.__repr__()

NamedTuple

named_tuple_factory() named_tuple.py

14 of 18 4/1/2022, 9:18 PM
Python Class Constructors: Control Your Object Instantiation – Real Python https://realpython.com/python-class-constructor/#:~:text=Class%20constructors%20are%20a%20fu...

>>> from named_tuple import named_tuple_factory

>>> Point = named_tuple_factory("Point", "x", "y")

>>> point = Point(21, 42)


>>> point
Point(21, 42)
>>> point.x
21
>>> point.y
42
>>> point[0]
21
>>> point[1]
42

>>> point.x = 84
Traceback (most recent call last):
...
AttributeError: can't set attribute

>>> dir(point)
['__add__', '__class__', ..., 'count', 'index', 'x', 'y']

Point named_tuple_factory()

Point .x .y

AttributeError

dir() point

.__new__() .__init__()

.__new__() .__init__()

.__init__()

.__new__()

15 of 18 4/1/2022, 9:18 PM
Python Class Constructors: Control Your Object Instantiation – Real Python https://realpython.com/python-class-constructor/#:~:text=Class%20constructors%20are%20a%20fu...

16 of 18 4/1/2022, 9:18 PM
Python Class Constructors: Control Your Object Instantiation – Real Python https://realpython.com/python-class-constructor/#:~:text=Class%20constructors%20are%20a%20fu...

17 of 18 4/1/2022, 9:18 PM
Python Class Constructors: Control Your Object Instantiation – Real Python https://realpython.com/python-class-constructor/#:~:text=Class%20constructors%20are%20a%20fu...

⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅
⋅ ⋅ ⋅ ⋅ ⋅

18 of 18 4/1/2022, 9:18 PM

You might also like