Python: классы — краткий обзор: аргументы, методы и специальные методы, импорт классов

Автор: | 08/18/2014
 

PythonСтруктура класса

class ClassName:
   'Optional class documentation string'
   class_body

Тут:
class — объявление класса, аналогично def в функциях;
ClassName — имя класса; так же может включать в скобках имя «родительского класса» (наследование классов);
'Optional class documentation string' — опционально, описание класса, доступна при вызове ClassName.__doc__;
class_body — тело класса: методы и атрибуты класса.

Атрибуты данных класса — переменные, в области этого класса.

Атрибуты-методы класса — грубо говоря, функции, которые в нём описаны.

Для простоты — можно их называть как «атрибуты» (про атрибуты данных), и «методы» (про атрибуты-методы).

Простой пример класса на Python:

class thisIsClass:
        # зададим два аргумента, разных типов - string  и int
        arg1 = 'string'
        arg2 = 100

        # определим метод
        def method(self):
                # действия, выполняемые методом
                print 'nRunning method:'
                print self.arg1
                print self.arg2
# создадём экземпляр (или "объект") класса
class_instance = thisIsClass()

# вызываем два аргумента экземпляра класса
print 'Printing arguments:'
print class_instance.arg1
print class_instance.arg2

# вызываем метод экземпляра класса
class_instance.method()

Выполним его:

$ ./class.py
Printing arguments:
string
100

Running method:
string
100

Рассмотрим работу с методом класса.

Перым аргументом (в скобках после имени метода) всегда должен идти «пустой» аргумент, который общепринято называть «self«.

Он служит для связи экземпляра (объекта) класса, который вызывает этот метод, с самим классом.

Так же — необходимо указывать self при вызове атрибутов класса:

print self.arg1

Сам интерпретатор будет читать данный вызов как:

print class_instance.arg1

т.к. на место self будет подставлен сам объект класса (class_instance), который вызывает данный аргумент (arg1).

Можно переопределить имя в описании метода, что бы упростить написание:

class thisIsClass:
        arg1 = 'string'
        arg2 = 100
        def method(self):
                a1 = self.arg1
                a2 = self.arg2
                print 'nRunning method:'
                print a1
                print a2

И далее в классе  и его объектах использовать аргументы a1 и a2, вместо self.arg1 и self.arg2.

Работа  с аргументами

Для передачи новых значений методу класса — ему можно определить несколько дополнительных аргументов:

class thisIsClass:
        # зададим два аргумента
        arg1 = 'string'
        arg2 = 100

        # создаём два новых агрумента - arg3 и arg4
        def method(self, arg3, arg4):
                # инициализируем их
                self.a3 = arg3
                self.a4 = arg4
                print self.a3
                print self.a4

# создадём экземпляр (или "объект") класса
class_instance = thisIsClass()

# вызываем два аргумента экземпляра класса
print 'Printing static arguments:'
print class_instance.arg1
print class_instance.arg2

print 'nPrinting method additional arguments:'
# вызываем объект, и передаём ему
# два дополнительных (self не учитывается) аргумента
class_instance.method('This is arg3', 'This is arg4')

Результат:

 ./class.py
Printing static arguments:
string
100

Printing method additional arguments:
This is arg3
This is arg4

Можно так же переопределить уже заданные аргументы:

class thisIsClass:
        # зададим два аргумента
        arg1 = 'string'
        arg2 = 100

        # зададим два аргумента - changearg1, changearg2
        def method(self, changearg1, changearg2):
                # переопределяем уже созданные аргументы arg1 и arg2
                self.arg1 = changearg1
                self.arg2 = changearg2
                print self.arg1
                print self.arg2

# создадём экземпляр (или "объект") класса
class_instance = thisIsClass()

# вызываем два аргумента экземпляра класса
print 'Printing static arguments:'
print class_instance.arg1
print class_instance.arg2

print 'nPrinting method additional arguments:'
# вызываем объект, и передаём ему
# два дополнительных (self не учитывается) аргумента
class_instance.method('This is changed argument 1', 'This is achanged argument 2')

Что вернёт нам такой результат:

 ./class.py
Printing static arguments:
string
100

