Урок 27. Ітератори та генератори

Ітератори в Python — це об’єкти, які дозволяють перебирати елементи колекції (наприклад, списків, кортежів, словників, множин) по одному за раз. Вони реалізують протокол ітерації, що складається з двох методів: __iter__() і __next__(). Ітератори є корисними для економії пам’яті, оскільки вони генерують елементи на льоту, не зберігаючи всю колекцію в пам’яті. Приклад з відео:

#Ітератор - це об'єкт, 
#який містить підраховану кількість значень.
#Ітератор — це об’єкт, який можна повторювати, 
#тобто ви можете проходити через усі значення.
#У Python ітератор — це об’єкт, який реалізує 
#протокол ітератора, який складається 
#з методів __iter__() і __next__().
#Списки, кортежі, словники та множини
#є ітерабельними об’єктами.
str1 = "Text"
str1Iterator = iter(str1)
print(str1Iterator)
print(next(str1Iterator))
print(next(str1Iterator))
print(next(str1Iterator))
print(next(str1Iterator))
#print(next(str1Iterator))
list1 = ["Dodge", "Ford", "Toyota"]
list1Iterator = iter(list1)
print(list1Iterator)
print(next(list1Iterator))
print(next(list1Iterator))
print(next(list1Iterator))
for i in list1:
    print(i)

Для створення об’єкта чи класу як ітератора потрібно реалізувати в ньому методи __iter__() та __next__(). Приклад з відео:

#Щоб створити об’єкт/клас як ітератор, 
#вам потрібно реалізувати
#методи __iter__() і __next__() 
#для вашого об’єкта.
#Метод __iter__() завжди повинен 
#повертати сам об’єкт ітератора.
#Метод __next__() також дозволяє 
#виконувати операції, і має повернути 
#наступний елемент у послідовності.
class IncreaseByOne:
    def __iter__(self):
        self.num = 1
        return self
    def __next__(self):
        nextnum = self.num
        self.num += 1
        return nextnum
    
instance1 = IncreaseByOne()
iterator1 = iter(instance1)
print(next(iterator1))
print(next(iterator1))
print(next(iterator1))
print(next(iterator1))
print(next(iterator1))

Для уникнення нескінченного виконання ітепацій можна використати StopIteration. Приклад з відео:

#Щоб ітерація не тривала вічно, ми можемо 
#використати оператор StopIteration.
class IncreaseByOne:
    def __iter__(self):
        self.num = 1
        return self
    def __next__(self):
        if self.num<=10:
            nextnum = self.num
            self.num += 1
            return nextnum
        else:
            raise StopIteration
    
instance1 = IncreaseByOne()
iterator1 = iter(instance1)
for i in iterator1:
    print(i)

Генератори

Генератори — це простіший спосіб створення ітераторів. Вони використовують оператор yield, щоб повернути значення на льоту без необхідності реалізовувати методи __iter__() і __next__(). Приклад з відео:

#У Python генератор — це функція, 
#яка повертає ітератор
#Ми можемо визначити функцію генератора 
#за допомогою ключового слова def,
#але замість оператора return ми 
#використовуємо оператор yield.
#Ключове слово yield використовується 
#для створення значення з генератора.
#Коли викликається функція генератора, 
#вона не виконує тіло функції негайно. 
#Натомість він повертає об’єкт-генератор, 
#який можна повторити, щоб отримати значення.
def increaseByOneGenerator(n):
    num = 0
    while num<n:
        yield num
        num+=1
        
for i in increaseByOneGenerator(10):
    print(i)
print("---------------")
generator1 = increaseByOneGenerator(25)
print(next(generator1))
print(next(generator1))
print(next(generator1))
for i in generator1:
    print(i)

Приклад з відео із застосуванням спрощеного синтаксису для генераторів:

#expression for item in iterable
#Вираз-генератор створює об’єкт-генератор, 
#який виробляє значення виразу для кожного 
#елемента об’єкта, що повторюється, 
#по одному під час кожної ітерації.
squareGenerator = (num*num for num in range(10))
for i in squareGenerator:
    print(i)
Урок 27. Ітератори та генератори

