-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #497 from realpython/duck-typing-python
Sample code for the Duck typing article
- Loading branch information
Showing
13 changed files
with
264 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# Duck Typing in Python: Writing Flexible and Decoupled Code | ||
|
||
This folder provides the code examples for the Real Python tutorial [Duck Typing in Python: Writing Flexible and Decoupled Code](https://realpython.com/duck-typing-python/). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
class Duck: | ||
def swim(self): | ||
print("The duck is swimming") | ||
|
||
def fly(self): | ||
print("The duck is flying") | ||
|
||
|
||
class Swan: | ||
def swim(self): | ||
print("The swan is swimming") | ||
|
||
def fly(self): | ||
print("The swan is flying") | ||
|
||
|
||
class Albatross: | ||
def swim(self): | ||
print("The albatross is swimming") | ||
|
||
def fly(self): | ||
print("The albatross is flying") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
class Duck: | ||
def fly(self): | ||
print("The duck is flying") | ||
|
||
def swim(self): | ||
print("The duck is swimming") | ||
|
||
|
||
class Pigeon: | ||
def fly(self): | ||
print("The pigeon is flying") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
name,age,job | ||
John,25,Engineer | ||
Jane,22,Designer |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
[ | ||
{ | ||
"name": "John", | ||
"age": 25, | ||
"job": "Engineer" | ||
}, | ||
{ | ||
"name": "Jane", | ||
"age": 22, | ||
"job": "Designer" | ||
} | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
John | ||
25 | ||
Engineer | ||
Jane | ||
22 | ||
Designer |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
numbers = [1, 2, 3] | ||
person = ("Jane", 25, "Python Dev") | ||
letters = "abc" | ||
ordinals = {"one": "first", "two": "second", "three": "third"} | ||
even_digits = {2, 4, 6, 8} | ||
collections = [numbers, person, letters, ordinals, even_digits] | ||
|
||
for collection in collections: | ||
for value in collection: | ||
print(value) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
from collections.abc import Collection | ||
|
||
|
||
def mean(grades: Collection) -> float: | ||
return sum(grades) / len(grades) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
from collections import deque | ||
|
||
|
||
class Queue: | ||
def __init__(self): | ||
self._elements = deque() | ||
|
||
def enqueue(self, element): | ||
self._elements.append(element) | ||
|
||
def dequeue(self): | ||
return self._elements.popleft() | ||
|
||
def __iter__(self): | ||
return iter(self._elements) | ||
|
||
def __len__(self): | ||
return len(self._elements) | ||
|
||
def __reversed__(self): | ||
return reversed(self._elements) | ||
|
||
def __contains__(self, element): | ||
return element in self._elements |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import csv | ||
import json | ||
from itertools import batched # Python >= 3.12 | ||
|
||
|
||
class TextReader: | ||
def __init__(self, filename): | ||
self.filename = filename | ||
|
||
def read(self): | ||
with open(self.filename, encoding="utf-8") as file: | ||
return [ | ||
{ | ||
"name": batch[0].strip(), | ||
"age": batch[1].strip(), | ||
"job": batch[2].strip(), | ||
} | ||
for batch in batched(file.readlines(), 3) | ||
] | ||
|
||
|
||
class CSVReader: | ||
def __init__(self, filename): | ||
self.filename = filename | ||
|
||
def read(self): | ||
with open(self.filename, encoding="utf-8", newline="") as file: | ||
return list(csv.DictReader(file)) | ||
|
||
|
||
class JSONReader: | ||
def __init__(self, filename): | ||
self.filename = filename | ||
|
||
def read(self): | ||
with open(self.filename, encoding="utf-8") as file: | ||
return json.load(file) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
from math import pi | ||
from typing import Protocol | ||
|
||
|
||
class Shape(Protocol): | ||
def area(self) -> float: | ||
... | ||
|
||
def perimeter(self) -> float: | ||
... | ||
|
||
|
||
class Circle: | ||
def __init__(self, radius: float) -> None: | ||
self.radius = radius | ||
|
||
def area(self) -> float: | ||
return pi * self.radius**2 | ||
|
||
def perimeter(self) -> float: | ||
return 2 * pi * self.radius | ||
|
||
|
||
class Square: | ||
def __init__(self, side: float) -> None: | ||
self.side = side | ||
|
||
def area(self) -> float: | ||
return self.side**2 | ||
|
||
def perimeter(self) -> float: | ||
return 4 * self.side | ||
|
||
|
||
class Rectangle: | ||
def __init__(self, length: float, width: float) -> None: | ||
self.length = length | ||
self.width = width | ||
|
||
def area(self) -> float: | ||
return self.length * self.width | ||
|
||
def perimeter(self) -> float: | ||
return 2 * (self.length + self.width) | ||
|
||
|
||
def describe_shape(shape: Shape) -> None: | ||
print(f"{type(shape).__name__}") | ||
print(f" Area: {shape.area():.2f}") | ||
print(f" Perimeter: {shape.perimeter():.2f}") | ||
|
||
|
||
circle = Circle(3) | ||
square = Square(5) | ||
rectangle = Rectangle(4, 5) | ||
|
||
describe_shape(circle) | ||
describe_shape(square) | ||
describe_shape(rectangle) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
from abc import ABC, abstractmethod | ||
|
||
|
||
class Vehicle(ABC): | ||
def __init__(self, make, model, color): | ||
self.make = make | ||
self.model = model | ||
self.color = color | ||
|
||
@abstractmethod | ||
def start(self): | ||
raise NotImplementedError("This method must be implemented") | ||
|
||
@abstractmethod | ||
def stop(self): | ||
raise NotImplementedError("This method must be implemented") | ||
|
||
@abstractmethod | ||
def drive(self): | ||
raise NotImplementedError("This method must be implemented") | ||
|
||
|
||
class Car(Vehicle): | ||
def start(self): | ||
print("The car is starting") | ||
|
||
def stop(self): | ||
print("The car is stopping") | ||
|
||
def drive(self): | ||
print("The car is driving") | ||
|
||
|
||
class Truck(Vehicle): | ||
def start(self): | ||
print("The truck is starting") | ||
|
||
def stop(self): | ||
print("The truck is stopping") | ||
|
||
def drive(self): | ||
print("The truck is driving") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
class Car: | ||
def __init__(self, make, model, color): | ||
self.make = make | ||
self.model = model | ||
self.color = color | ||
|
||
def start(self): | ||
print("The car is starting") | ||
|
||
def stop(self): | ||
print("The car is stopping") | ||
|
||
def drive(self): | ||
print("The car is driving") | ||
|
||
|
||
class Truck: | ||
def __init__(self, make, model, color): | ||
self.make = make | ||
self.model = model | ||
self.color = color | ||
|
||
def start(self): | ||
print("The truck is starting") | ||
|
||
def stop(self): | ||
print("The truck is stopping") | ||
|
||
def drive(self): | ||
print("The truck is driving") |