Printing method additional arguments:
This is changed argument 1
This is achanged argumen 2

Или более наглядно — сделать так:

class thisIsClass:
        # зададим два аргумента
        arg1 = 'string'
        arg2 = 100

        # зададим два аргумента - changearg1, changearg2
        def method(self, changearg1, changearg2):
                # переопределяем уже созданные аргументы arg1 и arg2
                self.arg1 = changearg1
                self.arg2 = changearg2

# создадём экземпляр (или "объект") класса
class_instance = thisIsClass()

# вызываем два аргумента экземпляра класса
print 'Printing static arguments:'
print class_instance.arg1
print class_instance.arg2

# вызываем объект, и передаём ему два дополнительных (self не учитывается) аргумента
class_instance.method('This is changed argument 1', 'This is achanged argument 2')

# вызываем два измененных аргумента экземпляра класса
print 'Printing changed arguments:'
print class_instance.arg1
print class_instance.arg2

Что приведёт к тому же результату.

Кроме того, объекту класса можно присваивать новые аргументы, которые не обозначены в самом классе:

class thisIsClass:
 # зададим два аргумента
 arg1 = 'string'
 arg2 = 100

 # зададим два аргумента - changearg1, changearg2
 def method(self, changearg1, changearg2):
 # переопределяем уже созданные аргументы arg1 и arg2
 self.arg1 = changearg1
 self.arg2 = changearg2

# создадём экземпляр (или "объект") класса
class_instance = thisIsClass()

# вызываем два аргумента экземпляра класса
print 'Printing static arguments:'
print class_instance.arg1
print class_instance.arg2

# вызываем объект, и передаём ему два дополнительных (self не учитывается) аргумента
class_instance.method('This is changed argument 1', 'This is achanged argument 2')

# вызываем два измененных аргумента экземпляра класса
print 'Printing changed arguments:'
print class_instance.arg1
print class_instance.arg2

print 'nPrinting new object argument:'
# создаём объект класса с новым аргументом arg3
class_instance.arg3 = 'This is arg3'
print class_instance.arg3
$ ./class.py
Printing static arguments:
string
100
Printing changed arguments:
This is changed argument 1
This is achanged argument 2

Printing new object argument:
This is arg3

Специальные методы классов — метод __doc__

Как уже упоминалось в начале — строки, заключённые в тройные кавычки в классе будут применятся в его встроенном методе __doc__:

class thisIsClass:
        '''This is class documentation'''
        # зададим два аргумента
        arg1 = 'string'
        arg2 = 100

        # зададим два аргумента - changearg1, changearg2
        def method(self, changearg1, changearg2):
                # переопределяем уже созданные аргументы arg1 и arg2
                self.arg1 = changearg1
                self.arg2 = changearg2

# создадём экземпляр (или "объект") класса
class_instance = thisIsClass()

print class_instance.__doc__

Результат:

$ ./class.py
This is class documentation

Специальные методы классов — метод __init__

Метод __init__ будет вызываться каждый раз при создании нового объекта класса.

Таким образом — нет необходимости отдельного вызывать объект класса с методом, что бы передать новые аргументы:

class thisIsClass:
        '''This is class documentation'''
        # зададим два аргумента
        arg1 = 'string'
        arg2 = 100

        # зададим два аргумента - changearg1, changearg2
        def __init__(self, changearg1, changearg2):
                # переопределяем уже созданные аргументы arg1 и arg2
                self.arg1 = changearg1
                self.arg2 = changearg2

# создадём экземпляр (или "объект") класса
class_instance = thisIsClass('This is first argument', 'This is second argument')

print 'Printing arguments from __init__:'
print (class_instance.arg1, class_instance.arg2)

Результат:

$ ./class.py
Printing arguments from __init__:
('This is first argument', 'This is second argument')

Однако, если вызывать такой объект класса, но не передать ему при создании аргументы — будет вызвана ошибка:

class thisIsClass:
        '''This is class documentation'''
        # зададим два аргумента
        arg1 = 'string'
        arg2 = 100

        # зададим два аргумента - changearg1, changearg2
        def __init__(self, changearg1, changearg2):
                # переопределяем уже созданные аргументы arg1 и arg2
                self.arg1 = changearg1
                self.arg2 = changearg2

