PythonPython · Chapterبەش 11 · Lectureوانە 11.4
Inheritance and Polymorphismبۆماوە و فرەشێوەیی
Build classes on other classes: a subclass with super().__init__, overriding and extending methods, isinstance() and issubclass(), polymorphism with one loop over many animals, duck typing, abstract base classes with abc.ABC and @abstractmethod, composition (has-a) versus inheritance (is-a), a short look at multiple inheritance and the MRO, a worked shapes program, a Python–Java table, common mistakes and exercises.
لەسەر تر دروست بکە: بە super().__init__، و فراوانکردنی ، isinstance() و issubclass()، بە یەک بەسەر زۆر ئاژەڵدا، ، بە abc.ABC و @abstractmethod، («هەیەتی») بەرامبەر («جۆرێکە لە»)، تێڕوانینێکی کورت لە لە چەند و MRO، تەواوی شێوەکان، خشتەیەکی –Java، هەڵە باوەکان و ڕاهێنان.
What you will learnچی فێر دەبیت
- Write a subclass that calls
super().__init__()and adds its own attributes. - Override and extend methods, and explain how Python finds the method to run.
- Use
isinstance()andissubclass()correctly, and know whytype() ==misses subclasses. - Use polymorphism and duck typing to handle many kinds of objects with one loop.
- Write an abstract base class with
abc.ABCand@abstractmethod, and choose between inheritance and composition.
- بنووسیت کە
super().__init__()بانگ بکات و خۆی زیاد بکات. - پێناسە بکەیتەوە و فراوانیان بکەیت و ڕوون بکەیتەوە چۆن ئەو دەدۆزێتەوە کە جێبەجێی دەکات.
isinstance()وissubclass()بە دروستی بەکار بهێنیت و بزانیت بۆچیtype() ==ناژمێرێت.- و بەکار بهێنیت بۆ مامەڵەکردن لەگەڵ زۆر جۆر بە یەک .
- بە
abc.ABCو@abstractmethodبنووسیت و لە نێوان و هەڵبژێریت.
Why inheritance?بۆچی بۆماوە؟
A village farm near Shaqlawa has a dog, a cat, sheep and a rooster. Every animal has a name and an age and can describe itself, and each one makes its own sound. As four separate classes, the same __init__ and describe() would be typed four times, and a bug fixed in one copy would stay in the others. Inheritance lets a new class take everything from an existing class and add or change only what is different.
کێڵگەیەکی گوندێک لە نزیک شەقڵاوە سەگێک، پشیلەیەک، چەند مەڕێک و کەڵەشێرێکی هەیە. هەموو ئاژەڵێک ناو و تەمەنی هەیە و دەتوانێت خۆی بناسێنێت و هەر یەکەیان دەنگی تایبەتی خۆی هەیە. وەک چوار جیا، هەمان __init__ و describe() چوار جار دەنووسرێن و ئەگەر لە کۆپییەکدا چاک بکرێت، لە ئەوانی تردا دەمێنێتەوە. ڕێگە بە نوێ دەدات هەموو شتێک لە هەبووەوە وەربگرێت و تەنیا ئەوەی جیاوازە زیاد بکات یان بیگۆڕێت.
The existing class is the superclass (also called the parent or base class); the new one is a subclass (child or derived class). Java does the same with extends (why inheritance).
(پێی دەڵێن کلاسی بنەڕەتیش)؛ نوێیەکە . Java هەمان کار بە extends دەکات (بۆچی بۆماوە).
A subclass: class Dog(Animal)کلاسێکی منداڵ: class Dog(Animal)
Write the superclass in brackets after the new class's name. Dog then gets every method of Animal, and it can add new ones, such as fetch(). Sheep adds nothing at all: pass is an empty body.
لە ناو کەوانە لە دوای ناوی بنووسە. ئەوسا Dog هەموو Animal وەردەگرێت و دەتوانێت نوێ زیاد بکات، وەک fetch(). Sheep هیچ شتێک زیاد ناکات: pass لاشەیەکی بەتاڵە.
class Animal:
def __init__(self, name, age):
self.name = name
self.age = age
def describe(self):
return f"{self.name}, {self.age} years old"
def speak(self):
return "..."
class Dog(Animal): # Dog is a subclass of Animal
def fetch(self): # something only a dog can do
return f"{self.name} brings the ball back"
class Sheep(Animal): # nothing new yet: everything is inherited
pass
sher = Dog("Sher", 4)
bafr = Sheep("Bafr", 2)
print(sher.describe())
print(bafr.describe())
print(sher.fetch())
print(bafr.fetch())Sher, 4 years old
Bafr, 2 years old
Sher brings the ball back
Traceback (most recent call last):
File "first_subclass.py", line 27, in <module>
print(bafr.fetch())
^^^^^^^^^^
AttributeError: 'Sheep' object has no attribute 'fetch'Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 13
Animal in brackets: Dog is a subclass of Animal.
Animal لە ناو کەوانەدا: Dog Animalـە.
- Lineدێڕی 24
describe()is not written in Dog: it is inherited.describe()لە Dogـدا نەنووسراوە: بە وەرگیراوە.- Lineدێڕی 27
Inheritance goes down, not sideways: a sheep is not a dog.
بەرەو خوارەوە دەچێت، نەک بەلادا: مەڕ سەگ نییە.
A subclass: class Dog(Animal)کلاسێکی منداڵ: class Dog(Animal)
The is-a testتاقیکردنەوەی «جۆرێکە لە»
Before you write class B(A), say the sentence "a B is an A". "A dog is an animal": yes. "A square is a rectangle": yes. "A farm is an animal": no, a farm has animals; that is composition, later in this lesson. If the sentence sounds wrong, inheritance is the wrong tool (the is-a test in Java).
پێش ئەوەی بنووسیت class B(A)، ئەم ڕستەیە بڵێ: «B جۆرێکە لە A». «سەگ جۆرێکە لە ئاژەڵ»: بەڵێ. «چوارگۆشە جۆرێکە لە لاکێشە»: بەڵێ. «کێڵگە جۆرێکە لە ئاژەڵ»: نەخێر، کێڵگە ئاژەڵی هەیە؛ ئەمە ، لە دواتری ئەم وانەیەدا. ئەگەر ڕستەکە هەڵە دەنگ بداتەوە، ئامرازی هەڵەیە (تاقیکردنەوەی «جۆرێکە لە» لە Java).
super().__init__(): build the superclass part firstsuper().__init__(): سەرەتا بەشی کلاسی باوک دروست بکە
A dog also has a breed. Give Dog its own __init__, but do not copy the lines that set name and age: call the superclass's __init__ with super().__init__(name, age), then add the new attribute. super() means "the superclass of this class", and you do not pass self to it.
سەگ نەژادیشی هەیە. __init__ـێکی تایبەت بدە Dog، بەڵام ئەو دێڕانە کۆپی مەکە کە name و age دادەنێن: بە super().__init__(name, age) بانگ بکە و پاشان نوێیەکە زیاد بکە. super() واتە « ئەم » و selfـی بۆ نانێریت.
class Animal:
def __init__(self, name, age):
print(" Animal.__init__ sets name and age")
self.name = name
self.age = age
def describe(self):
return f"{self.name}, {self.age} years old"
class Dog(Animal):
def __init__(self, name, age, breed):
print(" Dog.__init__ starts")
super().__init__(name, age) # build the Animal part first
self.breed = breed # then add what is new
print(" Dog.__init__ adds breed")
print("Creating a dog:")
sher = Dog("Sher", 4, "Pshdar")
print(sher.describe(), "-", sher.breed)
print(vars(sher))Creating a dog:
Dog.__init__ starts
Animal.__init__ sets name and age
Dog.__init__ adds breed
Sher, 4 years old - Pshdar
{'name': 'Sher', 'age': 4, 'breed': 'Pshdar'}Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 14
Build the Animal part first: no copied lines.
سەرەتا بەشی Animal دروست بکە: هیچ دێڕێکی کۆپیکراو نییە.
- Lineدێڕی 15
Then add what is new in Dog.
پاشان ئەوەی لە Dogـدا نوێیە زیاد بکە.
- Lineدێڕی 22
One object with all three attributes.
یەک بە هەر سێ .