В цьому відео поговоримо про ітератори та генератори.

Приклади на Github

Урок 26. Поліморфізм

Поліморфізм в Python — це принцип об’єктно-орієнтованого програмування, що дозволяє об’єктам різних класів оброблятися через єдиний інтерфейс. Це означає, що одна й та ж операція може мати різні реалізації для різних типів об’єктів. Поліморфізм підвищує гнучкість і зручність використання коду. Приклад поліморфізму з відео на ілюстрації застосування функції len() з об’єктами різних класів:

#Слово «поліморфізм» означає «багато форм», 
#і в програмуванні воно відноситься до 
#методів/функцій/операторів з однаковою назвою, 
#які можуть виконуватися для багатьох об’єктів або класів.
#Наприклад функція len().
str1 = "Python is a solid choice."
print(len(str1))
list1 = ["Dodge", "Ford", "Toyota"]
print(len(list1))
tuple1 = ("Lincoln", "Honda", "Alfa Romeo")
print(len(tuple1))

Приклад поліморфізму з відео із застосування методу sound() для об’єктів різних класів:

#Слово «поліморфізм» означає «багато форм», 
#і в програмуванні воно відноситься до 
#методів/функцій/операторів з однаковою назвою, 
#які можуть виконуватися для багатьох 
#об’єктів або класів.
class Cat:
    def sound(self):
        print("Meow, meow, meow")
        
class Dog:
    def sound(self):
        print("Woof, woof, woof")
        
cat1 = Cat()
dog1 = Dog()
cat1.sound()
dog1.sound()

Поліморфізм можна використовувати у комбінації з наслідуванням. Приклад з відео:

#Ми можемо використовувати поліморфізм 
#із класами наслідування
class Animal:
    def sound(self):
        print("Animal sound")
    
class Cat(Animal):
    def sound(self):
        print("Meow")
        
class Dog(Animal):
    def sound(self):
        print("Woof")
        
cat1 = Cat()
dog1 = Dog()
cat1.sound()
dog1.sound()
Урок 26. Поліморфізм

В цьому відео поговоримо про поліморфізм (важлива концепція ООП).

Приклади на Github

Урок 25. Наслідування

Ілюстрація з відео для пояснення потреби в наслідуванні:

#Навіщо нам наслідування?
class Person:
    def __init__(self, name, surname):
        self.name = name
        self.surname = surname
        
class Student:
    def __init__(self, name, surname):
        self.name = name
        self.surname = surname
        
person1 = Person("John", "Smith")
student1 = Student("Jenny", "Jackson")
print(person1.name, person1.surname)
print(student1.name,student1.surname)

Наслідування в Python — це один з основних принципів об’єктно-орієнтованого програмування, який дозволяє створювати нові класи на основі вже існуючих. Це дозволяє повторно використовувати код, спрощує його підтримку та забезпечує більш організовану структуру. Клас, який наслідується, називається “батьківським” (або “базовим”), а новий клас, що його наслідує, — “дочірнім”. Приклад з відео:

#Inheritance (наслідування) 
#дозволяє нам визначити клас, 
#який успадковує всі методи
#та властивості з іншого класу.
#Батьківський клас — це клас, який успадковується, 
#також називається базовим класом.
#Дочірній клас - це клас, який успадковує інший клас,
#також називається похідним класом.
class Person:
    def __init__(self, name, surname):
        self.name = name
        self.surname = surname
        
class Student(Person):
    pass
        
person1 = Person("John", "Smith")
student1 = Student("Jenny", "Jackson")
print(person1.name, person1.surname)
print(student1.name,student1.surname)

Функція super()

В Python є функція super(), яка дозволяє дочірньому класу наслідувати властивості від батьківського. Приклад з відео:

#Python також має функцію super(), 
#яка змусить дочірній клас успадкувати 
#всі методи та властивості від 
#свого батьківського класу.
class Person:
    def __init__(self, name, surname):
        self.name = name
        self.surname = surname
        
class Student(Person):
    def __init__(self, name, surname, averageMark):
        super().__init__(name, surname)
        self.averageMark = averageMark
        
