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، هەڵە باوەکان و ڕاهێنان.

22 min read20 خولەک خوێندنەوە · 21 stepsهەنگاو

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() and issubclass() correctly, and know why type() == misses subclasses.
  • Use polymorphism and duck typing to handle many kinds of objects with one loop.
  • Write an abstract base class with abc.ABC and @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 دەکات (بۆچی بۆماوە).

Left, without inheritance: three class boxes Dog, Cat and Sheep, each repeating name, age and describe() (marked in orange) and each with its own speak(); a fix must be made three times. Right, with inheritance: one Animal box with name, age and describe(), and below it Dog, Cat and Sheep with only speak(), each joined to Animal by an inheritance arrow. Written once, used by every subclass.چەپ، بەبێ بۆماوە: سێ سندوقی کلاس، Dog، Cat و Sheep، هەر یەکەیان name، age و describe() دووپاتە دەکاتەوە (بە پرتەقاڵی نیشانە کراون) و هەر یەکەیان speak()ـی خۆی هەیە؛ چاککردنەوەیەک دەبێت سێ جار بکرێت. ڕاست، بە بۆماوە: یەک سندوقی Animal بە name، age و describe() و لە ژێریدا Dog، Cat و Sheep تەنیا بە speak()، هەر یەکەیان بە تیرێکی بۆماوە بە Animalـەوە بەستراوە. یەک جار نووسراوە و هەموو کلاسەکانی منداڵ بەکاری دەهێنن.
Copied three times, or written once and inherited.سێ جار کۆپی کراو، یان یەک جار نووسراو و بە وەرگیراو.CêIT

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 لاشەیەکی بەتاڵە.

Dog and Sheep inherit from AnimalDog و Sheep لە Animalـەوە وەردەگرنfirst_subclass.pyPYTHONType in a terminalلە تێرمیناڵدا بینووسە
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())
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 class family. At the top, object; below it the superclass Animal with name, age, describe() and speak(). Below Animal four subclasses: Dog, which adds fetch(), and Cat, Sheep and Rooster, which inherit everything. Each subclass has an arrow up to Animal. The code class Dog(Animal): the superclass goes in the brackets.خێزانی کلاسەکان. لە سەرەوە object؛ لە ژێریدا کلاسی باوکەکە Animal بە name، age، describe() و speak(). لە ژێر Animal چوار کلاسی منداڵ: Dog کە fetch() زیاد دەکات و Cat، Sheep و Rooster کە هەموو شتێک وەردەگرن. هەر کلاسێکی منداڵ تیرێکی بەرەو Animal هەیە. کۆدی class Dog(Animal): کلاسی باوک لە ناو کەوانەکەدا دەنووسرێت.
One superclass, four subclasses, and object above them all.یەک ، چوار و object لە سەرووی هەموویانەوە.CêIT

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).

Three sentences. A dog is an animal: yes, class Dog(Animal). A square is a rectangle: yes, class Square(Rectangle). A farm is an animal?: no, class Farm(Animal) is crossed out; a farm has animals, so use composition.سێ ڕستە. سەگ ئاژەڵە: بەڵێ، class Dog(Animal). چوارگۆشە لاکێشەیە: بەڵێ، class Square(Rectangle). کێڵگە ئاژەڵە؟: نەخێر، class Farm(Animal) هێڵی بەسەردا هاتووە؛ کێڵگە ئاژەڵی هەیە، بۆیە ئاوێتەکردنی ئۆبجێکت بەکار بهێنە.
Say it as a sentence before you write it as code.پێش ئەوەی وەک کۆد بینووسیت، وەک ڕستە بیڵێ.CêIT

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ـی بۆ نانێریت.

Dog.__init__ calls Animal.__init__ first⁦Dog.__init__⁩ سەرەتا ⁦Animal.__init__⁩ بانگ دەکاتsuper_init.pyPYTHONType in a terminalلە تێرمیناڵدا بینووسە
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))
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.

یەک بە هەر سێ .