# создадём экземпляр (или "объект") класса
# без передачи аргументов
class_instance = thisIsClass()

print 'Printing arguments from __init__:'
print (class_instance.arg1, class_instance.arg2)

Результат:

$ ./class.py
Traceback (most recent call last):
  File "./class.py", line 17, in <module>
    class_instance = thisIsClass()
TypeError: __init__() takes exactly 3 arguments (1 given)

Заметьте — в описании ошибки говорится что «метод __init__ принимает 3 аргумента, но только 1 передан» — этот 1 и есть аргумент self, о котором говорилось выше.

Что бы избежать этого — можно задать аргументы по-умолчанию:

class thisIsClass:
        '''This is class documentation'''
        # зададим два аргумента
        arg1 = 'string'
        arg2 = 100

        # зададим два аргумента - changearg1, changearg2
        # и после символа = задаём значения по-умолчанию
        def __init__(self, changearg1='Default value 1', changearg2='Default value 2'):
                # переопределяем уже созданные аргументы arg1 и arg2
                self.arg1 = changearg1
                self.arg2 = changearg2

# создадём пустой экземпляр (или "объект") класса
class_instance_def = thisIsClass()

print 'nPrinting default arguments from __init__:'
print (class_instance_def.arg1, class_instance_def.arg2)

# создадём экземпляр (или "объект") класса с аргументами
class_instance_changed = thisIsClass('This is first argument', 'This is second argument')

print 'nPrinting changed arguments from __init__:'
print (class_instance_changed.arg1, class_instance_changed.arg2)

Результат:

$ ./class.py

Printing default arguments from __init__:
('Default value 1', 'Default value 2')

Printing changed arguments from __init__:
('This is first argument', 'This is second argument')

 Импорт классов

Предположим, наш файл с описанием класса называется classfile.py и содержит почти тот же код, кроме создания объекта класса и вызовов:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

class thisIsClass:
        '''This is class documentation'''
        # зададим два аргумента
        arg1 = 'string'
        arg2 = 100

        # зададим два аргумента - changearg1, changearg2
        # и после символа = задаём значения по-умолчанию
        def __init__(self, changearg1='Default value 1', changearg2='Default value 2'):
                # переопределяем уже созданные аргументы arg1 и arg2
                self.arg1 = changearg1
                self.arg2 = changearg2

Создадим новый файл — script.py, который будет содержать такой код:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# импортируем файл с описанием класса
# который по сути является модулем
import classfile

# создадём пустой экземпляр (или "объект") класса
# с указанием имени модуля
class_instance_def = classfile.thisIsClass()

print 'nPrinting default arguments from __init__:'
print (class_instance_def.arg1, class_instance_def.arg2)

# создадём экземпляр (или "объект") класса с аргументами
# и тоже указываем имя модуля
class_instance_changed = classfile.thisIsClass('This is first argument', 'This is second argument')

print 'nPrinting changed arguments from __init__:'
print (class_instance_changed.arg1, class_instance_changed.arg2)

Что бы импортировать не все классы из модуля, а только один — используем оператор from:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# импортируем класс из модуля classfile
from classfile import thisIsClass

# создадём пустой экземпляр (или "объект") класса
# теперь имя модуля можно не указывать
# т.к. класс был импортирован "напрямую"
class_instance_def = thisIsClass()

print 'nPrinting default arguments from __init__:'
print (class_instance_def.arg1, class_instance_def.arg2)

# создадём экземпляр (или "объект") класса с аргументами
# тоже без указания имени модуля
class_instance_changed = thisIsClass('This is first argument', 'This is second argument')

print 'nPrinting changed arguments from __init__:'
print (class_instance_changed.arg1, class_instance_changed.arg2)

Оба варианта нам дадут одинаковый результат:

$ ./script.py

Printing default arguments from __init__:
('Default value 1', 'Default value 2')

Printing changed arguments from __init__:
('This is first argument', 'This is second argument')

Это лишь малая часть о классах в Python. В будущем — рассмотрим такие понятия как «полиформизм«, «инкапсуляция«, «композиция» и, конечно же, «наследование«.