person1 = Person("John", "Smith")
student1 = Student("Jenny", "Jackson", 3.5)
print(person1.name, person1.surname)
print(student1.name,student1.surname, student1.averageMark)

Множинне наслідування

Множинне наслідування в Python — це можливість створення дочірнього класу, який наслідує від кількох батьківських класів одночасно. Це дозволяє об’єднувати властивості та методи декількох класів, що може бути корисним у складних системах, де потрібно інтегрувати функціональність з різних джерел. Приклад з відео:

#Python підтримує множинне наслідування
class PythonDeveloper:
    def projectPython(self):
        print("Python coding in process.")
        
class JavaDeveloper:
    def projectJava(self):
        print("Java coding in process.")
        
class PythonJavaDeveloper(PythonDeveloper, JavaDeveloper):
    pass

developer1 = PythonJavaDeveloper()
developer1.projectPython()
developer1.projectJava()

Функція isinstance()

Функція isinstance() в Python використовується для перевірки, чи є об’єкт певного типу або чи належить він до певного класу (або підкласу). Вона повертає True, якщо об’єкт є екземпляром вказаного класу або його підкласу, і False в іншому випадку. Приклад з відео:

#Функція isinstance допомагає 
#перевірити тип об'єкта
class PythonDeveloper:
    def projectPython(self):
        print("Python coding in process.")
        
class JavaDeveloper:
    def projectJava(self):
        print("Java coding in process.")
        
developer1 = JavaDeveloper()

if isinstance(developer1,PythonDeveloper):
    print("This is PythonDeveloper object.")
    
elif isinstance(developer1, JavaDeveloper):
    print("This is JavaDeveloper object.")
    
else:
    print("Unknown object type.")
Уроки 25. Уроки наслідування

В цьому відео поговоримо про наслідування (важлива концепція ООП).

Приклади на Github

Урок 24. Інкапсуляція

Атрибути класів за помовчанням доступні або публічні (public), що надає можливість їх змінювати. Приклад з відео:

#Атрибути класу доступні за замовчуванням, 
#що означає, що ви можете їх змінити.
class Person:
    def __init__(self, name, surname, age):
        self.name = name
        self.surname = surname
        self.age = age
        
    def displayFunc(self):
        print(f"Name: {self.name} Surname:{self.surname} Age:{self.age}")
        
person1 = Person("John", "Smith", 35)
person1.displayFunc()
person1.age = -200
person1.surname = "InvalidSurname"
person1.name = "InvalidName"
person1.displayFunc()
print(person1.surname)

Інкапсуляція у Python — це принцип об’єктно-орієнтованого програмування, що полягає в приховуванні даних об’єкта та наданні доступу до них лише через визначені методи. Це дозволяє контролювати, як дані використовуються, забезпечуючи безпеку і запобігаючи випадковим змінам. У Python для цього використовують односторонній доступ до атрибутів, позначаючи їх як приватні, за допомогою одного або двох підкреслень.

Варіанти модифікаторів доступу:

  • self.name = name – public, доступні звідусіль
  • self._name = name – protected, доступні в межах класу та підкласів
  • self.__name = name – private, доступні в межах класу

Для того щоб зробити змінну приватною треба додати два підкреслення на початку назви змінної. Приклад з відео:

#Ми можемо захистити змінні в класі, 
#позначивши їх приватними.
#Щоб визначити приватну змінну, 
#додайте два підкреслення як префікс
#на початку назви змінної.
#self.__age
class Person:
    def __init__(self, name, surname, age):
        self.__name = name
        self.__surname = surname
        self.__age = age
        
    def displayFunc(self):
        print(f"Name:{self.__name} Surname:{self.__surname} Age:{self.__age}")
        
person1 = Person("John", "Smith", 35)
person1.displayFunc()
#print(person1.__age)
#print(person1.__surname)
#print(person1.__name)

Приклад з відео із застосуванням методу displayFunc() для виведення атрибутів об’єкта класу Person і спробою внесення змін у приватні атрибути:

