Перед тем как написать сво

Ваш первый класс

Перед тем как написать ваш первый класс, вы должны знать синтаксис. Мы определяем класс следующим образом.

class nameoftheclass(parent_class):
    statement1
    statement2
    statement3

В этих выражениях вы можете написать любое выражение Python, вы можете определить функции (которые мы называем методами класса).

>>> class MyClass(object):
...     a = 90
...     b = 88
...
>>> p = MyClass()
>>> p
<__main__.MyClass instance at 0xb7c8aa6c>

В приведенном выше примере вы можете увидеть, что сначала мы объявляем класс под названием MyClass, записываем несколько случайных выражений внутри этого класса. После определения класса мы создаем объект p класса MyClass. Если вы выполните dir на этом

>>> dir(p)
['__doc__', '__module__', 'a', 'b']

вы увидите переменные a и b внутри него.

__init__ метод

__init__ — это специальный метод в классах Python, он является конструктором класса. В следующем примере вы можете увидеть, как его использовать.

class Student(object):
    """
    Возвращает объект ```Student```python с заданным именем, специальностью и годом.

    """
    def __init__(self, name, branch, year):
            self.name = name
            self.branch = branch
            self.year = year
            print("Создан объект студента.")

    def print_details(self):
        """
        Выводит детали студента.
        """
        print("Имя:", self.name)
        print("Специальность:", self.branch)
        print("Год:", self.year)

__init__ вызывается всякий раз, когда создается объект класса. Это означает, что каждый раз, когда мы будем создавать объект студента, мы увидим сообщение “Создан объект студента” в командной строке. Вы можете видеть, что первый аргумент метода — self. Это специальная переменная, которая указывает на текущий объект (как this в C++). Объект неявно передается каждому доступному методу, но мы должны явно указывать его в каждом методе при написании методов. Пример показан ниже.

>>> std1 = Student()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: __init__() takes exactly 4 arguments (1 given)
>>> std1 = Student('Kushal','CSE','2005')
Создан объект студента

В этом примере сначала мы попытались создать объект Student без передачи аргументов, и интерпретатор Python сообщил, что требуется ровно 4 аргумента, но получен только один (self). Затем мы создали объект с правильными значениями аргументов, и из выведенного сообщения легко понять, что метод __init__ был вызван как конструктор.

Теперь мы собираемся вызвать метод print_details().

>>> std1.print_details()
Имя: Kushal
Специальность: CSE
Год: 2005

Наследование

В общем, мы, люди, всегда знаем о наследовании. В программировании это почти то же самое. Когда класс наследует другой класс, он наследует все его особенности (например, переменные и методы) родительского класса. Это помогает в повторном использовании кода.

В следующем примере мы сначала создаем класс под названием Person и создаем два подкласса Student и Teacher. Поскольку оба класса наследуются от класса Person, они будут иметь все методы Person и будут иметь новые методы и переменные для своих собственных целей.

student_teacher.py

#!/usr/bin/env python

class Person(object):
    """
    Возвращает объект ```Person```python с заданным именем.

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

    def get_details(self):
        "Возвращает строку, содержащую имя человека"
        return self.name


class Student(Person):
    """
    Возвращает объект ```Student```python, принимает 3 аргумента: name, branch, year.

    """
    def __init__(self, name, branch, year):
        Person.__init__(self, name)
        self.branch = branch
        self.year = year

    def get_details(self):
        "Возвращает строку, содержащую детали студента."
        return "%s учится на %s и находится в %s году." % (self.name, self.branch, self.year)


class Teacher(Person):
    """
    Возвращает объект ```Teacher```python, принимает список строк (список статей) в качестве
    аргумента.
    """
    def __init__(self, name, papers):
        Person.__init__(self, name)
        self.papers = papers

    def get_details(self):
        return "%s преподает %s" % (self.name, ','.join(self.papers))


person1 = Person('Сачин')
student1 = Student('Кушал', 'КСЕ', 2005)
teacher1 = Teacher('Прашад', ['C', 'C++'])

print(person1.get_details())
print(student1.get_details())
print(teacher1.get_details())

Вывод:

$ ./student_teacher.py
Сачин
Кушал учится на КСЕ и находится в 2005 году.
Прашад преподает C,C++

В этом примере вы можете увидеть, как мы вызывали метод __init__ класса Person в методах __init__ обоих классов Student и Teacher. Мы также переопределили метод get_details() класса Person в обоих классах Student и Teacher. Таким образом, когда мы вызываем метод get_details() для объекта teacher1, он возвращается на основе самого объекта (который является объектом класса teacher), а когда мы вызываем get_details() для объектов student1 или person1, он возвращается на основе метода get_details(), реализованного в их собственном классе.

student_teacher.py

#!/usr/bin/env python

class Person(object):
    """
    Возвращает объект ```Person```python с заданным именем.

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

    def get_details(self):
        "Возвращает строку, содержащую имя человека"
        return self.name