super().__init__(): build the superclass part firstsuper().__init__(): سەرەتا بەشی کلاسی باوک دروست بکە
Common mistake: forgetting super().__init__()هەڵەی باو: لەبیرکردنی super().__init__()
Unlike Java (javac adds super()), Python does not call the superclass's __init__ for you. If a subclass has its own __init__ and forgets super().__init__(...), the object never gets the superclass's attributes. The error appears later, far from the cause:
بە پێچەوانەی Java (javac خۆی super() زیاد دەکات)، خۆی __init__ـی بانگ ناکات. ئەگەر __init__ـی خۆی هەبێت و super().__init__(...) لەبیر بکات، هەرگیز وەرناگرێت. هەڵەکە دواتر دەردەکەوێت، دوور لە هۆکارەکەی:
class Animal:
def __init__(self, name, age):
self.name = name
self.age = age
def describe(self):
return f"{self.name}, {self.age} years old"
class Dog(Animal):
def __init__(self, name, age, breed):
self.breed = breed # wrong: super().__init__() is missing
sher = Dog("Sher", 4, "Pshdar")
print(vars(sher))
print(sher.describe()){'breed': 'Pshdar'}
Traceback (most recent call last):
File "forgot_super.py", line 17, in <module>
print(sher.describe())
~~~~~~~~~~~~~^^
File "forgot_super.py", line 7, in describe
return f"{self.name}, {self.age} years old"
^^^^^^^^^
AttributeError: 'Dog' object has no attribute 'name'Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 12
Only breed is set: name and age never are.
تەنیا breed دادەنرێت: name و age هەرگیز دانانرێن.
- Lineدێڕی 16
vars()proves it: the object has only one attribute.vars()دەیسەلمێنێت: تەنیا یەک هەیە.
Overriding a methodپێناسەکردنەوەی میتۆد
A subclass can write its own version of an inherited method, with the same name: this is overriding. When you call a method, Python looks first in the object's own class, then in its superclass, then further up, and runs the first one it finds. Python needs no keyword for this; Java marks it with @Override (overriding in Java).
دەتوانێت وەشانی خۆی بۆ بۆماوەگیراو بنووسێت، بە هەمان ناو: ئەمە . کاتێک بانگ دەکەیت، سەرەتا لە خودی دەگەڕێت، پاشان لە ، پاشان سەرتر و یەکەم دانە کە دەیدۆزێتەوە جێبەجێی دەکات. بۆ ئەمە پێویستی بە هیچ نییە؛ Java بە @Override نیشانەی دەکات (پێناسەکردنەوەی میتۆد لە Java).
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
return "..."
def greet(self):
return f"{self.name} says {self.speak()}"
class Dog(Animal):
def speak(self): # overrides Animal.speak
return "Woof!"
class Cat(Animal):
def speak(self):
return "Meow!"
class Fish(Animal): # no speak(): Animal's version is used
pass
for animal in (Dog("Sher"), Cat("Pishi"), Fish("Nemo")):
print(animal.greet())Sher says Woof! Pishi says Meow! Nemo says ...
Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 9
Written once in Animal, but
self.speak()runs the real object's version.یەک جار لە Animalـدا نووسراوە، بەڵام
self.speak()وەشانەکەی ڕاستەقینەکە جێبەجێ دەکات.- Lineدێڕی 13
Same name as in Animal: this replaces it for dogs.
هەمان ناوی ناو Animal: بۆ سەگەکان جێگەی دەگرێتەوە.
- Lineدێڕی 22
No speak() here, so Python climbs up to Animal's.
speak() لێرە نییە، بۆیە سەردەکەوێت بۆ هی Animal.
Overriding a methodپێناسەکردنەوەی میتۆد
Extending a method with super()فراوانکردنی میتۆدێک بە super()
Overriding does not have to throw the old version away. Inside the new describe(), super().describe() runs the superclass's version, and the subclass adds to its result. The shared part stays in one place.
پێویست ناکات وەشانە کۆنەکە فڕێ بدات. لە ناو describe()ـی نوێدا، super().describe() وەشانەکەی جێبەجێ دەکات و شتێک بۆ ئەنجامەکەی زیاد دەکات. بەشە هاوبەشەکە لە یەک شوێندا دەمێنێتەوە.
class Animal:
def __init__(self, name, age):
self.name = name
self.age = age
def describe(self):
return f"{self.name}, {self.age} years old"
class Dog(Animal):
def __init__(self, name, age, breed):
super().__init__(name, age)
self.breed = breed
def describe(self):
text = super().describe() # the old version does the first part
return f"{text}, a {self.breed} dog"
print(Animal("Bafr", 2).describe())
print(Dog("Sher", 4, "Pshdar").describe())Bafr, 2 years old Sher, 4 years old, a Pshdar dog
Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 16
The old version does the first part.
وەشانە کۆنەکە بەشی یەکەم دەکات.
isinstance() and issubclass()isinstance() و issubclass()
isinstance(obj, C) asks: is this object a C, or an object of a subclass of C? issubclass(A, B) asks the same about two classes. Every class comes from object, which stands at the top of every family tree. type(obj) gives only the exact class, so use isinstance() when subclasses should count too (type() and isinstance(), instanceof in Java).
isinstance(obj, C) دەپرسێت: ئایا ئەم Cـە، یان Cـە؟ issubclass(A, B) هەمان پرسیار لەبارەی دوو دەکات. هەموو لە objectـەوە دێت، کە لە سەرووی هەموو دارێکی خێزانییەوەیە. type(obj) تەنیا دەدات، بۆیە کاتێک دەتەوێت بژمێردرێن isinstance() بەکار بهێنە (type() و isinstance()، instanceof لە Java).
class Animal:
pass
class Dog(Animal):
pass
class Cat(Animal):
pass
sher = Dog()
print(isinstance(sher, Dog)) # True
print(isinstance(sher, Animal)) # True: a Dog is an Animal
print(isinstance(sher, Cat)) # False
print(type(sher) == Animal) # False: type() gives the exact class
print(issubclass(Dog, Animal)) # True
print(issubclass(Animal, Dog)) # False: not every animal is a dog
print(issubclass(Dog, object)) # True: every class comes from object
print(isinstance(3.5, (int, float))) # True: one of the two
print(issubclass(bool, int)) # True: Python's own exampleTrue True False False True False True True True
Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 17
type()sees only Dog, not its superclasses.type()تەنیا Dog دەبینێت، نەک .- Lineدێڕی 21
A tuple of classes means "any of these".
لە واتە «هەر یەکێک لەمانە».
- Lineدێڕی 22
Python's own example:
TrueandFalseare a kind ofint.نموونەی خودی :
TrueوFalseجۆرێکن لەint.
Polymorphism: one loop, many animalsفرەشێوەیی: یەک خول، زۆر ئاژەڵ
Put different objects in one list and call the same method on each. Every object runs its own version, and the loop neither knows nor cares which kind of animal it holds. This is polymorphism ("many forms"): one line of code, many behaviours (polymorphism in Java).
چەند جیاواز بخە ناو یەک و هەمان بۆ هەر یەکێکیان بانگ بکە. هەر وەشانی خۆی جێبەجێ دەکات و نە دەزانێت و نە گرنگە بۆی چ جۆرە ئاژەڵێک لە دەستدایە. ئەمە («زۆر شێوە»): یەک دێڕ کۆد، زۆر ڕەفتار (فرەشێوەیی لە Java).
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
return "..."
class Dog(Animal):
def speak(self):
return "Woof!"
class Cat(Animal):
def speak(self):
return "Meow!"
class Sheep(Animal):
def speak(self):
return "Baa!"
class Rooster(Animal):
def speak(self):
return "Cock-a-doodle-doo!"
farm = [Dog("Sher"), Cat("Pishi"), Sheep("Bafr"), Rooster("Kalo"), Animal("?")]
for animal in farm: # one loop ...
print(f"{animal.name:>6}: {animal.speak()}") # ... and each runs its own speak() Sher: Woof!
Pishi: Meow!
Bafr: Baa!
Kalo: Cock-a-doodle-doo!
?: ...Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 29
Five objects of five different classes in one list.
پێنج لە پێنج جیاواز لە یەک .
- Lineدێڕی 31
The same line runs a different method for each object.
هەمان دێڕ بۆ هەر جیاواز جێبەجێ دەکات.


