Вы находитесь на странице: 1из 13

8. Менеджер контекстів. "Магічні методи".

Конструкция with ... as используется для оборачивания выполнения блока инструкций


менеджером контекста. Иногда это более удобная конструкция, чем try...except...finally.
Синтаксис конструкции with ... as:

"with" expression ["as" target] ("," expression ["as" target])* ":"


suite

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


1. Выполняется выражение в конструкции with ... as.
2. Загружается специальный метод __exit__ для дальнейшего использования.
3. Выполняется метод __enter__. Если конструкция with включает в себя слово as, то
возвращаемое методом __enter__ значение записывается в переменную.
4. Выполняется suite.
5. Вызывается метод __exit__, причём неважно, выполнилось ли suite или произошло
исключение. В этот метод передаются параметры исключения, если оно произошло, или во
всех аргументах значение None, если исключения не было.

Что такое магические методы? Это специальные методы обектов, с помощью которых вы
можете добавить в ваши классы «магию». Они всегда обрамлены двумя нижними
подчеркиваниями (например, __init__ или __lt__).

9. Декторатор. Замикання.
Декораторы — это, по сути, "обёртки", которые дают нам возможность изменить поведение
функции, не изменяя её код.

@my_shiny_new_decorator
... def another_stand_alone_function():
... print("Оставь меня в покое")
...
>>> another_stand_alone_function()

То есть, декораторы в python — это просто синтаксический сахар для конструкций вида:
another_stand_alone_function = my_shiny_new_decorator(another_stand_alone_function)

Для начала обратимся к википедии: “замыкание (closure) в программировании — это


функция, в теле которой присутствуют ссылки на переменные, объявленные вне тела этой
функции в окружающем коде и не являющиеся ее параметрами.” Перед тем как перейти к
рассмотрению примеров реализации замыканий на Python, для начал вспомним тему
“область видимости переменных”. Обычно, по области видимости, переменные делят на
глобальные и локальные. Глобальные существует в течении всего времени выполнения
программы, а локальные создаются внутри методов, функций и прочих блоках кода, при
этом, после выхода из такого блока переменная удаляется из памяти.
Что касается Python, то тут выделяют четыре области видимости для переменных (с вашего
позволения я буду использовать английские термины).
 Local
Эту область видимости имеют переменные, которые создаются и используются внутри
функций.
Пример.

>>> def add_two(a):


x=2
return a + x

>>> add_two(3)
5

>>> print(x)
Traceback (most recent call last):
 File "<pyshell#5>", line 1, in <module>
   print(x)
NameError: name 'x' is not defined

В данной программе объявлена функция add_two(), которая прибавляет двойку к


переданному ей числу и возвращает полученный результат. Внутри этой функции
используется переменная x, доступ к которой снаружи невозможен. К тому же, эта
переменная удаляется из памяти каждый раз (во всяком случае, должна удаляться), когда
завершается add_two().
 Enclosing
Суть данной области видимости в том, что внутри функции могут быть вложенные функции и
локальные переменные, так вот локальная переменная функции для ее вложенной функции
находится в enclosing области видимости.
Пример.

>>> def add_four(a):


x=2
def add_some():
print("x = " + str(x))
return a + x
return add_some()

>>> add_four(5)
x=2
7

В данном случае переменная x имеет область видимости enclosing для функции add_some().


 Global
Переменные области видимости global – это глобальные переменные уровня модуля
(модуль – это файл с расширением .py).
Пример.

>>> x = 4
>>> def fun():
print(x+3)

>>> fun()
7
В приведенном выше коде переменная x – это global переменная. Доступ к ней можно
получить из любой функции объявленной в данном модуле. Но если мы этот модуль
импортируем в каком-то другом модуле, то x для него уже не будет переменной
уровня global.
 Built-in
Уровень Python интерпретатора. В рамках этой области видимости находятся
функции open, len и т.п., также туда входят исключения. Эти сущности доступны в любом
модуле Python и не требуют предварительного импорта. Built-in – это максимально широкая
область видимости.

10. Багатопоточність. GIL.


Python модули
Python предлагает два модуля для реализации потоков в программах.
 thread
 threading