class Student(Person):
    """
    Возвращает объект ```Student```python, принимает 3 аргумента: name, branch, year.

    """
    def __init__(self, name, branch, year):
        Person.__init__(self, name)
        self.branch = branch
        self.year = year

    def get_details(self):
        "Возвращает строку, содержащую детали студента."
        return "%s учится на %s и находится в %s году." % (self.name, self.branch, self.year)


class Teacher(Person):
    """
    Возвращает объект ```Teacher```python, принимает список строк (список статей) в качестве
    аргумента.
    """
    def __init__(self, name, papers):
        Person.__init__(self, name)
        self.papers = papers

    def get_details(self):
        return "%s преподает %s" % (self.name, ','.join(self.papers))


person1 = Person('Сачин')
student1 = Student('Кушал', 'КСЕ', 2005)
teacher1 = Teacher('Прашад', ['C', 'C++'])

print(person1.get_details())
print(student1.get_details())
print(teacher1.get_details())

Результат:

$ ./student_teacher.py
Сачин
Кушал учится на КСЕ и находится в 2005 году.
Прашад преподает C,C++

В этом примере вы можете увидеть, как мы вызывали метод __init__ класса Person в методах __init__ классов Student и Teacher. Мы также переопределили метод get_details() класса Person в обоих классах Student и Teacher. Таким образом, когда мы вызываем метод get_details() на объекте teacher1, он возвращает результат на основе самого объекта (который является объектом класса Teacher), а когда мы вызываем метод get_details() на объектах student1 или person1, он возвращает результат на основе метода get_details(), реализованного в их собственном классе.

Множественное наследование

Один класс может наследовать более одного класса. Он получает доступ ко всем методам и переменным родительских классов. Общая синтаксис выглядит следующим образом:

class MyClass(Parentclass1, Parentclass2,...):
    def __init__(self):
        Parentclass1.__init__(self)
        Parentclass2.__init__(self)
        ...
        ...

Удаление объекта

Как мы уже знаем, как создать объект, теперь мы рассмотрим, как удалить объект Python. Для этого мы используем del.

>>> s = "Я тебя люблю"
>>> del s
>>> s
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 's' is not defined

del фактически уменьшает счетчик ссылок на единицу. Когда счетчик ссылок объекта становится равным нулю, сборщик мусора удалит этот объект.

Геттеры и сеттеры в Python

Один простой ответ — не надо. Если вы пришли из других языков (читай Java), вам будет искушать использовать геттеры или сеттеры во всех ваших классах. Пожалуйста, не делайте этого. Просто используйте атрибуты напрямую. Следующий пример демонстрирует прямое использование.

>>> class Student(object):
...     def __init__(self, name):
...         self.name = name
...
>>> std = Student("Kushal Das")
>>> print(std.name)
Kushal Das
>>> std.name = "Python"
>>> print std.name
Python

Свойства

Если вам нужен более тонкий контроль над доступом к атрибутам данных, то вы можете использовать свойства. В следующем примере банковского счета мы обеспечим, чтобы никто не мог установить значение денег в отрицательное, а также свойство под названием inr будет предоставлять нам значения долларов в счете в индийских рупиях.

#!/usr/bin/env python

class Account(object):
    """Класс Account,
    Сумма указана в долларах.
    """
    def __init__(self, rate):
        self.__amt = 0
        self.rate = rate

    @property
    def amount(self):
        "Сумма денег на счете"
        return self.__amt

    @property
    def inr(self):
        "Предоставляет сумму в индийских рупиях."
        return self.__amt * self.rate

    @amount.setter
    def amount(self, value):
        if value < 0:
            print "Извините, на счете не может быть отрицательной суммы."
            return
        self.__amt = value

if __name__ == '__main__':
    acc = Account(rate=61) # На основе сегодняшнего курса INR :(
    acc.amount = 20
    print("Сумма в долларах:", acc.amount)
    print("В индийских рупиях:", acc.inr)
    acc.amount = -100
    print("Сумма в долларах:", acc.amount)

Вывод:

$ python property.py
Сумма в долларах: 20
В индийских рупиях: 1220
Извините, на счете не может быть отрицательной суммы.
Сумма в долларах: 20

Перейти к следующему уроку →