An animation in five steps for sher = Dog("Sher", 4, "Pshdar"). 1: Python makes an empty Dog object and calls Dog.__init__. 2: its first line, super().__init__(name, age), hands name and age to the superclass. 3: Animal.__init__ fills in name = 'Sher' and age = 4. 4: back in Dog.__init__, breed = 'Pshdar' is added. 5: one object with both parts.
An animation in five steps for sher = Dog("Sher", 4, "Pshdar"). 1: Python makes an empty Dog object and calls Dog.__init__. 2: its first line, super().__init__(name, age), hands name and age to the superclass. 3: Animal.__init__ fills in name = 'Sher' and age = 4. 4: back in Dog.__init__, breed = 'Pshdar' is added. 5: one object with both parts.
The superclass part first, then the subclass part.سەرەتا بەشی ، پاشان بەشی .CêIT

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__(...) لەبیر بکات، هەرگیز وەرناگرێت. هەڵەکە دواتر دەردەکەوێت، دوور لە هۆکارەکەی:

Wrong: the Animal part is missingهەڵە: بەشی Animal نییەforgot_super.pyPYTHONType in a terminalلە تێرمیناڵدا بینووسە
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())
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() دەیسەلمێنێت: تەنیا یەک هەیە.

The Dog class whose __init__ has the line super().__init__(name, age) missing and sets only self.breed. The object sher has breed = 'Pshdar', while name and age are empty and never set. sher.describe() needs self.name and fails with AttributeError: 'Dog' object has no attribute 'name'. Fix: call super().__init__(name, age) first in the subclass's __init__; Python does not call the superclass __init__ for you.کلاسی Dog کە لە __init__ـەکەیدا دێڕی super().__init__(name, age) نییە و تەنیا self.breed دادەنێت. ئۆبجێکتەکە sher breed = 'Pshdar'ـی هەیە، بەڵام name و age بەتاڵن و هەرگیز دانەنراون. sher.describe() پێویستی بە self.name هەیە و بە AttributeError: 'Dog' object has no attribute 'name' سەرناکەوێت. چارەسەر: لە دروستکەری کلاسی منداڵەکەدا سەرەتا super().__init__(name, age) بانگ بکە؛ Python خۆی دروستکەری کلاسی باوک بانگ ناکات.
No super().__init__(), no name and no age.بێ ⁦super().__init__()⁩، نە name و نە age.CêIT

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).

Dog and Cat override speak()Dog و Cat میتۆدی speak پێناسە دەکەنەوەoverriding.pyPYTHONType in a terminalلە تێرمیناڵدا بینووسە
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())
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.

Animal has speak() returning "..." and greet(). Below it Dog, which overrides speak() to return "Woof!", and Fish, which has only pass. For sher.speak(), step 1 finds speak in Dog: "Woof!". For nemo.speak(), step 1 finds nothing in Fish, so step 2 climbs to Animal: "...".Animal speak()ـی هەیە کە "..." دەگەڕێنێتەوە لەگەڵ greet(). لە ژێریدا Dog کە speak() پێناسە دەکاتەوە بۆ گەڕاندنەوەی "Woof!" و Fish کە تەنیا pass ـی هەیە. بۆ sher.speak()، هەنگاوی 1 speak لە Dogـدا دەدۆزێتەوە: "Woof!". بۆ nemo.speak()، هەنگاوی 1 لە Fishـدا هیچ نادۆزێتەوە، بۆیە هەنگاوی 2 سەردەکەوێت بۆ Animal: "...".
Python searches upward from the object's own class. لە خودی بەرەو سەرەوە دەگەڕێت.CêIT

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() وەشانەکەی جێبەجێ دەکات و شتێک بۆ ئەنجامەکەی زیاد دەکات. بەشە هاوبەشەکە لە یەک شوێندا دەمێنێتەوە.

Dog.describe() builds on Animal.describe()⁦Dog.describe()⁩ لەسەر ⁦Animal.describe()⁩ دروست دەبێتsuper_method.pyPYTHONType in a terminalلە تێرمیناڵدا بینووسە
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())
Explain the codeڕوونکردنەوەی کۆدەکە
Lineدێڕی 16

The old version does the first part.

وەشانە کۆنەکە بەشی یەکەم دەکات.

