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

Автор: | 18/08/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. В будущем – рассмотрим такие понятия как “полиформизм“, “инкапсуляция“, “композиция” и, конечно же, “наследование“.