Tomorrow a goat joins the farm: write class Goat(Animal) with its own speak(), put it in the list, and the loop works without a single change.
سبەی بزنێک دێتە کێڵگەکە: class Goat(Animal) بە speak()ـی خۆیەوە بنووسە، بیخە ناو و بەبێ تاکە گۆڕانێک کار دەکات.
Duck typing: if it quacks like a duckجۆرداریی مراوی: ئەگەر وەک مراوی دەنگ بکات
Python does not even need a shared superclass. When it runs thing.speak(), it asks only one question: does this object have a speak() method? A Robot or a Radio that has one works in the same function. The name comes from the saying "if it walks like a duck and quacks like a duck, it is a duck". This is duck typing. Duck typing also lets you hand a class any helper that has the right methods: see Dependency Injection.
تەنانەت پێویستی بە هاوبەش نییە. کاتێک thing.speak() جێبەجێ دەکات، تەنیا یەک پرسیار دەکات: ئایا ئەم speak()ـی هەیە؟ Robot یان Radioـیەک کە ئەم هەبێت لە هەمان کار دەکات. ناوەکە لە پەندێکەوە هاتووە: «ئەگەر وەک مراوی بڕوات و وەک مراوی دەنگ بکات، مراوییە». ئەمە . ڕێگەش دەدات هەر یاریدەدەرێک کە دروستی هەبێت بدەیتە : بڕوانە تێخستنی وابەستەیی.
class Dog:
def speak(self):
return "Woof!"
class Robot: # not an animal at all
def speak(self):
return "Beep, I am a robot."
class Radio:
def speak(self):
return "Good morning, Erbil!"
class Tractor: # no speak() method
pass
def make_it_speak(thing):
print(thing.speak()) # Python only asks: does it have speak()?
for thing in (Dog(), Robot(), Radio(), Tractor()):
make_it_speak(thing)Woof!
Beep, I am a robot.
Good morning, Erbil!
Traceback (most recent call last):
File "duck_typing.py", line 25, in <module>
make_it_speak(thing)
~~~~~~~~~~~~~^^^^^^^
File "duck_typing.py", line 21, in make_it_speak
print(thing.speak()) # Python only asks: does it have speak()?
^^^^^^^^^^^
AttributeError: 'Tractor' object has no attribute 'speak'Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 6
Not an Animal, and no shared superclass apart from
object.Animal نییە و جگە لە
objectهیچ هاوبەشی نییە.- Lineدێڕی 21
The only question: is there a
speak()?تاکە پرسیار: ئایا
speak()هەیە؟
You have used duck typing all along: len() works on a string, a list, a dictionary and a range, and on your own class too if it has a __len__() method:
هەمیشە بەکار هێناوە: len() لەسەر ، ، و range کار دەکات و لەسەر خۆشت ئەگەر __len__()ـی هەبێت:
for thing in ("Hawler", [4, 8, 15], {"tea": 3, "sugar": 2}, range(10)):
print(type(thing).__name__, len(thing))
class Queue: # our own class can join in
def __init__(self):
self._people = ["Aram", "Hana", "Soran"]
def __len__(self): # len() looks for this method
return len(self._people)
print("Queue", len(Queue()))str 6 list 3 dict 2 range 10 Queue 3
Duck typing: if it quacks like a duckجۆرداریی مراوی: ئەگەر وەک مراوی دەنگ بکات
Ask first, or just try?سەرەتا بپرسە، یان ڕاستەوخۆ تاقی بکەرەوە؟
When an object might not have the method, there are two styles. Try it and catch the AttributeError: Python's documentation calls this EAFP, "easier to ask for forgiveness than permission". Or ask first with hasattr(): LBYL, "look before you leap". Python code usually prefers trying (check first, or just try?).
کاتێک دەکرێت ئەو نەبێت، دوو شێواز هەیە. تاقی بکەرەوە و AttributeError بگرە: بەمە دەڵێن EAFP، واتە «داوای لێبووردن ئاسانترە لە داوای مۆڵەت». یان سەرەتا بپرسە بە hasattr(): LBYL، واتە «پێش بازدان سەیر بکە». کۆدی زۆرجار تاقیکردنەوەی پێ باشترە (سەرەتا بپشکنە، یان ڕاستەوخۆ تاقی بکەرەوە؟).
class Robot:
def speak(self):
return "Beep!"
class Tractor:
pass
for thing in (Robot(), Tractor()):
try: # try it, and catch the mistake
print(thing.speak())
except AttributeError:
print(type(thing).__name__, "cannot speak")
for thing in (Robot(), Tractor()):
if hasattr(thing, "speak"): # or look before you leap
print(thing.speak())
else:
print(type(thing).__name__, "cannot speak")Beep! Tractor cannot speak Beep! Tractor cannot speak
Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 11-13
EAFP: just call it, and catch the error.
EAFP: ڕاستەوخۆ بانگی بکە و هەڵەکە بگرە.
- Lineدێڕی 17
LBYL: check first with
hasattr().LBYL: سەرەتا بە
hasattr()بپشکنە.
Abstract base classes: ABC and @abstractmethodکلاسە ڕووتەکان: ABC و @abstractmethod
Duck typing trusts objects to have the right methods. Sometimes you want Python to check instead: every shape must have area() and perimeter(). An abstract base class (ABC) says so. Inherit from ABC (from the module abc) and mark each required method with the decorator @abstractmethod. Such a class is only a plan: Python will not create an object from it.
متمانە بە دەکات کە دروستیان هەبێت. هەندێک جار دەتەوێت لەبری ئەوە بپشکنێت: هەموو شێوەیەک دەبێت area() و perimeter()ـی هەبێت. (ABC) ئەمە دەڵێت. لە ABC (لە abc) وەربگرە و هەر پێویست بە @abstractmethod نیشانە بکە. ئەم جۆرە تەنیا نەخشەیەکە: لێ دروست ناکات.
from abc import ABC, abstractmethod
class Shape(ABC): # an abstract base class
@abstractmethod
def area(self):
"""Every shape must say how to work out its area."""
@abstractmethod
def perimeter(self):
"""... and its perimeter."""
def describe(self): # a normal method: written once, for all
return (f"{type(self).__name__}: area {self.area():.2f}, "
f"perimeter {self.perimeter():.2f}")
class Rectangle(Shape):
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width * self.height
def perimeter(self):
return 2 * (self.width + self.height)
print(Rectangle(4, 2.5).describe())
s = Shape()Rectangle: area 10.00, perimeter 13.00
Traceback (most recent call last):
File "abstract_shape.py", line 31, in <module>
s = Shape()
TypeError: Can't instantiate abstract class Shape without an implementation for abstract methods 'area', 'perimeter'Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 5-7
An abstract method needs no body: a docstring (or
...) is enough.پێویستی بە لاشە نییە: (یان
...) بەسە.- Lineدێڕی 13
A normal method, inherited by every shape; it may call the abstract ones.
ئاسایی کە هەموو شێوەیەک وەریدەگرێت؛ دەتوانێت بانگ بکات.
- Lineدێڕی 31
The plan itself cannot become an object.
خودی نەخشەکە ناتوانێت ببێتە .
Java builds the same idea with the abstract keyword (abstract classes in Java). In Python an ABC is just a class that inherits from ABC.
Java هەمان بیرۆکە بە abstract دروست دەکات (کلاسە ڕووتەکان لە Java). لە ABC تەنیا کە لە ABCـەوە وەردەگرێت.
Abstract base classes: ABC and @abstractmethodکلاسە ڕووتەکان: ABC و @abstractmethod
A subclass that forgets oneکلاسێکی منداڵ کە یەکێکیان لەبیر دەکات
If a subclass writes only some of the abstract methods, it is still abstract. Python refuses to create the object at once, and the message names exactly what is missing:
ئەگەر تەنیا هەندێک لە بنووسێت، هێشتا ڕووتە. یەکسەر دروستکردنی ڕەت دەکاتەوە و پەیامەکە ڕێک ناوی ئەوە دەهێنێت کە کەمە:
from abc import ABC, abstractmethod
import math
class Shape(ABC):
@abstractmethod
def area(self): ...
@abstractmethod
def perimeter(self): ...
class Circle(Shape):
def __init__(self, radius):
self.radius = radius
def area(self):
return math.pi * self.radius ** 2
# perimeter() is forgotten
c = Circle(3)Traceback (most recent call last):
File "missing_method.py", line 22, in <module>
c = Circle(3)
TypeError: Can't instantiate abstract class Circle without an implementation for abstract method 'perimeter'This is the gain over duck typing: the mistake shows up when the object is made, not hours later when somebody finally asks a circle for its perimeter. These messages are Python 3.13's; versions before 3.12 say "with abstract methods" instead.
ئەمە سوودەکەیەتی بەراورد بە : هەڵەکە کاتی دروستکردنی دەردەکەوێت، نەک چەند کاتژمێر دواتر کاتێک یەکێک لە کۆتاییدا داوای چێوەی بازنەکە دەکات. ئەم پەیامانە هی 3.13ـن؛ وەشانەکانی پێش 3.12 لەبری ئەوە دەڵێن "with abstract methods".
Worked program: rugs of every shapeبەرنامەیەکی تەواو: بەڕە بە هەموو شێوەیەک
Dilan sells handmade rugs in the Erbil bazaar: rectangular, round, square and triangular. For the price she needs each rug's area in m², and for the fringe its edge length. One abstract Shape, four subclasses, and one loop. Each constructor also refuses impossible sizes with ValueError, as in Encapsulation and Properties.
دیلان لە بازاڕی هەولێر بەڕەی دەستکرد دەفرۆشێت: لاکێشەیی، خڕ، چوارگۆشە و سێگۆشە. بۆ نرخەکە پێویستی بە ڕووبەری هەر بەڕەیەک هەیە بە m². بۆ ڕیشاڵەکەش پێویستی بە درێژیی لێوارەکەی هەیە. یەک Shapeـی ڕووت، چوار و یەک . هەر قەبارەی مەحاڵیش بە ValueError ڕەت دەکاتەوە، وەک لە کەپسوولکردن و خەسڵەتە بەڕێوەبراوەکان.
from abc import ABC, abstractmethod
import math
class Shape(ABC):
@abstractmethod
def area(self): ...
@abstractmethod
def perimeter(self): ...
def __str__(self):
return f"{type(self).__name__:<10}{self.area():>8.2f}{self.perimeter():>8.2f}"
class Circle(Shape):
def __init__(self, radius):
if radius <= 0:
raise ValueError("the radius must be more than 0")
self.radius = radius
def area(self):
return math.pi * self.radius ** 2
def perimeter(self):
return 2 * math.pi * self.radius
class Rectangle(Shape):
def __init__(self, width, height):
if width <= 0 or height <= 0:
raise ValueError("the sides must be more than 0")
self.width = width
self.height = height
def area(self):
return self.width * self.height
def perimeter(self):
return 2 * (self.width + self.height)
class Square(Rectangle): # a square is a rectangle ...
def __init__(self, side):
super().__init__(side, side) # ... with equal sides
class Triangle(Shape):
def __init__(self, a, b, c):
if a + b <= c or a + c <= b or b + c <= a:
raise ValueError(f"{a}, {b} and {c} cannot make a triangle")
self.a, self.b, self.c = a, b, c
def area(self): # Heron's formula
s = self.perimeter() / 2
return math.sqrt(s * (s - self.a) * (s - self.b) * (s - self.c))
def perimeter(self):
return self.a + self.b + self.c
rugs = [Rectangle(3, 2), Circle(1.5), Square(2), Triangle(3, 4, 5)]
print(f"{'shape':<10}{'area':>8}{'edge':>8}")
for rug in rugs:
print(rug)
print(f"total area: {sum(r.area() for r in rugs):.2f} m²")
biggest = max(rugs, key=lambda r: r.area())
print("biggest:", type(biggest).__name__)
print(isinstance(rugs[2], Rectangle), isinstance(rugs[2], Shape))
try:
Triangle(1, 2, 8)
except ValueError as error:
print("Refused:", error)shape area edge Rectangle 6.00 10.00 Circle 7.07 9.42 Square 4.00 8.00 Triangle 6.00 12.00 total area: 23.07 m² biggest: Circle True True Refused: 1, 2 and 8 cannot make a triangle
Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 12
Written once: every shape prints itself with its own area and perimeter.
یەک جار نووسراوە: هەموو شێوەیەک بە ڕووبەر و چێوەی خۆیەوە خۆی چاپ دەکات.
- Lineدێڕی 43-45
A square is a rectangle whose two sides are equal.
چوارگۆشە لاکێشەیەکە کە دوو لاکەی یەکسانن.
- Lineدێڕی 50
Each side must be shorter than the other two together.
هەر لایەک دەبێت لە کۆی دوو لاکەی تر کورتتر بێت.
- Lineدێڕی 68
max()works because every shape hasarea().max()کار دەکات چونکە هەموو شێوەیەکarea()ـی هەیە.
Check the numbers: the circle is m², the 3-4-5 triangle has area 6 by Heron's formula with , and the total is 23.07 m². Square(2) is both a Rectangle and a Shape, and the impossible triangle 1, 2, 8 is refused.
ژمارەکان بپشکنە: بازنەکە m²ـە، ڕووبەری سێگۆشەی 3-4-5 بە هاوکێشەی هیرۆن و دەبێتە 6 و کۆی گشتی 23.07 m²ـە. Square(2) هەم Rectangleـە و هەم Shape و سێگۆشە مەحاڵەکەی 1، 2، 8 ڕەت دەکرێتەوە.
Composition: has-a instead of is-aئاوێتەکردنی ئۆبجێکت: «هەیەتی» لەبری «جۆرێکە لە»
Inheritance is not the only way to reuse code. A farm is not an animal, but it has animals. So Farm keeps a list of animal objects in an attribute and asks each one to work. Building an object out of other objects is composition. The farm even uses polymorphism: it calls speak() and every animal answers in its own way.
تاکە ڕێگای دووپاتە بەکارهێنانەوەی کۆد نییە. کێڵگە ئاژەڵ نییە، بەڵام ئاژەڵی هەیە. بۆیە Farm لە ئاژەڵ لە هەڵدەگرێت و داوا لە هەر یەکێکیان دەکات کار بکات. دروستکردنی لە تر . کێڵگەکە تەنانەت بەکار دەهێنێت: speak() بانگ دەکات و هەر ئاژەڵێک بە شێوەی خۆی وەڵام دەداتەوە.
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
return "..."
class Dog(Animal): # is-a: a dog IS an animal
def speak(self):
return "Woof!"
class Sheep(Animal):
def speak(self):
return "Baa!"
class Farm: # has-a: a farm HAS animals
def __init__(self, village):
self.village = village
self._animals = [] # the farm keeps its animals in a list
def add(self, animal):
self._animals.append(animal)
def morning(self):
print(f"Morning in {self.village}:")
for animal in self._animals: # the farm asks each animal to work
print(" ", animal.name, animal.speak())
def __len__(self):
return len(self._animals)
farm = Farm("Shaqlawa")
farm.add(Dog("Sher"))
farm.add(Sheep("Bafr"))
farm.add(Sheep("Bawr"))
farm.morning()
print(len(farm), "animals")
print(isinstance(farm, Animal)) # False: a farm is not an animalMorning in Shaqlawa: Sher Woof! Bafr Baa! Bawr Baa! 3 animals False
Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 19
No superclass: a farm is not an animal.
هیچ نییە: کێڵگە ئاژەڵ نییە.
- Lineدێڕی 22
The has-a link: the animals live in an attribute.
بەستەری «هەیەتی»: ئاژەڵەکان لە دەژین.
- Lineدێڕی 42
Composition creates no is-a link.
هیچ پەیوەندییەکی «جۆرێکە لە» دروست ناکات.
Composition: has-a instead of is-aئاوێتەکردنی ئۆبجێکت: «هەیەتی» لەبری «جۆرێکە لە»
Parts you can swapپارچەی گۆڕاو
Composition has one more strength: the parts can change while the program runs. A phone has a battery object and hands work to it. Put in a new battery and the phone keeps working. With inheritance the parent is fixed the moment the class is written. Passing such a part in from outside, for example through __init__, is called dependency injection: see Dependency Injection.
هێزێکی تریشی هەیە: پارچەکان لە کاتی کارکردنی دەگۆڕدرێن. مۆبایل پاتری هەیە و کار دەداتە دەست ئەو. پاترییەکی نوێی تێ بخە و مۆبایلەکە هەر کار دەکات. لە لەو ساتەوە جێگیرە کە دەنووسرێت. دانی پارچەیەکی لەم جۆرە لە دەرەوە، بۆ نموونە لە ڕێی __init__ـەوە، پێی دەوترێت : بڕوانە تێخستنی وابەستەیی.
class Battery:
def __init__(self, capacity_mah):
self.capacity_mah = capacity_mah
self.percent = 100
def use(self, percent):
self.percent = max(0, self.percent - percent)
class Phone:
def __init__(self, model, battery):
self.model = model
self.battery = battery # the phone HAS a battery object
def watch_video(self, minutes):
self.battery.use(minutes // 6) # the phone hands the work to its battery
return f"{self.model}: {self.battery.percent}% left"
phone = Phone("Lana's phone", Battery(5000))
print(phone.watch_video(60))
phone.battery = Battery(6000) # swap the part: a new, full battery
print(phone.watch_video(30), phone.battery.capacity_mah, "mAh")Lana's phone: 90% left Lana's phone: 95% left 6000 mAh
Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 16
The phone does not know how a battery works: it asks it (delegation).
مۆبایلەکە نازانێت پاتری چۆن کار دەکات: داوای لێ دەکات.
- Lineدێڕی 22
Swap the part: a new, full 6000 mAh battery.
پارچەکە بگۆڕە: پاترییەکی نوێ و پڕی 6000 mAh.
Extra: multiple inheritance and the MROزیادە: بۆماوە لە چەند کلاسێکی باوکەوە و ڕیزبەندیی گەڕانی میتۆد
Python and Java side by sidePython و Java لە تەنیشت یەکتر
If you have studied the Java track, this table connects the two languages. If not, it is a preview of how the same ideas look elsewhere.
ئەگەر ڕێڕەوی Javaـت خوێندبێت، ئەم خشتەیە دوو زمانەکە بە یەکەوە دەبەستێتەوە. ئەگەر نا، نموونەیەکە بۆ ئەوەی هەمان بیرۆکەکان لە زمانێکی تردا چۆن دەردەکەون.
| Ideaبیرۆکە | Python | Java |
|---|---|---|
| Subclass | class Dog(Animal): | class Dog extends Animal |
| Superclass constructor | super().__init__(name), never automaticsuper().__init__(name)، هەرگیز خۆکار نییە | super(name); first; super() added if missingsuper(name); یەکەم دێڕ؛ ئەگەر نەبێت super() زیاد دەکرێت |
| Overriding | Same name; @override (3.12+) only for checkersهەمان ناو؛ @override (3.12+) تەنیا بۆ پشکنەرەکان | Same signature; @Overrideهەمان واژوو؛ @Override |
| Type checkپشکنینی جۆر | isinstance(x, Dog) | x instanceof Dog |
| Abstract class | class Shape(ABC) + @abstractmethod | abstract class Shape |
| A required set of methodsکۆمەڵێک پێویست | An ABC, or simply duck typingABC، یان تەنیا | interface |
| Several superclassesچەند | Allowed, ordered by the MROڕێگە پێدراوە، بە MRO ڕیز دەکرێن | Not allowed; several interfaces insteadڕێگە پێنەدراوە؛ لەبری ئەوە چەند |
| Hidden data شاراوە | _name by convention, __name mangled_name بە ڕێککەوتن، __name شێوێنراو | private |
Java lessons: inheritance and polymorphism, abstraction, interfaces and enums, the two languages compared.
وانەکانی Java: بۆماوە و فرەشێوەیی، ڕووتکردنەوە، نێوبەستەکان و enum، بەراوردی دوو زمانەکە.
Common mistakesهەڵە باوەکان
A typo in an override is silent. def speek(self) does not override anything: it adds a new method, and Animal's speak() keeps running. Since Python 3.12 you can write @override (from typing, PEP 698) above a method you mean to override. At run time it only leaves a mark; type checkers such as mypy and Pyright read that mark and report an @override method that overrides nothing.
هەڵەی نووسین لە بێدەنگە. def speek(self) هیچ شتێک پێناسە ناکاتەوە: نوێ زیاد دەکات و speak()ـی Animal هەر جێبەجێ دەبێت. لە 3.12ـەوە دەتوانیت لە سەرووی ئەو مەبەستتە پێناسەی بکەیتەوە بنووسیت @override (لە typing، PEP 698). لە کاتی جێبەجێکردندا تەنیا نیشانەیەک دادەنێت؛ پشکنەرەکانی جۆر وەک mypy و Pyright ئەو نیشانەیە دەخوێننەوە و ئاگادار دەکەنەوە ئەگەر @override هیچ شتێک پێناسە نەکاتەوە.
from typing import override # Python 3.12 and later
class Animal:
def speak(self):
return "..."
class Dog(Animal):
def speek(self): # typo: this is a NEW method
return "Woof!"
class Cat(Animal):
@override # "I mean to override a method"
def speak(self):
return "Meow!"
print(Dog().speak()) # Animal's version runs: no error!
print(Cat().speak())
print(Cat.speak.__override__) # @override only leaves this mark... Meow! True
Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 10
One wrong letter: Dog now has two methods,
speak()(inherited) andspeek().یەک پیتی هەڵە: ئێستا Dog دوو هەیە،
speak()(بۆماوەگیراو) وspeek().- Lineدێڕی 22
@overridechanges nothing at run time; the checking is done by a type checker.@overrideلە کاتی جێبەجێکردندا هیچ ناگۆڕێت؛ پشکنینەکە پشکنەرێکی جۆر دەیکات.
| Mistakeهەڵە | What happensچی ڕوو دەدات | Fixچارەسەر |
|---|---|---|
Forgetting super().__init__(...)لەبیرکردنی super().__init__(...) | AttributeError: 'Dog' object has no attribute 'name' | Call it first in the subclass's __init__لە __init__ـی یەکەم بانگی بکە |
type(x) == Dog to test for dogstype(x) == Dog بۆ ناسینەوەی سەگ | A Puppy(Dog) is not counted: "not a dog?"Puppy(Dog) ناژمێردرێت: "not a dog?" | Use isinstance(x, Dog)isinstance(x, Dog) بەکار بهێنە |
Creating the abstract class itself: Shape()دروستکردنی خودی : Shape() | TypeError: Can't instantiate abstract class Shape ... | Create a concrete subclass, such as Rectangle(4, 2.5) تەواو دروست بکە، وەک Rectangle(4, 2.5) |
Inheriting for a has-a link: class Farm(Animal) بۆ پەیوەندیی «هەیەتی»: class Farm(Animal) | A farm gets speak() and age, which make no senseکێڵگە speak() و age وەردەگرێت، کە هیچ واتایەکیان نییە | Use composition: self._animals = [] بەکار بهێنە: self._animals = [] |
An override with different parameters: def speak(self, loud) بە جیاواز: def speak(self, loud) | The shared loop animal.speak() fails with TypeError for that class animal.speak() بۆ ئەو بە TypeError سەرناکەوێت | Keep the same parameters (or give the new one a default value)هەمان بهێڵەوە (یان بنەڕەتی بدە نوێیەکە) |
The type() row is real output of type_check.py: not a dog? | a dog. All error messages are Python 3.13's.
ڕیزی type() ڕاستەقینەی type_check.pyـە: not a dog? | a dog. هەموو پەیامەکانی هەڵە هی 3.13ـن.
Exercisesڕاهێنانەکان
Write Drink(name, price) with describe(). Tea(Drink) takes the number of sugar spoons, always costs 500 IQD and extends describe() with super(). Juice(Drink) takes a fruit and a price. Print a menu with one loop.
Drink(name, price) بە describe()ـەوە بنووسە. Tea(Drink) ژمارەی کەوچکی شەکر وەردەگرێت، هەمیشە 500 دینارە و بە super() describe() فراوان دەکات. Juice(Drink) میوەیەک و نرخێک وەردەگرێت. بە یەک لیستی خواردنەوەکان چاپ بکە.
Hintئاماژە
In Tea.__init__, call super().__init__("tea", 500) first.
لە Tea.__init__ـدا سەرەتا super().__init__("tea", 500) بانگ بکە.
Show answerوەڵامەکە پیشان بدە
class Drink:
def __init__(self, name, price):
self.name = name
self.price = price
def describe(self):
return f"{self.name}: {self.price} IQD"
class Tea(Drink):
def __init__(self, sugar):
super().__init__("tea", 500)
self.sugar = sugar
def describe(self):
return super().describe() + f", {self.sugar} spoons of sugar"
class Juice(Drink):
def __init__(self, fruit, price):
super().__init__(f"{fruit} juice", price)
menu = [Tea(2), Juice("pomegranate", 2_000), Drink("water", 250)]
for drink in menu:
print(drink.describe())tea: 500 IQD, 2 spoons of sugar pomegranate juice: 2000 IQD water: 250 IQD
What does this program print? Work it out on paper first.
ئەم چی چاپ دەکات؟ سەرەتا لەسەر کاغەز کاری لەسەر بکە.
class A:
def who(self):
return "A"
def show(self):
return "I am " + self.who()
class B(A):
def who(self):
return "B"
class C(B):
def show(self):
return super().show() + "!"
for obj in (A(), B(), C()):
print(obj.show())Show answerوەڵامەکە پیشان بدە
I am A I am B I am B!
show() is written in A, but self.who() runs the object's own version: B for B and for C (C inherits B's who()). C overrides show() and adds "!" to the result of super().show().
show() لە Aـدا نووسراوە، بەڵام self.who() وەشانەکەی خودی جێبەجێ دەکات: B بۆ B و بۆ C (C who()ـی B وەردەگرێت). C show() پێناسە دەکاتەوە و "!" بۆ ئەنجامی super().show() زیاد دەکات.
Write an abstract class Employee with an abstract method monthly_pay() and a __str__() that uses it. Add Salaried(name, salary) and Hourly(name, hours, rate). Print the staff and the total with one loop.
بە ناوی Employee بنووسە بە monthly_pay() و __str__()ـێک کە بەکاری دەهێنێت. Salaried(name, salary) و Hourly(name, hours, rate) زیاد بکە. بە یەک کارمەندەکان و کۆی گشتی چاپ بکە.
Show answerوەڵامەکە پیشان بدە
from abc import ABC, abstractmethod
class Employee(ABC):
def __init__(self, name):
self.name = name
@abstractmethod
def monthly_pay(self): ...
def __str__(self):
return f"{self.name:<7}{self.monthly_pay():>10,} IQD"
class Salaried(Employee):
def __init__(self, name, salary):
super().__init__(name)
self.salary = salary
def monthly_pay(self):
return self.salary
class Hourly(Employee):
def __init__(self, name, hours, rate):
super().__init__(name)
self.hours = hours
self.rate = rate
def monthly_pay(self):
return self.hours * self.rate
staff = [Salaried("Shilan", 900_000), Hourly("Rebin", 80, 7_500), Salaried("Karwan", 750_000)]
for person in staff:
print(person)
print("total:", f"{sum(p.monthly_pay() for p in staff):,}")Shilan 900,000 IQD Rebin 600,000 IQD Karwan 750,000 IQD total: 2,250,000
Add RegularHexagon(side) to the shapes program: area , perimeter . Check it with side 2.
RegularHexagon(side) بۆ شێوەکان زیاد بکە: ڕووبەر ، چێوە . بە لای 2 تاقی بکەرەوە.
Show answerوەڵامەکە پیشان بدە
from abc import ABC, abstractmethod
import math
class Shape(ABC):
@abstractmethod
def area(self): ...
@abstractmethod
def perimeter(self): ...
class RegularHexagon(Shape):
def __init__(self, side):
self.side = side
def area(self):
return 3 * math.sqrt(3) / 2 * self.side ** 2
def perimeter(self):
return 6 * self.side
h = RegularHexagon(2)
print(f"area {h.area():.2f}, perimeter {h.perimeter()}")area 10.39, perimeter 12
, and .
و .
Write show_all(things), which prints thing.describe() for every item and skips, with a message, any item that has no describe(). Test it with a Kettle, a Samovar and the number 42.
show_all(things) بنووسە کە بۆ هەر شتێک thing.describe() چاپ بکات و هەر شتێک کە describe()ـی نەبێت بە پەیامێکەوە تێپەڕێنێت. بە Kettle، Samovar و ژمارە 42 تاقی بکەرەوە.
Show answerوەڵامەکە پیشان بدە
class Kettle:
def describe(self):
return "a kettle full of tea"
class Samovar:
def describe(self):
return "a samovar in the tea house"
def show_all(things):
for thing in things:
try:
print(thing.describe())
except AttributeError:
print(f"skipped: {thing!r} has no describe()")
show_all([Kettle(), Samovar(), 42])a kettle full of tea a samovar in the tea house skipped: 42 has no describe()
Inheritance or composition? (a) Student and Person; (b) Library and Book; (c) ElectricCar and Car; (d) Car and Wheel.
یان ؟ (a) Student و Person؛ (b) Library و Book؛ (c) ElectricCar و Car؛ (d) Car و Wheel.
Show answerوەڵامەکە پیشان بدە
- (a) A student is a person: inheritance,
class Student(Person). - (b) A library has books: composition, a list of
Bookobjects. - (c) An electric car is a car: inheritance.
- (d) A car has wheels: composition.
- (a) قوتابی جۆرێکە لە کەس: ،
class Student(Person). - (b) کتێبخانە کتێبی هەیە: ، لە
Book. - (c) ئۆتۆمبێلی کارەبایی جۆرێکە لە ئۆتۆمبێل: .
- (d) ئۆتۆمبێل تایەی هەیە: .
Summaryپوختە
- Inheritance:
class Dog(Animal)gives Dog everything in Animal. Use it only when "a Dog is an Animal" is true. super().__init__(...)builds the superclass part; Python never calls it for you.- Overriding: a method with the same name in the subclass;
super().method()reuses the old one. isinstance()andissubclass()follow the family tree;type()gives only the exact class.- Polymorphism: one call, and each object runs its own version. Duck typing: any object with the method will do.
- An abstract base class (
ABC,@abstractmethod) cannot make objects, and forces subclasses to write the methods. - Composition (has-a) keeps other objects in attributes; prefer it when is-a is not clearly true.
- Several superclasses are allowed; the MRO decides the search order.
- :
class Dog(Animal)هەموو شتێکی Animal دەداتە Dog. تەنیا کاتێک بەکاری بهێنە کە «Dog جۆرێکە لە Animal» ڕاست بێت. super().__init__(...)بەشی دروست دەکات؛ هەرگیز خۆی بانگی ناکات.- : بە هەمان ناو لە ؛
super().method()کۆنەکە بەکار دەهێنێتەوە. isinstance()وissubclass()داری خێزانەکە پەیڕەو دەکەن؛type()تەنیا دەدات.- : یەک بانگکردن و هەر وەشانی خۆی جێبەجێ دەکات. : هەر کە هەبێت دەشێت.
- (
ABC،@abstractmethod) ناتوانێت دروست بکات و ناچار دەکات بنووسن. - («هەیەتی») تر لە هەڵدەگرێت؛ کاتێک «جۆرێکە لە» بە ڕوونی ڕاست نییە ئەمەی پێ باشتر بێت.
- چەند ڕێگە پێدراوە؛ ڕیزبەندیی گەڕان دیاری دەکات.
This ends the chapter on classes. The next chapter, Stacks, builds data structures, and a class makes a tidy home for each of them.
ئەمە کۆتایی بەشی . بەشی داهاتوو، ستاکەکان، دروست دەکات و ماڵێکی ڕێکوپێکە بۆ هەر یەکێکیان.
What is the difference between overriding and polymorphism?جیاوازیی نێوان پێناسەکردنەوەی میتۆد و فرەشێوەیی چییە؟
Overriding is what a subclass does: it writes its own version of a method. Polymorphism is what the caller gets: one call such as animal.speak() runs the right version for each object.
ئەوەیە کە دەیکات: وەشانی خۆی بۆ دەنووسێت. ئەوەیە کە بانگکەر وەریدەگرێت: یەک بانگکردنی وەک animal.speak() وەشانی دروست بۆ هەر جێبەجێ دەکات.
Duck typing or an abstract base class: when do you choose the ABC?جۆرداریی مراوی یان کلاسی ڕووت: کەی کلاسی ڕووت هەڵدەبژێریت؟
When a missing method should be caught early, at the moment an object is created, and when you want the required methods written down in one place.
کاتێک دەتەوێت کەم زوو بدۆزرێتەوە، لە ساتی دروستکردنی . هەروەها کاتێک دەتەوێت لە یەک شوێندا نووسرابن.
Why is class Farm(Animal) a bad design?بۆچی class Farm(Animal) دیزاینێکی خراپە؟
A farm is not an animal, so it would inherit methods like speak() that make no sense for it. A farm has animals: keep them in an attribute (composition).
کێڵگە ئاژەڵ نییە، بۆیە وەک speak() وەردەگرێت کە بۆ ئەو هیچ واتایەکیان نییە. کێڵگە ئاژەڵی هەیە: لە هەڵیانبگرە ().
Lesson complete!وانەکە تەواو بوو!
Well done. Review the key terms, then go on to the next lesson.دەستخۆش. سەیرێکی زاراوە سەرەکییەکان بکەرەوە، پاشان بڕۆ بۆ وانەی داهاتوو.
Key termsزاراوە سەرەکییەکان
Stacks: Last In, First Outستاکەکان: دوایین هاتوو، یەکەم دەرچوو
Related lecturesوانە پەیوەندیدارەکان
- Inheritance and Polymorphismبۆماوە و فرەشێوەیی
- Abstract Classes, Interfaces, Inner Classes and Enumsکلاسە ڕووتەکان، نێوبەستەکان، کلاسە ناوەکییەکان و ئینەمەکان
- Python Next to JavaPython لە تەنیشت Javaـەوە
- Handling Errors with try and exceptمامەڵەکردن لەگەڵ هەڵاوێردە بە try و except
- Dart Classes, Inheritance and Mixinsکلاسەکان، بۆماوە و میکسینەکان لە Dartـدا
- Stacks: Last In, First Outستاکەکان: دوایین هاتوو، یەکەم دەرچوو
References and further readingسەرچاوەکان و خوێندنەوەی زیاتر
- Python Tutorial 9.5: Inheritance and multiple inheritance (overriding, isinstance, issubclass, the MRO)
- Python Library Reference: abc — Abstract Base Classes (ABC, @abstractmethod)
- Python Glossary: duck-typing, EAFP, LBYL, abstract base class, method resolution order
- PEP 698: Override Decorator for Static Typing (typing.override, Python 3.12)
- University of Helsinki, Python Programming MOOC 2024, Part 10: Class hierarchies (base and derived classes, super(), overriding)
This lecture is a first edition. The Kurdish text and terminology are waiting for review by Kurdish IT teachers.ئەم وانەیە چاپی یەکەمە. دەقە کوردییەکە و زاراوەکانی چاوەڕێی پێداچوونەوەی مامۆستایانی کوردی بواری IT ن.