The code of Dog.describe(): text = super().describe() gives "Sher, 4 years old" from Animal's describe(); Dog adds ", a Pshdar dog"; together they make Sher, 4 years old, a Pshdar dog.کۆدی Dog.describe(): text = super().describe() لە describe()ـی Animalـەوە "Sher, 4 years old" دەدات؛ Dog ", a Pshdar dog" زیاد دەکات؛ پێکەوە دەبنە Sher, 4 years old, a Pshdar dog.
Reuse the old result, then add the new part.ئەنجامە کۆنەکە بەکار بهێنەوە، پاشان بەشە نوێیەکە زیاد بکە.CêIT

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).

Asking about the family treeپرسیار لەبارەی داری خێزانەکەisinstance_demo.pyPYTHONType in a terminalلە تێرمیناڵدا بینووسە
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 example
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: True and False are a kind of int.

نموونەی خودی : True و False جۆرێکن لە int.

A family tree: object at the top, then Animal, then Dog and Cat. The object sher hangs under Dog. Seven checks on the right: isinstance(sher, Dog) True; isinstance(sher, Animal) True; isinstance(sher, object) True; isinstance(sher, Cat) False; type(sher) == Animal False; issubclass(Dog, Animal) True; issubclass(Animal, Dog) False. A Dog is also an Animal and an object.دارێکی خێزانی: object لە سەرەوە، پاشان Animal، پاشان Dog و Cat. ئۆبجێکتەکە sher لە ژێر Dog هەڵواسراوە. حەوت پشکنین لە ڕاستەوە: isinstance(sher, Dog) True؛ isinstance(sher, Animal) True؛ isinstance(sher, object) True؛ isinstance(sher, Cat) False؛ type(sher) == Animal False؛ issubclass(Dog, Animal) True؛ issubclass(Animal, Dog) False. سەگ هەروەها Animal و objectـیشە.
isinstance() climbs the tree; type() stops at the exact class.⁦isinstance()⁩ بە دارەکەدا سەردەکەوێت؛ ⁦type()⁩ لە دەوەستێت.CêIT

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).

One loop, five speak() methodsیەک خول، پێنج میتۆدی speakpolymorphism.pyPYTHONType in a terminalلە تێرمیناڵدا بینووسە
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()
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.

هەمان دێڕ بۆ هەر جیاواز جێبەجێ دەکات.

An animation of the loop for animal in farm: print(animal.speak()). The list holds Sher (Dog), Pishi (Cat), Bafr (Sheep), Kalo (Rooster) and a plain Animal. In each frame one object is highlighted, an arrow goes to its own class's speak(), and its sound is added to the output: Woof!, Meow!, Baa!, Cock-a-doodle-doo! and .... The last frame says: the same line, five different results: this is polymorphism.
An animation of the loop for animal in farm: print(animal.speak()). The list holds Sher (Dog), Pishi (Cat), Bafr (Sheep), Kalo (Rooster) and a plain Animal. In each frame one object is highlighted, an arrow goes to its own class's speak(), and its sound is added to the output: Woof!, Meow!, Baa!, Cock-a-doodle-doo! and .... The last frame says: the same line, five different results: this is polymorphism.
One call in the loop, the right method for each object.یەک بانگکردن لە ، بۆ هەر .CêIT

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ـیەک کە ئەم هەبێت لە هەمان کار دەکات. ناوەکە لە پەندێکەوە هاتووە: «ئەگەر وەک مراوی بڕوات و وەک مراوی دەنگ بکات، مراوییە». ئەمە . ڕێگەش دەدات هەر یاریدەدەرێک کە دروستی هەبێت بدەیتە : بڕوانە تێخستنی وابەستەیی.

Any object with speak() will doهەر ئۆبجێکتێک کە ⁦speak()⁩ـی هەبێت دەشێتduck_typing.pyPYTHONType in a terminalلە تێرمیناڵدا بینووسە
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)
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() هەیە؟