class Person:
    def __init__(self, name, surname, age):
        self.__name = name
        self.__surname = surname
        self.__age = age
        
    def displayFunc(self):
        print(f"Name:{self.__name} Surname:{self.__surname} Age:{self.__age}")
        
person1 = Person("John", "Smith", 35)
person1.displayFunc()
person1.__name = "James"
person1.__surname = "Johns"
person1.__age = 25
print("--------------")
person1.displayFunc()
print(person1.__age)
print(person1.__surname)
print(person1.__name)
person2 = Person("Jenny", "Jackson", 30)
person2.displayFunc()
print(person2.__age)

Геттери та сеттери

Для внесення змін у приватні атрибути можна використовувати спеціальні методи: setter method (сеттери) – для внесення змін у визначені атрибути класу, getter method (геттери) – для отримання поточних даних з атрибутів класу. Прикладі з відео:

class Person:
    def __init__(self, surname, age):
        self.__surname = surname
        self.__age = age
        
    #setter method
    def setAge(self, age):
        if 1<age<120:
            self.__age=age
            
        else:
            print("Invalid age input.")
    #getter method            
    def getAge(self):
        return self.__age

person1 = Person("Smith", 35)
print(person1.getAge())
person1.setAge(33)
print(person1.getAge())
person1.setAge(0)
print(person1.getAge())
print(person1.__surname)

Замість методів геттерів та сеттерів можна використовувати так звані властивості геттерів та сеттерів. Особливість синтаксису полягає у використанні символу @ для позначення відповідних властивостей. Приклад з відео:

#Щоб створити властивість геттера, 
#використовуйте анотацію @property.
#Щоб створити властивість сеттера, 
#використовуйте анотацію @name.setter.
class Person:
    def __init__(self, surname, age):
        self.__surname = surname
        self.__age = age
        
    @property
    def age(self):
        return self.__age
    
    @age.setter
    def age(self, age):
        if 1<age<120:
            self.__age=age    
        else:
            print("Invalid age input.")
            
person1 = Person("Smith", 35)
print(person1.age)
person1.age = 33
print(person1.age)
person1.age = 150
print(person1.age)
Урок 24. Інкапсуляція

В цьому відео поговоримо про інкапсуляцію (важлива концепція ООП).

Приклади на Github

Урок 23. Класи і об’єкти

Класи в Python — це шаблони для створення об’єктів, які дозволяють організувати дані і функціональність у програмі. Вони є основою об’єктно-орієнтованого програмування (ООП) і дозволяють створювати об’єкти, які мають власні атрибути (дані) і методи (функції). Приклад з відео:

#Python — це об'єктно-орієнтована 
#мова програмування.
#Майже все в Python є об’єктом 
#зі своїми властивостями та методами.
#Клас схожий на конструктор об’єктів 
#або «схему» для створення об’єктів.
#Щоб створити клас, використовуйте 
#ключове слово class
class MyFavouriteNumber:
    favouriteNumber = 5
    
#Now we can use the class named MyFavouriteNumber to create objects
favNum1 = MyFavouriteNumber()
print(favNum1)
print(type(favNum1))
print(favNum1.favouriteNumber)

Функція __init__()

Функція __init__() в Python — це спеціальний метод, який використовується як конструктор класу. Він викликається автоматично при створенні нового об’єкта цього класу і використовується для ініціалізації атрибутів об’єкта. Приклад з відео:

#Щоб зрозуміти значення класів, 
#ми повинні зрозуміти
#вбудовану функцію __init__().
#Усі класи мають функцію під 
#назвою __init__(), яка завжди
#виконується, коли клас ініціюється.
#Функція __init__() щоразу 
#викликається автоматично
#клас використовується для 
#створення нового об'єкта.
class MyFavouriteNumber:
    def __init__(self, favouriteNumber):
        self.favouriteNumber=favouriteNumber
        
favNum1 = MyFavouriteNumber(7)

print(favNum1.favouriteNumber)

favNum2 = MyFavouriteNumber(8)

print(favNum2.favouriteNumber)

Функція __str__()

Функція __str__() в Python — це спеціальний метод, який визначає, як об’єкт класу буде представлений у вигляді рядка. Він викликається, коли ви використовуєте функцію print() або функцію str() для об’єкта. Приклад з відео:

