|
Самоучитель PythonВыпуск 2Дмитрий Мусинмая 07, 2017
Подключение модуля из стандартной библиотеки Подключить модуль можно с помощью инструкции import. К примеру, подключим мо- дуль os для получения текущей директории: >>> import os >>> os getcwd() 'C:\\Python33' После ключевого слова import указывается название модуля. Одной инструкцией можно подключить несколько модулей, хотя этого не рекомендуется делать, так как это снижает читаемость кода. Импортируем модули time и random >>> import time , random >>> time time() 1376047104.056417 >>> random random() 0.9874550833306869 105 Самоучитель Python, Выпуск 0.2После импортирования модуля его название становится переменной, через которую можно получить доступ к атрибутам модуля. Например, можно обратиться к константе e, расположенной в модуле math : >>> import math >>> math e 2.718281828459045 Стоит отметить, что если указанный атрибут модуля не будет найден, возбудится ис- ключение AttributeError. А если не удастся найти модуль для импортирования, то ImportError. >>> import notexist Traceback (most recent call last): File "", line 1, in import notexist ImportError : No module named 'notexist' >>> import math >>> math Ё Traceback (most recent call last): File "", line 1, in math.Ё AttributeError : 'module' object has no attribute 'Ё' Использование псевдонимовЕсли название модуля слишком длинное, или оно вам не нравится по каким-то другим причинам, то для него можно создать псевдоним, с помощью ключевого слова as. >>> import math as m >>> m e 2.718281828459045 Теперь доступ ко всем атрибутам модуля math осуществляется только с помощью пере- менной m, а переменной math в этой программе уже не будет (если, конечно, вы после этого не напишете import math, тогда модуль будет доступен как под именем m, так и под именем math). Инструкция fromПодключить определенные атрибуты модуля можно с помощью инструкции from. Она имеет несколько форматов: from < Название модуля > import < Атрибут 1 > [ as < Псевдоним 1 > ], [ < Атрибут 2 > [ as ˓→ < Псевдоним 2 > ] ] from < Название модуля > import * 27.2. Использование псевдонимов106 Самоучитель Python, Выпуск 0.2 Первый формат позволяет подключить из модуля только указанные вами атрибуты. Для длинных имен также можно назначить псевдоним, указав его после ключевого слова as. >>> from math import e, ceil as c >>> e 2.718281828459045 >>> c( 4.6 ) 5 Импортируемые атрибуты можно разместить на нескольких строках, если их много, для лучшей читаемости кода: >>> from math import (sin, cos, tan, atan) Второй формат инструкции from позволяет подключить все (точнее, почти все) перемен- ные из модуля. Для примера импортируем все атрибуты из модуля sys : >>> from sys import * >>> version '3.3.2 (v3.3.2:d047928ae3f6, May 16 2013, 00:03:43) [MSC v.1600 32 bit (Intel)]' >>> version_info sys.version_info(major=3, minor=3, micro=2, releaselevel='final', serial=0) Следует заметить, что не все атрибуты будут импортированы. Если в модуле определена переменная __all__ (список атрибутов, которые могут быть подключены), то будут под- ключены только атрибуты из этого списка. Если переменная __all__ не определена, то бу- дут подключены все атрибуты, не начинающиеся с нижнего подчёркивания. Кроме того, необходимо учитывать, что импортирование всех атрибутов из модуля может нарушить пространство имен главной программы, так как переменные, имеющие одинаковые име- на, будут перезаписаны. Создание своего модуля на Python Теперь пришло время создать свой модуль. Создадим файл mymodule.py, в которой опре- делим какие-нибудь функции: def hello (): print ( 'Hello, world!' ) def fib (n): a = b = 1 for i in range (n - 2 ): a, b = b, a + b return b Теперь в этой же папке создадим другой файл, например, main.py: 27.4. Создание своего модуля на Python 107
Самоучитель Python, Выпуск 0.2import mymodule mymodule hello() print (mymodule fib( 10 )) Выведет: Hello, world! 55 Поздравляю! Вы сделали свой модуль! Напоследок отвечу ещё на пару вопросов, связан- ных с созданием модулей: Как назвать модуль?Помните, что вы (или другие люди) будут его импортировать и использовать в качестве переменной. Модуль нельзя именовать также, как и ключевое слово (их список можно посмотреть тут ). Также имена модулей нельзя начинать с цифры. И не стоит называть модуль также, как какую-либо из встроенных функций . То есть, конечно, можно, но это создаст большие неудобства при его последующем использовании. Куда поместить модуль?Туда, где его потом можно будет найти. Пути поиска модулей указаны в переменной sys.path. В него включены текущая директория (то есть модуль можно оставить в пап- ке с основной программой), а также директории, в которых установлен python. Кроме того, переменную sys.path можно изменять вручную, что позволяет положить модуль в любое удобное для вас место (главное, не забыть в главной программе модифицировать sys.path). Можно ли использовать модуль как самостоятельную программу?Можно. Однако надо помнить, что при импортировании модуля его код выполняется полностью, то есть, если программа что-то печатает, то при её импортировании это будет напечатано. Этого можно избежать, если проверять, запущен ли скрипт как программа, или импортирован. Это можно сделать с помощью переменной __name__, которая опре- делена в любой программе, и равна “__main__”, если скрипт запущен в качестве главной программы, и имя, если он импортирован. Например, mymodule.py может выглядеть вот так: def hello (): print ( 'Hello, world!' ) def fib (n): a = b = 1 for i in range (n - 2 ): 27.4. Создание своего модуля на Python108 Самоучитель Python, Выпуск 0.2 a, b = b, a + b return b if __name__ == "__main__" : hello() for i in range ( 10 ): print (fib(i)) 27.4. Создание своего модуля на Python 109
Глава 28 Объектно-ориентированное программирование. Общее представление Сегодня мы поговорим об объектно-ориентированном программировании и о его приме- нении в python. Объектно-ориентированное программирование (ООП) — парадигма программирова- ния, в которой основными концепциями являются понятия объектов и классов. Класс — тип, описывающий устройство объектов. Объект — это экземпляр класса. Класс можно сравнить с чертежом, по которому создаются объекты. Python соответствует принципам объектно-ориентированного программирования. В python всё является объектами - и строки, и списки, и словари, и всё остальное. Но возможности ООП в python этим не ограничены. Программист может написать свой тип данных (класс), определить в нём свои методы. Это не является обязательным - мы можем пользоваться только встроенными объектами. Однако ООП полезно при долгосрочной разработке программы несколькими людьми, так как упрощает понимание кода. Приступим теперь собственно к написанию своих классов на python. Попробуем опреде- лить собственный класс: >>> # Пример самого простейшего класса class A : pass Теперь мы можем создать несколько экземпляров этого класса: >>> a = A() >>> b = A() >>> a arg = 1 # у экземпляра a появился атрибут arg, равный 1 110
Самоучитель Python, Выпуск 0.2>>> b arg = 2 # а у экземпляра b - атрибут arg, равный 2 >>> print (a arg) 1 Классу возможно задать собственные методы: >>> class A : def g ( self ): # self - обязательный аргумент, содержащий в себе экземпляр # класса, передающийся при вызове метода, # поэтому этот аргумент должен присутствовать# во всех методах класса. return 'hello world' >>> a = A() >>> a g() 'hello world' И напоследок еще один пример: >>> class B : arg = 'Python' # Все экземпляры этого класса будут иметь атрибут arg, # равный "Python" # Но впоследствии мы его можем изменить def g ( self ): return self arg >>> b = B() >>> b g() 'Python' >>> B g(b) 'Python' >>> b arg = 'spam' >>> b g() 'spam' 111 Глава 29 Инкапсуляция, наследование, полиморфизм Недавно мы говорили об основах объектно-ориентированного программирования в python , теперь продолжим эту тему и поговорим о таких понятиях ООП, как инкапсу- ляция, наследование и полиморфизм. Инкапсуляция Инкапсуляция — ограничение доступа к составляющим объект компонентам (методам и переменным). Инкапсуляция делает некоторые из компонент доступными только внут- ри класса. Инкапсуляция в Python работает лишь на уровне соглашения между программистами о том, какие атрибуты являются общедоступными, а какие — внутренними. Одиночное подчеркивание в начале имени атрибута говорит о том, что переменная или метод не предназначен для использования вне методов класса, однако атрибут доступен по этому имени. class A: def _private(self): print("Это приватный метод!") >>> a = A() >>> a._private() Это приватный метод! Двойное подчеркивание в начале имени атрибута даёт большую защиту: атрибут стано- вится недоступным по этому имени. 112
Самоучитель Python, Выпуск 0.2>>> class B : def __private ( self ): print ( "Это приватный метод!" ) >>> b = B() >>> b __private() Traceback (most recent call last): File " " , line 1 , in AttributeError : 'B' object has no attribute '__private' Однако полностью это не защищает, так как атрибут всё равно остаётся доступным под именем _ИмяКласса__ИмяАтрибута: >>> b _B__private() Это приватный метод! Наследование Наследование подразумевает то, что дочерний класс содержит все атрибуты родитель- ского класса, при этом некоторые из них могут быть переопределены или добавлены в дочернем. Например, мы можем создать свой класс, похожий на словарь : >>> class Mydict ( dict ): def get ( self , key, default = 0 ): return dict get( self , key, default) >>> a = dict (a = 1 , b = 2 ) >>> b = Mydict(a = 1 , b = 2 ) Класс Mydict ведёт себя точно так же, как и словарь, за исключением того, что метод get по умолчанию возвращает не None, а 0. >>> b[ 'c' ] = 4 >>> print (b) {'a': 1, 'c': 4, 'b': 2} >>> print (a get( 'v' )) None >>> print (b get( 'v' )) 0 Полиморфизм Полиморфизм - разное поведение одного и того же метода в разных классах. Например, мы можем сложить два числа, и можем сложить две строки. При этом получим разный результат, так как числа и строки являются разными классами. 29.2. Наследование 113
Самоучитель Python, Выпуск 0.2 >>> 1 + 1 2 >>> "1" + "1" '11' 29.3. Полиморфизм 114
Глава 30 Перегрузка операторов Перегрузка операторов — один из способов реализации полиморфизма, когда мы можем задать свою реализацию какого-либо метода в своём классе. Например, у нас есть два класса: class A : def go ( self ): print ( 'Go, A!' ) class B (A): def go ( self , name): print ( 'Go, {} !' format(name)) В данном примере класс B наследует класс A, но переопределяет метод go, поэтому он имеет мало общего с аналогичным методом класса A. Однако в python имеются методы, которые, как правило, не вызываются напрямую, а вы- зываются встроенными функциями или операторами. Например, метод __init__ перегружает конструктор класса. Конструктор - создание экзем- пляра класса. >>> class A : def __init__ ( self , name): self name = name >>> a = A( 'Vasya' ) >>> print (a name) Vasya Собственно, далее пойдёт список таких “магических” методов. 115
Самоучитель Python, Выпуск 0.2 __new__(cls[, ...]) — управляет созданием экземпляра. В качестве обязательного аргумента принимает класс (не путать с экземпляром). Должен возвращать экземпляр класса для его последующей его передачи методу __init__. __init__(self[, ...]) - как уже было сказано выше, конструктор. __del__(self ) - вызывается при удалении объекта сборщиком мусора. __repr__(self ) - вызывается встроенной функцией repr; возвращает “сырые” данные, ис- пользующиеся для внутреннего представления в python. __str__(self ) - вызывается функциями str, print и format. Возвращает строковое представ- ление объекта. __bytes__(self ) - вызывается функцией bytes при преобразовании к байтам __format__(self, format_spec) - используется функцией format (а также методом format у строк). __lt__(self, other) - x < y вызывает x.__lt__(y). __le__(self, other) - x <= y вызывает x.__le__(y). __eq__(self, other) - x == y вызывает x.__eq__(y). __ne__(self, other) - x != y вызывает x.__ne__(y) __gt__(self, other) - x > y вызывает x.__gt__(y). __ge__(self, other) - x >= y вызывает x.__ge__(y). __hash__(self ) - получение хэш-суммы объекта, например, для добавления в словарь. __bool__(self ) - вызывается при проверке истинности. Если этот метод не определён, вы- зывается метод __len__ (объекты, имеющие ненулевую длину, считаются истинными). __getattr__(self, name) - вызывается, когда атрибут экземпляра класса не найден в обыч- ных местах (например, у экземпляра нет метода с таким названием). __setattr__(self, name, value) - назначение атрибута. __delattr__(self, name) - удаление атрибута (del obj.name). __call__(self[, args...]) - вызов экземпляра класса как функции __len__(self ) - длина объекта. __getitem__(self, key) - доступ по индексу (или ключу). __setitem__(self, key, value) - назначение элемента по индексу. __delitem__(self, key) - удаление элемента по индексу. __iter__(self ) - возвращает итератор для контейнера. __reversed__(self ) - итератор из элементов, следующих в обратном порядке. __contains__(self, item) - проверка на принадлежность элемента контейнеру (item in self ). 116
Самоучитель Python, Выпуск 0.2Перегрузка арифметических операторов__add__(self, other) - сложение. x + y вызывает x.__add__(y). __sub__(self, other) - вычитание (x - y). __mul__(self, other) - умножение (x * y). __truediv__(self, other) - деление (x / y). __floordiv__(self, other) - целочисленное деление (x // y). __mod__(self, other) - остаток от деления (x % y). __divmod__(self, other) - частное и остаток (divmod(x, y)). __pow__(self, other[, modulo]) - возведение в степень (x ** y, pow(x, y[, modulo])). __lshift__(self, other) - битовый сдвиг влево (x << y). __rshift__(self, other) - битовый сдвиг вправо (x >> y). __and__(self, other) - битовое И (x & y). __xor__(self, other) - битовое ИСКЛЮЧАЮЩЕЕ ИЛИ (x ^ y). __or__(self, other) - битовое ИЛИ (x | y). Пойдём дальше. __radd__(self, other), __rsub__(self, other), __rmul__(self, other), __rtruediv__(self, other), __rfloordiv__(self, other), __rmod__(self, other), __rdivmod__(self, other), __rpow__(self, other), __rlshift__(self, other), __rrshift__(self, other), __rand__(self, other), __rxor__(self, other), __ror__(self, other) - делают то же самое, что и арифметические операторы, перечислен- ные выше, но для аргументов, находящихся справа, и только в случае, если для левого операнда не определён соответствующий метод. Например, операция x + y будет сначала пытаться вызвать x.__add__(y), и только в том слу- чае, если это не получилось, будет пытаться вызвать y.__radd__(x). Аналогично для осталь- ных методов. 30.1. Перегрузка арифметических операторов117 Самоучитель Python, Выпуск 0.2Идём дальше. __iadd__(self, other) - +=. __isub__(self, other) - -=. __imul__(self, other) - *=. __itruediv__(self, other) - /=. __ifloordiv__(self, other) - //=. __imod__(self, other) - %=. __ipow__(self, other[, modulo]) - **=. __ilshift__(self, other) - <<=. __irshift__(self, other) - >>=. __iand__(self, other) - &=. __ixor__(self, other) - ^=. __ior__(self, other) - |=. __neg__(self ) - унарный -. __pos__(self ) - унарный +. __abs__(self ) - модуль (abs()). __invert__(self ) - инверсия (). __complex__(self ) - приведение к complex. __int__(self ) - приведение к int. __float__(self ) - приведение к float. __round__(self[, n]) - округление. __enter__(self ), __exit__(self, exc_type, exc_value, traceback) - реализация менеджеров кон- текста. Рассмотрим некоторые из этих методов на примере двухмерного вектора, для которого переопределим некоторые методы: import math class Vector2D : def __init__ ( self , x, y): self x = x self y = y def __repr__ ( self ): return 'Vector2D( {} , {} )' format( self x, self y) def __str__ ( self ): return '( {} , {} )' format( self x, self y) |
|
|