The function make_it_speak(thing) calls thing.speak(). Four objects are passed to it: Dog() gives "Woof!", Robot() gives "Beep, I am a robot.", Radio() gives "Good morning, Erbil!", and Tractor() fails with AttributeError. Only Dog is an animal, but three of them have speak(); Python asks what an object can do, not what class it is.کردارەکە make_it_speak(thing) بانگی thing.speak() دەکات. چوار ئۆبجێکت دەدرێنێ: Dog() "Woof!" دەدات، Robot() "Beep, I am a robot." دەدات، Radio() "Good morning, Erbil!" دەدات و Tractor() بە AttributeError سەرناکەوێت. تەنیا Dog ئاژەڵە، بەڵام سێیان speak()ـیان هەیە؛ Python دەپرسێت ئۆبجێکتەکە چی دەکات، نەک چ کلاسێکە.
Python asks "can you speak()?", not "what are you?". دەپرسێت «دەتوانیت ⁦speak()⁩ بکەیت؟»، نەک «تۆ چیت؟».CêIT

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__()ـی هەبێت:

len() only needs __len__()⁦len()⁩ تەنیا پێویستی بە ⁦__len__()⁩ هەیەduck_len.pyPYTHONType in a terminalلە تێرمیناڵدا بینووسە
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()))

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، واتە «پێش بازدان سەیر بکە». کۆدی زۆرجار تاقیکردنەوەی پێ باشترە (سەرەتا بپشکنە، یان ڕاستەوخۆ تاقی بکەرەوە؟).

Two ways to handle a missing methodدوو ڕێگا بۆ میتۆدێکی نەبووeafp.pyPYTHONType in a terminalلە تێرمیناڵدا بینووسە
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")
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 نیشانە بکە. ئەم جۆرە تەنیا نەخشەیەکە: لێ دروست ناکات.

Shape is abstract; Rectangle is notShape ڕووتە؛ Rectangle ناabstract_shape.pyPYTHONType in a terminalلە تێرمیناڵدا بینووسە
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()
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.

خودی نەخشەکە ناتوانێت ببێتە .

Shape(ABC) drawn as a form with dashed edges: @abstractmethod area() and @abstractmethod perimeter() are empty boxes that each subclass must write; describe() is a normal method shared by all. Shape() on the left fails with TypeError: can't instantiate abstract class Shape. Below, Rectangle(Shape) writes both area() and perimeter(), so objects can be made: Rectangle(4, 2.5) gives area 10.00 and perimeter 13.00. Python checks when you create the object, not later.Shape(ABC) وەک فۆرمێک بە لێواری پچڕپچڕ کێشراوە: @abstractmethod area() و @abstractmethod perimeter() خانەی بەتاڵن کە هەر کلاسێکی منداڵ دەبێت بیاننووسێت؛ describe() میتۆدێکی ئاسایی هاوبەشی هەمووانە. Shape() لە چەپ بە TypeError سەرناکەوێت: ناتوانرێت ئۆبجێکت لە Shape دروست بکرێت. لە خوارەوە Rectangle(Shape) هەردوو area() و perimeter() دەنووسێت، بۆیە ئۆبجێکت دروست دەکرێت: Rectangle(4, 2.5) ڕووبەری 10.00 و چێوەی 13.00 دەدات. Python لە کاتی دروستکردنی ئۆبجێکتەکەدا دەپشکنێت، نەک دواتر.
An abstract class is a form; its subclasses fill in the empty boxes. فۆرمێکە؛ خانە بەتاڵەکانی پڕ دەکەنەوە.CêIT

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:

ئەگەر تەنیا هەندێک لە بنووسێت، هێشتا ڕووتە. یەکسەر دروستکردنی ڕەت دەکاتەوە و پەیامەکە ڕێک ناوی ئەوە دەهێنێت کە کەمە:

Circle forgot perimeter()Circle میتۆدی ⁦perimeter()⁩ـی لەبیر کردmissing_method.pyPYTHONType in a terminalلە تێرمیناڵدا بینووسە
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)

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 ڕەت دەکاتەوە، وەک لە کەپسوولکردن و خەسڵەتە بەڕێوەبراوەکان.