#Функція __str__() керує тим, 
#що має бути повернуто
#коли об'єкт класу представлено 
#у вигляді рядка.
#Якщо функцію __str__() не встановлено, 
#повертається рядкове представлення об'єкта 

class Person:
    def __init__(self, name, surname, age):
        self.name = name
        self.surname = surname
        self.age = age
        
person1 = Person("John", "Smith", 35)
print(person1)
print(person1.name, person1.surname, person1.age)
person2 = Person("Jenny", "Jackson", 30)
print(person2)
print(person2.name, person2.surname, person2.age)

Приклад рядкового представлення об’єкта за допомогою функції __str__() з відео:

#Рядкове представлення 
#об’єкта з функцією __str__().
class Person:
    def __init__(self, name, surname, age):
        self.name = name
        self.surname = surname
        self.age = age
        
    def __str__(self):
        return f"Name: {self.name} Surname: {self.surname} Age: {self.age}"

        
person1 = Person("John", "Smith", 35)
print(person1)
person2 = Person("Jenny", "Jackson", 30)
print(person2)

Методи об’єкта

Спрощено методи об’єкта в Python — це функції, які визначені всередині класу і можуть бути викликані на об’єктах цього класу. Вони дозволяють виконувати дії або маніпулювати атрибутами об’єкта. Приклад з відео:

#Об'єкти також можуть містити методи. 
#Методи в об'єктах є функціями
#які належать об'єкту.
#Параметр self - це посилання на 
#поточний екземпляр класу,
#та використовується для доступу до 
#змінних, які належать до класу.
class Person:
    def __init__(self, name, surname):
        self.name = name
        self.surname = surname
        
    def introduceFunc(self):
        print("Hello my name is {} {}".format(self.name, self.surname))
        
person1 = Person("John", "Smith")
person1.introduceFunc()
person2 = Person("Jenny", "Jackson")
person2.introduceFunc()

Параметр self

Параметр self в Python — це посилання на поточний об’єкт класу, з яким працює метод. Він використовується для доступу до атрибутів і методів цього об’єкта. Приклад з відео:

#Параметр self - це посилання на 
#поточний екземпляр класу,
#та використовується для доступу до 
#змінних, які належать до класу.
#Його не обов'язково називати self, 
#ви можете називати його як завгодно,
#але це має бути перший параметр 
#будь-якої функції в класі.
class Person:
    def __init__(refToCurrentInstance, name, surname):
        refToCurrentInstance.name = name
        refToCurrentInstance.surname = surname
        
    def introduceFunc(refToCurrentInstance):
        print("Hello my name is {} {}".format(refToCurrentInstance.name,
                                              refToCurrentInstance.surname))
        
person1  = Person("John", "Smith")
person1.introduceFunc()
person2 = Person("Jenny", "Jackson")
person2.introduceFunc()

Внесення змін в об’єкти класу

Змінювати об’єктіи класу можна за допомогою так званого dot syntax (синтаксису крапки). Dot syntax (синтаксис крапки) в Python — це спосіб доступу до атрибутів і методів об’єктів або класів за допомогою крапки. Це дозволяє вам працювати з властивостями та функціями, які належать до конкретного об’єкта або класу. Приклад з відео:

#Ви можете змінювати властивості об’єктів, 
#використовуючи крапковий синтаксис для доступу
class Person:
    def __init__(self, name, surname, age):
        self.name =  name
        self.surname =  surname
        self.age = age
        
    def introduceFunc(self):
        print("Hello my name is {} {}".format(self.name, self.surname))
        print("I'm {} old".format(self.age))
        

person1 = Person("John", "Smith", 35)
person1.introduceFunc()
person1.name = "James"
person1.age = 33
person1.introduceFunc()
del person1.age
#person1.introduceFunc()
del person1
#print(person1)
Урок 23. Класи та об’єкти

В цьому відео поговоримо про:
00:06 Classes
03:43 init() Function
09:39 str() Function
18:30 Object Methods
22:35 self Parameter
27:14 Modify Objects

Приклади на Github