Для вашей информации, модуль thread устарел в Python 3 и переименован в
модуль _thread для обратной совместимости. Но мы объясним оба метода, потому что
многие пользователи все еще используют устаревшие версии Python.
Основное различие между этими двумя модулями состоит в том, что модуль реализует поток
как функцию. С другой стороны, модуль предлагает объектно-ориентированный подход,
позволяющий создавать потоки.
Как использовать модуль Thread для создания потоков?
Если вы решили применить модуль thread в своей программе, используйте следующий
метод для создания потоков.
thread.start_new_thread ( function, args[, kwargs] )
Этот метод является довольно простым и эффективным способом создания потоков. Вы
можете использовать его для запуска программ в Linux и Windows.
Этот метод запускает новый поток и возвращает его идентификатор. Он вызовет функцию,
указанную в качестве параметра «function» с переданным списком аргументов. Когда
возвращается функция, поток молча завершает работу.
Здесь args - это кортеж аргументов; используйте пустой кортеж для вызова без каких-либо
аргументов. Необязательный аргумент указывает словарь аргументов с ключевыми словами.
Если функция завершается с необработанным исключением, выводится трассировка стека, а
затем поток выходит (это не влияет на другие потоки, они продолжают работать).
Используйте приведенный ниже код, чтобы узнать больше о многопоточности.
Базовый пример Multithreading Python
# Пример многопоточности Python.
# 1. Рассчитать факториал с помощью рекурсии.
# 2. Вызовите факториальную функцию, используя поток.

from thread import start_new_thread

threadId = 1

def factorial(n):
global threadId
if n < 1:
print "%s: %d" % ("Thread", threadId )
threadId += 1
return 1
else:
returnNumber = n * factorial( n - 1 ) # рекусрсивынй вызов
print(str(n) + '! = ' + str(returnNumber))
return returnNumber

start_new_thread(factorial,(5, ))
start_new_thread(factorial,(4, ))

c = raw_input("Waiting for threads to return...\n")


Вы можете запустить приведенный выше код в своем локальном терминале или
использовать любой онлайн-терминал. Как только вы запустите эту программу, она выдаст
следующее.
Waiting for threads to return...
Thread: 1
1! = 1
2! = 2
3! = 6
4! = 24
Thread: 2
1! = 1
2! = 2
3! = 6
4! = 24
5! = 120
Как использовать модуль Threading для создания потоков?
Последний модуль threading предоставляет богатые возможности и большую поддержку
потоков, чем устаревший модуль thread, описанный в предыдущем разделе.
Модуль threading является отличным примером многопоточности Python.
Модуль объединяет все методы модуля thread и предоставляет несколько дополнительных
методов.
 threading.activeCount(): находит общее число активных объектов потока.
 threading.currentThread(): его можно использовать для определения количества
объектов потока в элементе управления потоком вызывающей стороны.
 threading.enumerate(): он предоставит вам полный список объектов потока, которые в
данный момент активны.
Помимо описанных выше методов, модуль также представляет класс Thread, который вы
можете попробовать реализовать в потоках. Это объектно-ориентированный вариант
многопоточности Python.
Класс имеет следующие методы.
Методы
Описание метода
класса
run(): Это функция точки входа для любого потока.
start(): запускает поток при вызове метода run.
join([time]): позволяет программе ожидать завершения потоков.
isAlive(): проверяет активный поток.
getName(): извлекает имя потока.
setName(): обновляет имя потока.
При желании вы можете обратиться к родной документации Python, чтобы глубже изучить
функциональность модуля threading.
Шаги для реализации потоков с помощью модуля Threading
Вы можете выполнить следующие шаги для создания нового потока с помощью модуля .
 Создайте класс наследовав его от Thread.
 Переопределите метод __ init __ (self [, args]) для предоставления аргументов в
соответствии с требованиями.
 Затем переопределите метод run(self [, args]), чтобы создать бизнес-логику потока.
Как только вы определили новый подкласс Thread, вы должны создать его экземпляр, чтобы
начать новый поток. Затем вызовите метод для его запуска. В конечном итоге он вызовет
метод для выполнения бизнес-логики.
Python Multithreading - синхронизация потоков
Модуль имеет встроенную функциональность для реализации блокировки, которая
позволяет синхронизировать потоки. Блокировка необходима для контроля доступа к общим
ресурсам для предотвращения повреждения или пропущенных данных.
Вы можете вызвать метод Lock(), чтобы применить блокировки, он возвращает новый объект
блокировки. Затем вы можете вызвать метод захвата (блокировки) объекта блокировки,
чтобы заставить потоки работать синхронно.
Необязательный параметр блокировки указывает, ожидает ли поток получения блокировки.
 В случае, если блокировка установлена на ноль, поток немедленно возвращается с
нулевым значением, если блокировка не может быть получена, и 1, если блокировка
получена.
 В случае, если для блокировки задано значение 1, поток блокируется и ожидает
снятия блокировки.
GIL. в любой момент может выполняться только один поток Python. Глобальная блокировка
интерпретатора — GIL — тщательно контролирует выполнение тредов. GIL гарантирует
каждому потоку эксклюзивный доступ к переменным интерпретатора (и соответствующие
вызовы C-расширений работают правильно).