The class diagram of the shapes program. Shape (ABC) at the top with the abstract methods area() and perimeter() and a shared __str__(). Under it Circle (pi * r ** 2, 2 * pi * r), Triangle (Heron's formula, a + b + c) and Rectangle (w * h, 2 * (w + h)). Square inherits from Rectangle and calls super().__init__(side, side). A square is a rectangle with equal sides; the loop calls area() on each one and gets the right formula.هێڵکاریی کلاسەکانی بەرنامەکەی شێوەکان. Shape (ABC) لە سەرەوە بە میتۆدە ڕووتەکان area() و perimeter() و __str__()ـێکی هاوبەش. لە ژێریدا Circle (pi * r ** 2، 2 * pi * r)، Triangle (هاوکێشەی هیرۆن، a + b + c) و Rectangle (w * h، 2 * (w + h)). Square لە Rectangle وەردەگرێت و super().__init__(side, side) بانگ دەکات. چوارگۆشە لاکێشەیەکە بە لای یەکسان؛ خولەکە area() بۆ هەر یەکێکیان بانگ دەکات و هاوکێشە دروستەکە وەردەگرێت.
Four shapes, one plan, one loop.چوار شێوە، یەک نەخشە، یەک .CêIT
Rugs of every shapeبەڕە بە هەموو شێوەیەکshapes.pyPYTHONType in a terminalلە تێرمیناڵدا بینووسە
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)
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 has area().

max() کار دەکات چونکە هەموو شێوەیەک area()ـی هەیە.

Check the numbers: the circle is π×1.52≈7.07\pi \times 1.5^2 \approx 7.07 m², the 3-4-5 triangle has area 6 by Heron's formula s(s−a)(s−b)(s−c)\sqrt{s(s-a)(s-b)(s-c)} with s=6s = 6, 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.

ژمارەکان بپشکنە: بازنەکە π×1.52≈7.07\pi \times 1.5^2 \approx 7.07 ⁦m²⁩ـە، ڕووبەری سێگۆشەی ⁦3-4-5⁩ بە هاوکێشەی هیرۆن s(s−a)(s−b)(s−c)\sqrt{s(s-a)(s-b)(s-c)} و s=6s = 6 دەبێتە 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() بانگ دەکات و هەر ئاژەڵێک بە شێوەی خۆی وەڵام دەداتەوە.

A farm has animalsکێڵگە ئاژەڵی هەیەcomposition.pyPYTHONType in a terminalلە تێرمیناڵدا بینووسە
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 animal
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.

هیچ پەیوەندییەکی «جۆرێکە لە» دروست ناکات.

Three panels. Is-a, inheritance: Dog has an inheritance arrow to Animal; a dog is an animal; class Dog(Animal). Has-a, composition: Farm is joined by filled diamonds to Dog, Sheep and Sheep; a farm has animals; self._animals = []. Has-a, a part you can swap: Phone is joined to a 5000 mAh battery that can be replaced by a 6000 mAh one; a phone has a battery; self.battery = battery. Not sure? Prefer has-a: it is looser and easier to change.سێ بەش. «جۆرێکە لە»، بۆماوە: Dog تیرێکی بۆماوەی بەرەو Animal هەیە؛ سەگ ئاژەڵە؛ class Dog(Animal). «هەیەتی»، ئاوێتەکردنی ئۆبجێکت: Farm بە ئەڵماسی پڕ بە Dog، Sheep و Sheepـەوە بەستراوە؛ کێڵگە ئاژەڵی هەیە؛ self._animals = []. «هەیەتی»، پارچەیەک کە دەگۆڕدرێت: Phone بە پاترییەکی 5000 mAhـەوە بەستراوە کە دەکرێت بە 6000 mAh بگۆڕدرێت؛ مۆبایل پاتریی هەیە؛ self.battery = battery. دڵنیا نیت؟ «هەیەتی» باشترە: سستترە و ئاسانتر دەگۆڕدرێت.
Is-a builds a family tree; has-a builds an object out of parts.«جۆرێکە لە» دارێکی خێزانی دروست دەکات؛ «هەیەتی» لە پارچەکان دروست دەکات.CêIT

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__ـەوە، پێی دەوترێت : بڕوانە تێخستنی وابەستەیی.

A phone has a batteryمۆبایل پاتریی هەیەphone_battery.pyPYTHONType in a terminalلە تێرمیناڵدا بینووسە
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")
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زیادە: بۆماوە لە چەند کلاسێکی باوکەوە و ڕیزبەندیی گەڕانی میتۆد

A diamond of classes: Animal at the top (below object), Swimmer and Flyer under it, and Duck at the bottom inheriting from both. Numbered circles show the method resolution order: 1 Duck, 2 Swimmer, 3 Flyer, 4 Animal, 5 object. Beside it the code class Duck(Swimmer, Flyer) and Duck.__mro__ giving Duck, Swimmer, Flyer, Animal, object. Python looks in this order: the class, then its superclasses from left to right, Animal only once; super() follows the same order.ئەڵماسێک لە کلاسەکان: Animal لە سەرەوە (لە ژێر object)، Swimmer و Flyer لە ژێریدا و Duck لە خوارەوە کە لە هەردووکیان وەردەگرێت. بازنەی ژمارەدار ڕیزبەندیی گەڕانی میتۆد پیشان دەدەن: 1 Duck، 2 Swimmer، 3 Flyer، 4 Animal، 5 object. لە تەنیشتیەوە کۆدی class Duck(Swimmer, Flyer) و Duck.__mro__ کە Duck، Swimmer، Flyer، Animal، object دەدات. Python بەم ڕیزبەندییە دەگەڕێت: کلاسەکە، پاشان کلاسەکانی باوکی لە چەپەوە بۆ ڕاست، Animal تەنیا جارێک؛ super() هەمان ڕیزبەندی پەیڕەو دەکات.
The MRO walks the diamond from left to right, each class once. لە چەپەوە بۆ ڕاست بە ئەڵماسەکەدا دەڕوات، هەر یەک جار.CêIT

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بیرۆکەPythonJava
Subclassclass Dog(Animal):class Dog extends Animal
Superclass constructor super().__init__(name), never automaticsuper().__init__(name)، هەرگیز خۆکار نییەsuper(name); first; super() added if missingsuper(name); یەکەم دێڕ؛ ئەگەر نەبێت super() زیاد دەکرێت
OverridingSame name; @override (3.12+) only for checkersهەمان ناو؛ @override ⁦(3.12+)⁩ تەنیا بۆ پشکنەرەکانSame signature; @Overrideهەمان واژوو؛ @Override
Type checkپشکنینی جۆرisinstance(x, Dog)x instanceof Dog
Abstract classclass Shape(ABC) + @abstractmethodabstract 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

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 هیچ شتێک پێناسە نەکاتەوە.

speek() is a new method, not an override⁦speek()⁩ میتۆدێکی نوێیە، نەک پێناسەکردنەوەی میتۆدoverride_typo.pyPYTHONType in a terminalلە تێرمیناڵدا بینووسە
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
Explain the codeڕوونکردنەوەی کۆدەکە
Lineدێڕی 10

One wrong letter: Dog now has two methods, speak() (inherited) and speek().

یەک پیتی هەڵە: ئێستا Dog دوو هەیە، speak() (بۆماوەگیراو) و speek().

Lineدێڕی 22

@override changes 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ڕاهێنانەکان

ExerciseڕاهێنانA tea-house menuلیستی خواردنەوەی چایخانە

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وەڵامەکە پیشان بدە
One possible answerوەڵامێکی گونجاوex_drinks.pyPYTHONType in a terminalلە تێرمیناڵدا بینووسە
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())
ExerciseڕاهێنانPredict the outputدەرخستەکە پێشبینی بکە

What does this program print? Work it out on paper first.

ئەم چی چاپ دەکات؟ سەرەتا لەسەر کاغەز کاری لەسەر بکە.

Three classes, one methodسێ کلاس، یەک میتۆدex_predict.pyPYTHONType in a terminalلە تێرمیناڵدا بینووسە
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وەڵامەکە پیشان بدە
Outputدەرئەنجام
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() زیاد دەکات.

ExerciseڕاهێنانMonthly payمووچەی مانگانە

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وەڵامەکە پیشان بدە
One possible answerوەڵامێکی گونجاوex_staff.pyPYTHONType in a terminalلە تێرمیناڵدا بینووسە
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):,}")
ExerciseڕاهێنانA hexagonشەشگۆشە

Add RegularHexagon(side) to the shapes program: area 332s2\frac{3\sqrt{3}}{2}s^2, perimeter 6s6s. Check it with side 2.

RegularHexagon(side) بۆ شێوەکان زیاد بکە: ڕووبەر 332s2\frac{3\sqrt{3}}{2}s^2، چێوە 6s6s. بە لای 2 تاقی بکەرەوە.