Принцип работы прост. Потоки удерживают GIL, пока выполняются. Однако они
освобождают его при блокировании для операций ввода-вывода. Каждый раз, когда поток
вынужден ждать, другие, готовые к выполнению, потоки используют свой шанс запуститься.

11. Робота з датою і часом: стандартні можливості та Pendulum.


Python содержит несколько инструментов, которые разработчик может использовать
для работы с датой и временем. В данном разделе статье мы рассмотрим
модули datetime и time. Мы изучим принципы их работы и способы их применения. Начнем
с модуля datetime.
Модуль datetime
Мы изучим следующие классы модуля:
 datetime.date
 datetime.timedelta
 datetime.datetime
Благодаря этим классам мы в будущем сможем работать с большей частью случаев, в
которых нам понадобятся объекты date и datetime. Также существует класс tzinfo, который
применяется для работы с часовыми поясами. Для дополнительной информации об этом
классе вы можете обратиться к документации Python.
datetime.date
Python может представлять даты различными способами. Для начала, рассмотрим
формат datetime.date, так как это один из самых простых объектов date.
print(datetime.date(2012, 12, 14)) # datetime.date(2012, 12, 14)
datetime.datetime
Объект datetime.datetime содержит всю информацию
объектов datetime.date плюс datetime.time. Давайте приведем несколько примеров, для
лучшего понимания разницы между этим объектом, и объектом datetime.date.
import datetime
 
print(datetime.date.today()) # datetime.date(2017, 4, 5)

12. Створення класів та інкапсуляція.


13. Наслідування та поліморфізм.
Инкапсуляция
Инкапсуляция — ограничение доступа к составляющим объект компонентам (методам и
переменным). Инкапсуляция делает некоторые из компонент доступными только внутри
класса.
Инкапсуляция в Python работает лишь на уровне соглашения между программистами о том,
какие атрибуты являются общедоступными, а какие — внутренними.
Одиночное подчеркивание в начале имени атрибута говорит о том, что переменная или
метод не предназначен для использования вне методов класса, однако атрибут доступен по
этому имени.

class A:
def _private(self):
print("Это приватный метод!")

>>> a = A()
>>> a._private()
Это приватный метод!

Двойное подчеркивание в начале имени атрибута даёт большую защиту: атрибут становится
недоступным по этому имени.
>>>
>>> class B:
... def __private(self):
... print("Это приватный метод!")
...
>>> b = B()
>>> b.__private()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
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

Полиморфизм
Полиморфизм - разное поведение одного и того же метода в разных классах. Например, мы
можем сложить два числа, и можем сложить две строки. При этом получим разный
результат, так как числа и строки являются разными классами.
>>>

>>> 1 + 1
2
>>> "1" + "1"
'11'

14. Static method vs class method.


Метод класса

Декоратор @classmethod - это встроенный декоратор функций, который является


выражением, которое вычисляется после определения вашей функции. Результат этой
оценки затеняет определение вашей функции.
Метод класса получает класс как неявный первый аргумент, так же, как метод экземпляра
получает экземпляр
Синтаксис:

класс C (объект):
    @classmethod
    def fun (cls, arg1, arg2, ...):
       ....
fun: функция, которую нужно преобразовать в метод класса
возвращает: метод класса для функции.
Метод класса - это метод, который привязан к классу, а не к объекту класса.
У них есть доступ к состоянию класса, так как он принимает параметр класса, который
указывает на класс, а не на экземпляр объекта.
Он может изменять состояние класса, которое будет применяться ко всем экземплярам
класса. Например, он может изменить переменную класса, которая будет применима ко
всем экземплярам.
Статический метод

Статический метод не получает неявный первый аргумент.


Синтаксис:

класс C (объект):
    @staticmethod
    def fun (arg1, arg2, ...):
        ...
возвращает: статический метод для функции fun.
Статический метод - это также метод, который связан с классом, а не с объектом класса.
Статический метод не может получить доступ или изменить состояние класса.
Он присутствует в классе, потому что имеет смысл, чтобы метод присутствовал в классе.
Метод класса против статического метода

Метод класса принимает cls в качестве первого параметра, в то время как статический метод
не нуждается в особых параметрах.
Метод класса может получить доступ или изменить состояние класса, в то время как
статический метод не может получить доступ или изменить его.
В общем, статические методы ничего не знают о состоянии класса. Это методы служебного
типа, которые принимают некоторые параметры и работают с этими параметрами. С другой
стороны, методы класса должны иметь класс в качестве параметра.
Мы используем декоратор @classmethod в python для создания метода класса и используем
декоратор @staticmethod для создания статического метода в python.
Когда использовать что?

Обычно мы используем метод класса для создания фабричных методов. Методы фабрики
возвращают объект класса (аналог конструктора) для разных вариантов использования.
Обычно мы используем статические методы для создания служебных функций.

Вам также может понравиться