Show answerوەڵامەکە پیشان بدە
One possible answerوەڵامێکی گونجاوex_hexagon.pyPYTHONType in a terminalلە تێرمیناڵدا بینووسە
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()}")

332×22=63≈10.39\frac{3\sqrt{3}}{2} \times 2^2 = 6\sqrt{3} \approx 10.39, and 6×2=126 \times 2 = 12.

332×22=63≈10.39\frac{3\sqrt{3}}{2} \times 2^2 = 6\sqrt{3} \approx 10.39 و 6×2=126 \times 2 = 12.

ExerciseڕاهێنانDuck typing in the tea houseجۆرداریی مراوی لە چایخانە

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وەڵامەکە پیشان بدە
One possible answer (EAFP)وەڵامێکی گونجاو ⁦(EAFP)⁩ex_duck.pyPYTHONType in a terminalلە تێرمیناڵدا بینووسە
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])
ExerciseڕاهێنانIs-a or has-a?«جۆرێکە لە» یان «هەیەتی»؟

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 Book objects.
  • (c) An electric car is a car: inheritance.
  • (d) A car has wheels: composition.
  • ⁦(a)⁩ قوتابی جۆرێکە لە کەس: ، class Student(Person).
  • ⁦(b)⁩ کتێبخانە کتێبی هەیە: ، لە Book.
  • ⁦(c)⁩ ئۆتۆمبێلی کارەبایی جۆرێکە لە ئۆتۆمبێل: .
  • ⁦(d)⁩ ئۆتۆمبێل تایەی هەیە: .

Summaryپوختە

A one-page map of the lesson. Inheritance (class Dog(Animal), is-a) leads down to overriding (same name, own version); an abstract class (@abstractmethod) forces subclasses to write methods. Overriding and duck typing (any object with the method) both lead to polymorphism (one call, many behaviours). super() builds or extends the parent part. Composition (self._animals = [], has-a) stands beside inheritance with the question: is-a or has-a?نەخشەیەکی یەک پەڕەیی وانەکە. بۆماوە (class Dog(Animal)، «جۆرێکە لە») بەرەو پێناسەکردنەوەی میتۆد (هەمان ناو، وەشانی خۆی) دەچێت؛ کلاسی ڕووت (@abstractmethod) کلاسەکانی منداڵ ناچار دەکات میتۆدەکان بنووسن. پێناسەکردنەوەی میتۆد و جۆرداریی مراوی (هەر ئۆبجێکتێک کە میتۆدەکەی هەبێت) هەردووکیان دەگەنە فرەشێوەیی (یەک بانگکردن، زۆر ڕەفتار). super() بەشی باوک دروست دەکات یان فراوانی دەکات. ئاوێتەکردنی ئۆبجێکت (self._animals = []، «هەیەتی») لە تەنیشت بۆماوە وەستاوە بەم پرسیارەوە: «جۆرێکە لە» یان «هەیەتی»؟
Seven ideas and how they connect.حەوت بیرۆکە و چۆنیەتیی پەیوەندییان.CêIT
  • 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() and issubclass() 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.

ئەمە کۆتایی بەشی . بەشی داهاتوو، ستاکەکان، دروست دەکات و ماڵێکی ڕێکوپێکە بۆ هەر یەکێکیان.

Review questionsپرسیارەکانی پێداچوونەوە
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زاراوە سەرەکییەکان

Next lessonوانەی داهاتوو

Stacks: Last In, First Outستاکەکان: دوایین هاتوو، یەکەم دەرچوو

References and further readingسەرچاوەکان و خوێندنەوەی زیاتر

This lecture is a first edition. The Kurdish text and terminology are waiting for review by Kurdish IT teachers.ئەم وانەیە چاپی یەکەمە. دەقە کوردییەکە و زاراوەکانی چاوەڕێی پێداچوونەوەی مامۆستایانی کوردی بواری IT ن.

Appearanceڕووکار

Modeدۆخ
Styleشێواز
Coloursڕەنگەکان

Saved on this device only.تەنیا لەسەر ئەم ئامێرە پاشەکەوت دەکرێت.