На сайте Poromenos’ Stuff была
опубликована статья, в которой, в сжатой форме,
рассказывают об основах языка Python. Я предлагаю вам перевод этой статьи. Перевод не дословный. Я постарался подробнее объяснить некоторые моменты, которые могут быть непонятны.
Если вы собрались изучать язык Python, но не можете найти подходящего руководства, то эта
статья вам очень пригодится! За короткое время, вы сможете познакомиться с
основами языка Python. Хотя эта статья часто опирается
на то, что вы уже имеете опыт программирования, но, я надеюсь, даже новичкам
этот материал будет полезен. Внимательно прочитайте каждый параграф. В связи с
сжатостью материала, некоторые темы рассмотрены поверхностно, но содержат весь
необходимый метриал.
Основные свойства
Python не требует явного объявления переменных, является регистро-зависим (переменная var не эквивалентна переменной Var или VAR — это три разные переменные) объектно-ориентированным языком.
Синтаксис
Во первых стоит отметить интересную особенность Python. Он не содержит операторных скобок (begin..end в pascal или {..}в Си), вместо этого
Чтобы присвоить значение пременной используется знак «=», а для сравнения —
«==». Для увеличения значения переменной, или добавления к строке используется оператор «+=», а для уменьшения — «-=». Все эти операции могут взаимодействовать с большинством типов, в том числе со строками. Например
>>> myvar = 3
>>> myvar += 2
>>> myvar -= 1«»«Это многострочный комментарий
Строки заключенные в три двойные кавычки игнорируются»»»
>>> mystring = «Hello»
>>> mystring += » world.»
>>> print mystring
Hello world.
# Следующая строка меняет
значения переменных местами. (Всего одна строка!)
>>> myvar, mystring = mystring, myvar
Структуры данных
Python содержит такие структуры данных как списки (lists), кортежи (tuples) и словари (dictionaries). Списки — похожи на одномерные массивы (но вы можете использовать Список включающий списки — многомерный массив), кортежи — неизменяемые списки, словари — тоже списки, но индексы могут быть любого типа, а не только числовыми. «Массивы» в Python могут содержать данные любого типа, то есть в одном массиве может могут находиться числовые, строковые и другие типы данных. Массивы начинаются с индекса 0, а последний элемент можно получить по индексу -1 Вы можете присваивать переменным функции и использовать их соответственно.
>>> sample = [1, [«another», «list»], («a», «tuple»)] #Список состоит из целого числа, другого списка и кортежа
>>> mylist = [«List item 1», 2, 3.14] #Этот список содержит строку, целое и дробное число
>>> mylist[0] = «List item 1 again» #Изменяем первый (нулевой) элемент листа mylist>>> mylist[-1] = 3.14 #Изменяем последний элемент листа
>>> mydict = {«Key 1»: «Value 1», 2: 3, «pi»: 3.14} #Создаем словарь, с числовыми и целочисленным индексами
>>> mydict[«pi»] = 3.15 #Изменяем элемент словаря под индексом «pi».
>>> mytuple = (1, 2, 3) #Задаем кортеж
>>> myfunction = len #Python позволяет таким образом объявлять синонимы функции
>>> print myfunction(list)
3
Вы можете использовать часть массива, задавая первый и последний индекс через двоеточие «:». В таком случае вы получите часть массива, от первого индекса до второго не включительно. Если не указан первый элемент, то отсчет начинается с начала массива, а если не указан последний — то масив считывается до последнего элемента. Отрицательные значения определяют положение элемента с конца. Например:
>>> mylist = [«List item 1», 2, 3.14]
>>> print mylist[:] #Считываются все элементы массива
[‘List item 1’, 2, 3.1400000000000001]
>>> print mylist[0:2] #Считываются нулевой и первый элемент массива.
[‘List item 1’, 2]
>>> print mylist[-3:-1] #Считываются элементы от нулевого (-3) до второго (-1) (не включительно)
[‘List item 1’, 2]>>> print mylist[1:] #Считываются элементы от первого, до последнего
[2, 3.14]
Строки
Строки в Python обособляются кавычками двойными «»» или одинарными «’». Внутри двойных ковычек могут присутствовать одинарные или наоборот. К примеру строка «Он сказал ‘привет’!» будет выведена на экран как «Он сказал ‘привет’!». Если нужно использовать строку из несколько строчек, то эту строку надо начинать и заканчивать тремя двойными кавычками «»»»». Вы можете подставить в шаблон строки элементы из кортежа или словаря. Знак процента «%» между строкой и кортежем, заменяет в строке символы «%s» на элемент кортежа. Словари позволяют вставлять в строку элемент под заданным индексом. Для этого надо использовать в строке конструкцию «%(индекс)s». В этом случае вместо «%(индекс)s» будет подставлено значение словаря под заданным индексом.
>>>print «Name: %s\nNumber: %s\nString: %s» % (myclass.name, 3, 3 * «-«)
Name: Poromenos
Number: 3
String: —
strString = «»«Этот текст расположен
на нескольких строках»»»
>>> print «This %(verb)s a %(noun)s.» % {«noun»: «test», «verb»: «is»}
This is a test.
Операторы
Операторы while, if, for составляют операторы перемещения. Здесь нет аналога оператора select, так что придется обходиться
rangelist = range(10) #Получаем список из десяти цифр (от 0 до 9)
>>> print rangelist
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
for number in rangelist: #Пока переменная number (которая каждый раз увеличивается на единицу) входит в список…
# Проверяем входит ли переменная
# numbers в кортеж чисел (3, 4, 7, 9)
if number in (3, 4, 7, 9): #Если переменная number входит в кортеж (3, 4, 7, 9)…# Операция «break» обеспечивает
# выход из цикла в любой момент
break
else:
# «continue» осуществляет «прокрутку»
# цикла. Здесь это не требуется, так как после этой операции
# в любом случае программа переходит опять к обработке цикла
continue
else:
# «else» указывать необязательно. Условие выполняется
# если цикл не был прерван при помощи «break».
pass # Ничего не делать
if rangelist[1] == 2:«The second item (lists are 0-based) is 2»
elif rangelist[1] == 3:
print «The second item (lists are 0-based) is 3»
else:
print «Dunno»
while rangelist[1] == 1:
pass
Функции
Для объявления функции служит ключевое слово «def». Аргументы функции задаются в скобках после названия функции. Можно задавать необязательные аргументы, присваивая им значение по умолчанию. Функции могут возвращать кортежи, в таком случае надо писать возвращаемые значения через запятую. Ключевое слово «lambda» служит для объявления элементарных функций .
# arg2 и arg3 — необязательые аргументы, принимают значение объявленное по умолчни,
# если не задать им другое значение при вызове функци.
def myfunction(arg1, arg2 = 100, arg3 = «test»):
return arg3, arg2, arg1
#Функция вызывается со значением первого аргумента — «Argument 1», второго — по умолчанию, и третьего — «Named argument».
>>>ret1, ret2, ret3 = myfunction(«Argument 1», arg3 = «Named argument»)
# ret1, ret2 и ret3 принимают значения «Named argument», 100, «Argument 1» соответственно
>>> print ret1, ret2, ret3
Named argument 100 Argument 1
# Следующая запись эквивалентна deff(x): return x + 1
functionvar = lambda x: x + 1
>>> print functionvar(1)
2
Классы
Язык Python ограничен в множественном наследовании в классах. Внутренние переменные и внутренние методы классов начинаются с двух знаков нижнего подчеркивания «__» (например «__myprivatevar»). Мы можем также присвоить значение переменной класса извне. Пример:
class Myclass:
common = 10
def __init__(self):
self.myvariable = 3
def myfunction(self, arg1, arg2):
return self.myvariable
# Здесь мы объявили класс Myclass. Функция __init__ вызывается автоматически при инициализации классов.
>>> classinstance = Myclass() # Мы инициализировали класс и переменная myvariable приобрела значение 3 как заявлено в методе инициализации
>>> classinstance.myfunction(1, 2) #Метод myfunction класса Myclass возвращает значение переменной myvariable
3
# Переменная common объявлена во всех классах
>>> classinstance2 = Myclass()
>>> classinstance.common
10
>>> classinstance2.common
10
# Поэтому, если мы изменим ее значение в классе Myclass изменятся
# и ее значения в объектах, инициализированных классом Myclass
>>> Myclass.common = 30
>>> classinstance.common
30
>>> classinstance2.common
30
# А здесь мы не изменяем переменную класса. Вместо этого
# мы объявляем оную в объекте и присваиваем ей новое значение
>>> classinstance.common = 10
>>> classinstance.common
10
>>> classinstance2.common
30
>>> Myclass.common = 50
# Теперь изменение переменной класса не коснется
# переменных объектов этого класса
>>> classinstance.common
10
>>> classinstance2.common
50
# Следующий класс является наследником класса Myclass
# наследуя его свойства и методы, ктому же класс может
# наследоваться из нескольких классов, в этом случае запись
# такая: class Otherclass(Myclass1, Myclass2, MyclassN)
class Otherclass(Myclass):
def __init__(self, arg1):
self.myvariable = 3
print arg1
>>> classinstance = Otherclass(«hello»)
hello
>>> classinstance.myfunction(1, 2)
3
# Этот класс не имеет совйтсва test, но мы можем
# объявить такую переменную для объекта. Причем
# tэта переменная будет членом только classinstance.
>>> classinstance.test = 10
>>> classinstance.test
10
Исключения
Исключения в Python имеют структуру try—except [exceptionname]:
def somefunction():
try:
# Деление на ноль вызывает ошибку
10 / 0
except ZeroDivisionError:
# Но программа не «Выполняет недопустимую операцию»
# А обрабатывает блок исключения соответствующий ошибке «ZeroDivisionError»
print «Oops, invalid.»
>>> fnexcept()
Oops, invalid.
Импорт
Внешние библиотеки можно подключить процедурой «import [libname]», где [libname] — название подключаемой библиотеки. Вы так же можете использовать команду «from [libname] import [funcname]», чтобы вы могли использовать функцию [funcname] из библиотеки [libname]
import random #Импортируем библиотеку «random»
from time import clock #И заодно функцию «clock» из библиотеки «time»
randomint = random.randint(1, 100)
>>> print randomint
64
Работа с файловой системой
Python имеет много встроенных библиотек. В этом примере мы попробуем сохранить в бинарном файле структуру списка, прочитать ее и сохраним строку в текстовом файле. Для преобразования структуры данных мы будем использовать стандартную библиотеку «pickle»
import pickle
mylist = [«This», «is», 4, 13327]
# Откроем файл C:\binary.dat для записи. Символ «r»
# предотвращает замену специальных сиволов (таких как \n, \t, \b и др.).
myfile = file(r«C:\binary.dat», «w»)
pickle.dump(mylist, myfile)
myfile.close()
myfile = file(r«C:\text.txt», «w»)
myfile.write(«This is a sample string»)
myfile.close()
myfile = file(r«C:\text.txt»)
>>> print myfile.read()
‘This is a sample string’
myfile.close()
# Открываем файл для чтения
myfile = file(r«C:\binary.dat»)
loadedlist = pickle.load(myfile)
myfile.close()
>>> print loadedlist
[‘This’, ‘is’, 4, 13327]
Особенности
- Условия могут комбинироваться. 1 < a < 3 выполняется тогда, когда а больше 1, но меньше 3.
- Используйте операцию «del» чтобы очищать переменные или элементы массива.
- Python предлагает большие возможности для работы со списками. Вы можете использовать операторы объявлении структуры списка. Оператор for позволяет задавать элементы списка в определенной последовательности, а if — позволяет выбирать элементы по условию.
>>> lst1 = [1, 2, 3]
>>> lst2 = [3, 4, 5]
>>> print [x * y for x in lst1 for y in lst2]
[3, 4, 5, 6, 8, 10, 9, 12, 15]
>>> print [x for x in lst1 if 4 > x > 1]
[2, 3]
# Оператор «any» возвращает true, если хотя
# бы одно из условий, входящих в него, выполняется.
>>> any(i % 3 for i in [3, 3, 4, 4, 3])
True
# Следующая процедура подсчитывает количество
# подходящих элементов в списке
>>> sum(1 for i in [3, 3, 4, 4, 3] if i == 3)
3
>>> del lst1[0]
>>> print lst1
[2, 3]
>>> del lst1
- Глобальные переменные объявляются вне функций и могут быть прочитанны без каких либо объявлений. Но если вам необходимо изменить значение глобальной переменной из функции, то вам необходимо объявить ее в начале функции ключевым словом «global», если вы этого не сделаете, то Python объявит переменную, доступную только для этой функции.
number = 5
def myfunc():
# Выводит 5
print number
def anotherfunc():
# Это вызывает исключение, поскольку глобальная апеременная
# не была вызванна из функции. Python в этом случае создает
# одноименную переменную внутри этой функции и доступную
# только для операторов этой функции.
print number
number = 3
def yetanotherfunc():
global number
# И только из этой функции значение переменной изменяется.
number = 3
Эпилог
Разумеется в этой статье не описываются все возможности Python. Я надеюсь что эта статья поможет вам, если вы захотите и в дальнейшем изучать этот язык программирования.
Преимущества Python
- Скорость выполнения программ написанных на Python очень высока. Это связанно с тем, что основные библиотеки Python
написаны на C++ и выполнение задач занимает меньше времени, чем на других языках высокого уровня. - В связи с этим вы можете писать свои собственные модули для Python на C или C++
- В стандартныx библиотеках Python вы можете найти средства для работы с электронной почтой, протоколами
Интернета, FTP, HTTP, базами данных, и пр. - Скрипты, написанные при помощи Python выполняются на большинстве современных ОС. Такая переносимость обеспечивает Python применение в самых различных областях.
- Python подходит для любых решений в области программирования, будь то офисные программы, вэб-приложения, GUI-приложения и т.д.
- Над разработкой Python трудились тысячи энтузиастов со всего мира. Поддержкой современных технологий в стандартных библиотеках мы можем быть обязаны именно тому, что Python был открыт для всех желающих.
Python 3 — Основные операторы
Операторы являются конструкциями, которые могут манипулировать значением операндов. Рассмотрим выражение 4 + 5 = 9. Здесь, 4 и 5 называются операндами и + называется оператором.Типы операторов
Язык Python поддерживает следующие типы операторов:
- Арифметические операторы
- Сравнение (реляционные) операторы
- Операторы присваивания
- Логические операторы
- Битовые операторы
- Членские операторы
- Операторы идентификации
Давайте рассмотрим все операторы один за другим.
Арифметические операторы в Python
Предположим, переменная содержит а значение 10, а переменная б содержит значение 21, то:
оператор | Описание | пример |
---|---|---|
+ Сложение | Добавление значений по обе стороны от оператора. | а + b = 31 |
– Вычитание | Вычитание правого операнда из левого операнда. | а – b = -11 |
* Умножение | Умножение значения по обе стороны от оператора | a * b = 210 |
/ Деление | Делит левый операнд на правый операнд | б / а = 2,1 |
% Модуль | Делит левый операнд на правый операнд и возвращает остаток | б % а = 1 |
** Экспонента | Выполняет экспоненциальный расчет на операторах | а ** b = 10 в степени 20 |
// деление с округлением | Отдел пола – Разделение операндов, где результат является фактором, в котором цифра после десятичной запятой удаляется. Но если один из операндов отрицателен, то результат округляется, т.е. округляется от нуля (по отношению к отрицательной бесконечности): | 9 // 2 = 4 и 9,0 // 2,0 = 4,0, -11 // 3 = -4, -11,0 // 3 = -4,0 |
Операторы сравнения в Python
Операторы сравнения значений по обе стороны от них и решить, соотношение между ними. Их также называют реляционные операторы.
Предположим, переменная а содержит значение 10, а переменная б имеет значение 20, то:
Показать пример
оператор | Описание | пример |
---|---|---|
== | Если значения двух операндов равны, то условие становится истинным. | (а == б) не верно. |
!= | Если значения двух операндов не равны, то условие становится истинным. | (а ! = б) истинно. |
> | Если значение левого операнда больше значения правого операнда, то условие становится истинным. | (а > б) не верно. |
< | Если значение левого операнда меньше значения правого операнда, то условие становится истинным. | (а < б) истинно. |
> = | Если значение левого операнда больше или равно значению правого операнда, то условие становится истинным. | (а >= б) не верно. |
<= | Если значение левого операнда меньше или равно значению правого операнда, то условие становится истинным. | (а <= б) истинно. |
Операторы присваивания в Python
Предположим, переменная содержит а значение 10, а переменная б имеет значение 20, то:
оператор | Описание | пример |
---|---|---|
= | Назначает значения с правой стороной операндов левой стороне операнда | с = а + b присваивает значение a + b в c |
+ = Добавить и | Добавляет правый операнд к левому операнду и присвоить результат левого операнда | с + = а эквивалентно c = c + a |
– = вычесть и | Вычитает правый операнд из левого операнда и присваивает результат левого операнда | с – = а эквивалентно c = c – a |
* = умножить и | Умножает правый операнд на левый операнд и присваивает результат левого операнда | с * = а эквивалентно c = c * a |
/ = разделить и | Делит левый операнд на правый операнд и присваивает результат левого операнда | с / = а эквивалентно c = c / ac /= a эквивалентно с = с / а |
% = Модуль и | Принимает модуль с помощью двух операндов и присваивает результат левого операнда | c% = а эквивалентно c = c % a |
** = Экспонент и | Выполняет вычисление экспоненту от операторов и присваивает значение левого операнда | с ** = а эквивалентно c = c ** a |
// = Floor Division | Выполняет деление операторов с округлением и присваивает значение левого операнда | с // = а эквивалентно c = c // a |
Битовые операторы в Python
Побитовые операторы работают над битами и выполняют операции бит за битом. Допустим, если а = 60; и б = 13; В настоящее время в двоичном формате они будут выглядить следующим образом:
а = 0011 1100
б = 0000 1101
—————–
а&б = 0000 1100
а|б = 0011 1101
а^б = 0011 0001
~а = 1100 0011
Встроенная функция bin() в Python может быть использована для получения двоичного представления целого числа.
Следующие Битовые операторы поддерживаются языком Python:
Оператор | Описание | Пример |
---|---|---|
& бинарный И | копии оператора бита, в результате, если они существует в обоих операндах | (а & б) (0000 означает 1100) |
| бинарный ИЛИ | копирует бит, если он существует в любом из операндов. | (а | б) = 61 (означает 0011 1101) |
^ бинарный Исключающий или | копирует бит, если он установлен в одном операнде, но не в обоих. | (а ^ б) = 49 (означает 0011 0001) |
~ Бинарным комплемент | Это унарное и имеет эффект бит «листать». | (~ а) = -61 (в форме означает двойной комплемент 1100 0011 из-за подписанного двоичного числа. |
<< Двоичный сдвиг влево | Значение левого операнда перемещается влево на число битов, заданное правым операндом. | а << = 240 (1111 означает 0000) |
>> Двоичный сдвиг вправо | Значение левого операнда перемещается вправо на число битов, заданное правым операндом. | а >> = 15 (0000 означает 1111) |
Логические операторы в Python
Следующие логические операторы поддерживаются языком Python. Предположим, переменная справедлива и переменная б имеет значение False, то:
Оператор | Описание | Пример |
---|---|---|
and логическое И | Если оба операнда истинны, то условие становится истинным. | (a and б) неверно. |
or логическое ИЛИ | Если какой-либо из двух операндов не равны нулю, то условие становится истинным. | (a or б) истинно. |
not Логическое НЕ | Используется для обратного логического состояния операнда. | not (а и б) Верно. |
Членские Операторы в Python
Статус операторов тестирования на членство в последовательности, такие как строки, списки или кортежи. Есть два членских операторов, как объяснено ниже:
Оператор | Описание | Пример |
---|---|---|
in | истина, если он находит переменную в указанной последовательности и ложь в противном случае. | х in у, здесь приводит к 1, если х является членом последовательности у. |
not in | истина, если он не находит переменную в указанной последовательности и ложь в противном случае. | х not in у, здесь не приводит к 1, если х не является членом последовательности у. |
Операторы идентификации в Python
Операторы идентификации сравнивают ячейки памяти двух объектов. Есть два оператора идентификации как объяснено ниже:
Оператор | Описание | Пример |
---|---|---|
is | Возвращает истину, если переменные по обе стороны от точки оператора указывают на тот же объект и ложь в противном случае. | х is у, здесь результат is равен 1, если идентификатор (х) равен идентификатору (у). |
not is | Возвращает ложным, если переменные по обе стороны от точки оператора указывают на тот же объект и верно в противном случае. | х not is у, здесь not is приводит к 1, если идентификатор (х) не равен идентификатору (у). |
Операторы приоритетов в Python
В следующей таблице перечислены все операторы от наивысшего приоритета к самому низкому.
Порядковый номер | Оператор & Описание | |
---|---|---|
1 | ** Возведение в степень (повышение мощности) | |
2 | ~ + – Дополнение, унарный плюс и минус (имена методов для двух последних являются + @ и – @) | |
3 | * / % // Умножение, деление по модулю и остаток от деления | |
4 | + – Сложение и вычитание | |
5 | >> << Правый и левый побитовый сдвиг | |
6 | & Побитовое «И» | |
7 | ^ | Побитовое исключающее “ИЛИ и регулярное ИЛИ” | |
8 | <= <>> = операторы сравнения | |
9 | <> ==! = операторы равенства | |
10 | = %= /= //= -= += *= **= операторы присваивания | |
11 | is not операторы идентификации | |
12 | in not in операторы членства | |
13 | not или and Логические операторы |
Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.
Функции в Пайтоне объявляются не просто, а очень просто. Вот пример самой простой:
def empty_func(): pass
Начинается объявление с ключевого слова def, что как не сложно догадаться является сокращением от define. После него идет имя функции. После имени в круглых скобках задается список параметров, в данном случае отсутствующих.
Тело функции пишется с отступом со следующей строки. учтите, что в Пайтоне функции с пустым телом запрещены, потому в качестве тела приведенной выше функции используется «пустой оператор» pass.
Теперь рассмотрим пример посерьезнее.
def safe_div(x, y): """Do a safe division :-) for fun and profit""" if y != 0: z = x / y print z return z else: print "Yippie-kay-yay, motherf___er!"
В этом примере есть несколько нововведений. первое, что бросается в глаза — это строка документации (docstring), идущая сразу после тела функции.
Обычно эта строка занимает не одну строку исходного текста (простите за каламбур) и потому задается в тройных кавычках. Она предназначена для описания функции, ее предназначения, параметров и т.п. Все хорошие ИДЕ умеют с этой строкой работать. Получить к ней доступ можно и из самой программы, используя свойство __doc__:
print safe_div.__doc__
Этим свойством (да, да, именно свойством, в Пайтоне даже функции на самом деле — классы) удобно пользоваться во время сеансов работы интерактивной консоли.
>>> from ftplib import FTP >>> print FTP.__doc__ An FTP client class. To create a connection, call the class using these argument: host, user, passwd, acct These are all strings, and have default value ''. Then use self.connect() with optional host and port argument. # дальнейшее почикано мною :-)
Вернемся к нашей исходной функции. Суть ее очень проста, она принимает 2 параметра: х и у. Если у не равен 0, она делит х на у, выводит результат на экран и возвращает свое частное в виде результата. Результат функции возвращают с помощью команды return. Благодаря механизму кортежей, описанному в прошлом уроке, функции в Пайтоне могут возвращать одновременно множество объектов.
Если же делитель все-таки равен нулю, функция выводит сообщение об ошибке. Неверно было бы предположить что в этом случае функция ничего не вернет. Правильнее будет сказать что функция вернет «ничего» 🙂 Иначе говоря, если в функции отсутствует оператор return, или же он вызван без параметров, то функция возвращает специальное значение None. В этом легко убедиться вызвав что-то типа print safe_div(10, 0).
Вот пример слегка посложнее, он взят из доклада-презентации Гвидо ван Россума.
def gcd(a, b): "Нахождение НОД" while a != 0: a,b = b%a,a # параллельное определение return b
Данная функция находит наибольший общий делитель двух чисел.
В общем, следует учитывать, что параметры в функции Пайтоном передаются по ссылке. Еще одним, возможно нетривиальным фактом к которому придется привыкать — является тот факт что сами функции являются значением, которое можно присваивать. Если воспользоваться нашей функцией safe_div для дальнейших экспериментов, то можно написать следующий код.
mystic_function = safe_div print mystic_function(10, 4)
Вот на этот раз и все, «за бортом» осталось еще много аспектов определения функций в Пайтоне, которые будут освещены в следующий раз.
Упражнения для проверки.
1. На основе существующей функции нахождения НОД, напишите функцию поиска НОК двух чисел.
2. Напишите подпрограмму табулирования функции, переданной в качестве аргумента. Так же аргументами задается начальное, конечное значение и шаг табуляции.
PS кстати, каков оптимальный объем «урока»? Что лучше — реже выходящие большие главы, или «лучше меньше да чаще».
От автора: операторы Python используются для выполнения операций над значениями и переменными. Операторы могут манипулировать отдельными элементами и возвращать результат. Элементы данных называются операндами или аргументами. Операторы представлены либо ключевыми словами, либо специальными символами. Например, для операторов идентификации мы используем ключевые слова «is» и «is not».
В этом руководстве мы рассмотрим различные операторы:
Арифметические
Операторы сравнения
Операторы присваивания
Бесплатный курс «Python. Быстрый старт»
Получите курс и узнайте, как создать программу для перевода текстов на Python
Получить курсЛогические или побитовые операторы
Операторы принадлежности
Операторы идентификации
Операторы приоритета
Арифметические операторы
Арифметические операторы выполняют различные арифметические вычисления, такие как сложение, вычитание, умножение, деление, % модуля, экспоненты и т. д. В Python существуют различные методы арифметического вычисления, например, вы можете использовать функцию eval, объявить переменную и вычислить или вызвать функции.
Пример: Для арифметических операторов мы возьмем простой пример сложения, где мы сложим два числа 4 + 5 = 9.
Точно так же вы можете использовать другие арифметические операторы, такие как умножение (*), деление (/), вычитание (-) и т. д.
Операторы сравнения
Эти операторы сравнивают значения по обе стороны и определяют отношение между ними. Их также называют реляционными операторами. Различные операторы сравнения: (==,!=, <>,>,
Пример: Мы сравним значение x со значением y и выведем результат: true или false. Здесь, например, наше значение x = 4, которое меньше, чем y = 5, поэтому, когда мы выводим значение как x>y, оно фактически сравнивает значение x с y и, поскольку оно не является истинным, возвращает false.
x = 4 y = 5 print((‘x > y is’,x>y))
x = 4 y = 5 print((‘x > y is’,x>y)) |
Точно так же вы можете попробовать другие операторы сравнения (x
Операторы присваивания Python
Операторы присваивания Python используются для присвоения значения правого операнда левому операнду. В Python используются различные операторы присваивания (+=, -=, *=, /= и т. д.)
Пример: операторы присваивания Python просто назначают значение, например:
num1 = 4 num2 = 5 print((«Line 1 — Value of num1 : «, num1)) print((«Line 2 — Value of num2 : «, num2))
num1 = 4 num2 = 5 print((«Line 1 — Value of num1 : «, num1)) print((«Line 2 — Value of num2 : «, num2)) |
Пример составного оператора присваивания
Мы также можем использовать составной оператор присваивания, в котором вы можете добавлять, вычитать, умножать правый операнд на левый и задавать сумму (или любую другую арифметическую функцию) для левого операнда.
Шаг 1. Назначаем значение для num1 и num2
Шаг 2: Добавляем значение num1 и num2 (4 + 5 = 9)
Шаг 3: Добавляем num1 к выводу шага 2 (9 + 4)
Шаг 4: Окончательный результат будет выведен, как 13
num1 = 4 num2 = 5 res = num1 + num2 res += num1 print((«Line 1 — Result of + is «, res))
num1 = 4 num2 = 5 res = num1 + num2 res += num1 print((«Line 1 — Result of + is «, res)) |
Логические операторы
Логические операторы в Python, используемые для условных операторов true или false. Логические операторы в Python — это AND, OR и NOT. Для логических операторов применяются следующие условия.
Для оператора AND — возвращает TRUE, если оба операнда (правый и левый) верны
Для оператора OR — возвращает TRUE, если любой из операндов (правый и левый) равен TRUE
Для оператора NOT — возвращает TRUE, если операнд равен false
Пример: в этом примере мы получаем true или false, основываясь на значениях a и b:
a = True b = False print((‘a and b is’,a and b)) print((‘a or b is’,a or b)) print((‘not a is’,not a))
a = True b = False print((‘a and b is’,a and b)) print((‘a or b is’,a or b)) print((‘not a is’,not a)) |
Операторы принадлежности
Эти операторы проверяют наличие в последовательности, такой как списки, строки или кортежи. В Python используются два оператора принадлежности (in, not in). Они дают результат, исходя из наличия переменной в указанной последовательности или строке.
Пример: Например, здесь мы проверяем, доступно ли в списке значение x=4 и значение y=8, для этого мы используем операторы in и not in.
x = 4 y = 8 list = [1, 2, 3, 4, 5 ]; if ( x in list ): print(«Line 1 — x is available in the given list») else: print(«Line 1 — x is not available in the given list») if ( y not in list ): print(«Line 2 — y is not available in the given list») else: print(«Line 2 — y is available in the given list»)
x = 4 y = 8 list = [1, 2, 3, 4, 5 ]; if ( x in list ): print(«Line 1 — x is available in the given list») else: print(«Line 1 — x is not available in the given list») if ( y not in list ): print(«Line 2 — y is not available in the given list») else: print(«Line 2 — y is available in the given list») |
Объявляем значение для х и у
Объявляем значение списка
Используем оператор «in» в коде с оператором if, чтобы проверить существование значения x в списке и вывести результат соответствующим образом.
Бесплатный курс «Python. Быстрый старт»
Получите курс и узнайте, как создать программу для перевода текстов на Python
Получить курсИспользуем «not in» в коде с оператором if, чтобы проверить существование значения y в списке и вывести результат соответствующим образом.
Запустите код — когда код запустится, он даст нужный результат
Операторы идентификации
Для сравнения расположения в памяти двух объектов используются операторы. В Python используются два оператора идентификации (is, is not).
Оператор is: возвращает true, если две переменные указывают на один и тот же объект, и false — в противном случае.
Оператор is not: возвращает false, если две переменные указывают на один и тот же объект и true — в противном случае
Следующие операнды расположены в порядке убывания приоритета. Операторы в одном поле оценивают слева направо.
** — Экспонента
*, /, //,% — Умножение, Деление, Полуделение, Модуль
+, — — Сложение, вычитание
> = — Операторы сравнения
= %= /= //= -= += *= **= — Операторы присваивания
is is not — Операторы идентификации
in not in — Операторы принадлежности
not or and — Логические операторы
x = 20 y = 20 if ( x is y ): print(«x & y SAME identity») y=30 if ( x is not y ): print(«x & y have DIFFERENT identity»)
x = 20 y = 20 if ( x is y ): print(«x & y SAME identity») y=30 if ( x is not y ): print(«x & y have DIFFERENT identity») |
Объявляем значение для переменных x и y
Используем в коде оператор «is», чтобы проверить, совпадает ли значение x с y
Далее мы используем в коде оператор «is not», чтобы проверить, совпадает ли значение x с y
Запустите код — результат будет таким, как ожидалось
Приоритет оператора
Приоритет оператора определяет, какие операторы должны быть оценены первыми. Чтобы избежать двусмысленности в значениях, необходим приоритет операторов. Как и в обычном методе умножения, умножение имеет более высокий приоритет, чем сложение. Например, в 3+ 4 * 5 ответом является 23, чтобы изменить порядок приоритета, мы используем круглые скобки (3 + 4) * 5, теперь ответ 35.
v = 4 w = 5 x = 8 y = 2 z = 0 z = (v+w) * x / y; print(«Value of (v+w) * x/ y is «, z)
v = 4 w = 5 x = 8 y = 2 z = 0 z = (v+w) * x / y; print(«Value of (v+w) * x/ y is «, z) |
Объявляем значение переменных v, w… z
Теперь применяем формулу и запускаем код
Код выполнит и вычислит переменную с более высоким приоритетом и выдаст результат
Пример Python 2
Выше приведены примеры кода Python 3, если вы хотите использовать Python 2, пожалуйста, рассмотрите следующие коды:
#Arithmetic Operators x= 4 y= 5 print x + y #Comparison Operators x = 4 y = 5 print(‘x > y is’,x>y) #Assignment Operators num1 = 4 num2 = 5 print («Line 1 — Value of num1 : «, num1) print («Line 2 — Value of num2 : «, num2) #compound assignment operator num1 = 4 num2 = 5 res = num1 + num2 res += num1 print («Line 1 — Result of + is «, res) #Logical Operators a = True b = False print(‘a and b is’,a and b) print(‘a or b is’,a or b) print(‘not a is’,not a) #Membership Operators x = 4 y = 8 list = [1, 2, 3, 4, 5 ]; if ( x in list ): print «Line 1 — x is available in the given list» else: print «Line 1 — x is not available in the given list» if ( y not in list ): print «Line 2 — y is not available in the given list» else: print «Line 2 — y is available in the given list» #Identity Operators x = 20 y = 20 if ( x is y ): print «x & y SAME identity» y=30 if ( x is not y ): print «x & y have DIFFERENT identity» #Operator precedence v = 4 w = 5 x = 8 y = 2 z = 0 z = (v+w) * x / y; print «Value of (v+w) * x/ y is «, z
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | #Arithmetic Operators x= 4 y= 5 print x + y
#Comparison Operators x = 4 y = 5 print(‘x > y is’,x>y)
#Assignment Operators num1 = 4 num2 = 5 print («Line 1 — Value of num1 : «, num1) print («Line 2 — Value of num2 : «, num2)
#compound assignment operator num1 = 4 num2 = 5 res = num1 + num2 res += num1 print («Line 1 — Result of + is «, res)
#Logical Operators a = True b = False print(‘a and b is’,a and b) print(‘a or b is’,a or b) print(‘not a is’,not a)
#Membership Operators x = 4 y = 8 list = [1, 2, 3, 4, 5 ]; if ( x in list ): print «Line 1 — x is available in the given list» else: print «Line 1 — x is not available in the given list» if ( y not in list ): print «Line 2 — y is not available in the given list» else: print «Line 2 — y is available in the given list»
#Identity Operators x = 20 y = 20 if ( x is y ): print «x & y SAME identity» y=30 if ( x is not y ): print «x & y have DIFFERENT identity»
#Operator precedence v = 4 w = 5 x = 8 y = 2 z = 0 z = (v+w) * x / y; print «Value of (v+w) * x/ y is «, z |
Заключение
Операторы в языке программирования используются для выполнения различных операций над значениями и переменными. В Python вы можете использовать такие операторы:
Существуют различные методы арифметических вычислений, также вы можете использовать функцию eval, объявить переменную и вычислить или вызвать функции
Операторы сравнения, часто называемые реляционными операторами, используются для сравнения значений операндов и определения связи между ними.
Операторы присваивания Python просто присваивают значение переменной
Python также позволяет вам использовать составной оператор присваивания в сложных арифметических вычислениях, где вы можете присваивать результат одного операнда другому
Для оператора AND — возвращает TRUE, если оба операнда (правая и левая стороны) верны
Для оператора OR — возвращает TRUE, если любой из операндов (правая или левая стороны) равен true
Для оператора NOT — возвращает TRUE, если операнд равен false
В Python используются два оператора принадлежности (in, not in).
Они дают результат, исходя из присутствия переменной в указанной последовательности или строке
В Python используются два оператора идентификации (is, is not)
Они возвращает true, если две переменные указывают на один и тот же объект, и false в противном случае
Оператор приоритета может быть полезен, когда вам нужно установить приоритет оператора, для которого вычисление должно быть выполнено первым в сложном вычислении.
Источник: https://www.guru99.com
Редакция: Команда webformyself.
Бесплатный курс «Python. Быстрый старт»
Получите курс и узнайте, как создать программу для перевода текстов на Python
Получить курсФорматирование строк или «Что означает %s в python?»
- Опубликовано:
- Теги: python
Оглавление
- Примеры
- Как работает оператор ‘%’
- Как работает встроенная функция format()
Для начала несколько примеров
Форматирование строк:>>> name = 'Vasya'
>>> print "My name is %s" % (name)
My name is Vasya
С указанием размера полей (перед ‘Vasya’ стоит пять пробелов, т.е. всего десять символов):>>> print "My name is %10s. That's my name." % (name)
My name is Vasya. That's my name.
То же самое, но выровненное по левому краю:>>> print "My name is %-10s. That's my name." % (name)
My name is Vasya . That's my name.
Когда это может быть полезно:>>> drinks = {'Long Island': 3, 'Bloody Mary': 2, 'Margarita':4}
>>> print "%-15s%-5s" % ("Name", "Qty")
Name Qty
>>> for k,v in drinks.items():
... print "%-15s%-3s" % (k, v)
...
Bloody Mary 2
Long Island 3
Margarita 4
Если понадобится вывести целую часть числа:>>> num = 12.34
>>> print "%d" % (num)
12
Вперемешку:>>> age = 25
>>> print "My name is %s. I'm %d." % (name, age)
My name is Vasya. I'm 25.
Теперь вкратце как работает оператор %
Выражение форматирования можно условно разделить на три части:
определение_формата
+ %
+ объект(ы)
Обозначения %s, %d, %g
и т. п. — это форматы типов данных. Если вы знакомы с языком Си, то это тот же синтаксис, что используется для вывода на печать printf()
.
Спецификации различных типов данных Python приведены в следующей таблице:
Формат | Значение |
---|---|
'd' |
Целое десятичное число. |
'i' |
Целое десятичное число. |
'o' |
Восьмеричное число. |
'u' |
Устаревший тип – то же что 'd' . |
'x' |
Шестнадцатеричное число (нижний регистр). |
'X' |
Шестнадцатеричное число (верхний регистр). |
'e' |
Вещественное число в экспоненциальном виде (нижний регистр). |
'E' |
Вещественное число в экспоненциальном виде (верхний регистр). |
'f' |
Вещественное число в десятичном виде. |
'F' |
Вещественное число в десятичном виде. |
'g' |
Вещественное число. Использует формат 'f' или 'e' в нижнем регистре. |
'G' |
Вещественное число. Использует формат 'F' или 'E' в верхнем регистре. |
'c' |
Один символ (или цифра). |
'r' |
Строка, в которую любой объект Python конвертируется с помощью repr(). |
's' |
Строка, в которую любой объект Python конвертируется с помощью str(). |
'%' |
Аргумент не конвертируется, выводится просто символ '%' . |
Встроенная функция format()
Работает так:str.format()
В строке «поля для замены» заключаются в фигурные скобки {}
. Все, что не заключено в скобки, воспринимается как обычный текст, которые копируется в неизменном виде. Чтобы передать в тексте символы фигурных скобок, их дублируют: {{
и }}
.
Поля для замены форматируются следующим образом:
поле_для_замены ::= "{" [имя_поля] ["!" конверсия] [":" спецификация] "}"
имя_поля ::= имя_аргумента ("." имя_атрибута | "[" номер_элемента "]")*
имя_аргумента ::= [идентификатор | integer]
имя_атрибута ::= идентификатор
индекс_элемента ::= integer | строковый индекс
строковый_индекс ::= <любой символ кроме "]"> +
конверсия ::= "r" | "s" # str или repr
спецификация ::= <описано ниже>
гдеспецификация ::= [[заглушка]выравнивание][знак][#][0][ширина][,][.точность][тип]
заглушка ::= <любой символ>
выравнивание ::= "<" | ">" | "=" | "^"
знак ::= "+" | "-" | " "
ширина ::= integer # ширина поля
точность ::= integer # знаки после десятичной запятой
тип ::= "b" | "c" | "d" | "e" | "E" | "f" | "F" | "g" | "G" | "n" | "o" | "s" | "x" | "X" | "%"
Записывается так:>>> print """\n{0}
... Сидел на стене
... {0}
... Свалился во сне.""".format('Шалтай-Болтай')
Шалтай-Болтай
Сидел на стене
Шалтай-Болтай
Свалился во сне.
Как видите, этот способ гораздо гибче оператора ‘%’, так как одни и те же значения мы можем использовать повторно и в любом порядке. Также можно передать именованные аргументы, и тогда обращаться к ним будем не по номерам, а по именам.
Еще пример форматирования:
>>> toc = (
... ('Первая глава', '3'),
... ('Вторая глава', '150')
... )
>>> for line in toc:
... print('{:.
Интересности и полезности python / Хабр
Я уже несколько лет программирую на python, однако, недавно осознал, что множество полезных приёмов и интересных моментов прошли мимо меня, возможно, я не один такой, поэтому решил перечислить их здесь, надеюсь, данные приёмы пригодятся кому-то в работе или побудят познакомиться с этим языком поближе.Как и во многих языках в python 1 эквивалентно True, а 0 — False, то есть
1 == True.
Казалось бы, и что в этом такого? Однако, это имеет некоторые побочные эффекты, связанные с тем, что одинаковые объекты обязаны иметь одинаковые хеши, соответственно у вас не получится запихать в один словарь ключ 1 и True.
>>> a = {1: "one", 0: "zero", True: "true", False: "false"}
# -> {1: 'true', 0: 'false'}
Так же это разрешает следующие операции:
>>> print(2 * False + True)
# -> 1
В данном примере строки использовались в качестве значений словаря, однако, зачастую хочется их использовать в качестве ключей словаря, меня всегда раздражало, что при создании словаря с помощью фигурных скобок, строки нужно указывать в кавычках, хотелось бы их опустить, это возможно, если создавать словарь через конструктор dict().
>>> {"one": 1, "two": 2, "three": 3} == dict(one=1, two=2, three=3)
# -> True
Кроме того, с помощью фигурных скобок создаются не только словари, но и множества(set).
>>> a = {1, 2, 3}
Для объединения двух множеств мне почему-то хочется воспользоваться оператором +, наверно, из-за способа конкатенации строк. Однако, python не поддерживает данный оператор для множеств. Но разумеется, это не значит, что нам всегда придётся пользоваться функциями, создатели подошли к данному вопросу более системно и добавили в язык поддержку основных операций над множествами (а не только объединения) и «повесили» их на логические операторы.
a = {1, 2, 3}
b = {0, 2, 4}
print(a & b) # -> {2}
print(a | b) # -> {0, 1, 2, 3, 4}
print(a ^ b) # -> {0, 1, 3, 4}
print(a - b) # -> {1, 3}, однако один арифметический
# оператор всё же оставили
Продолжая разговор про словари, начиная с версии 3.7 спецификацией языка гарантируется, что словари сохраняют порядок вставки элементов, OrderedDict больше не нужен.
www.python.org/downloads/release/python-370
mail.python.org/pipermail/python-dev/2017-December/151283.html
d = dict(zero='Cero', one='Uno', two='Dos', three='Tres', four='Cuatro',
five='Cinco', six='Seis', seven='Siete', eight='Ocho', night='Nueve')
for index, (key, value) in enumerate(d.items()):
print(f"{index} is {key} in England and {value} in Spain")
Обратите внимание на строку вывода, она начинается с префикса f — это особый тип строк, введённый в python 3.6.
Всего в языке три вида строк: обычные, обозначаемые кавычками без префиксов, сырые\не обрабатываемые(raw), в которых спец-символы, вроде, \n не обрабатываются и вставляются как текст и собственно f-строки.
Созданы они были для упрощения вывода, python поддерживает огромное количество способов вывода:
print("result" + str(2)) # Простая конкатенация строк, python не осуществляет
# автоматическое приведение всех аргументов к
# строковому типу, это остаётся за программистом
print("result", 2) # print может принимать несколько аргументов через запятую,
# в таком случае они будут выводиться через пробел,
# вам не нужны преобразовывать выводимые объекты в строку,
# в отличие от предыдущего способа
print("result %d" % 2) # %-синтаксис, сделан по аналогии с языком C.
print("result %d %.2f" % (2, 2)) # https://docs.python.org/3.4/library/string.html#formatspec
print("result %(name)s" % {"name": 2}) # также разрешено создавать именованные метки
print("{}".format(2)) # У класса строки есть метод format()
# он позволяет опускать тип выводимой переменной
print("{0} {1} {0}".format(1, 2)) # так же можно указать номер переменной и таким образом
# вывести её два раза
# нумерация начинается с нуля
# если число переданных переменных меньше использованных в выводе, будет сгенерированно исключение
print("{} {}".format(2)) # -> IndexError: tuple index out of range
print("{0} {0}".format(2, 3)) # -> 2 2 Однако если передано слишком много переменных
# код отработает без ошибок
from math import pi # при таком выводе так же поддерживаются строки формата
print("{:.2f}".format(pi)) # -> 3.14
from string import Template # возможен и такой способ вывода
s = Template("result $res") # однако он не получил большого распространения
print(s.substitute(res = [3, 4]))
Теперь добавили ещё и f-строки. В них доступны любые переменные из области видимости, можно вызывать функции, получать элементы по ключу, кроме того, они поддерживают строки формата.
from math import pi
result = 4
name = "user"
print(f"{name:84s} pi= {pi:.2f}, result={result}, {name[2]}")
# -> user pi= 3.14, result=4, e
from datetime import datetime
print(f"{datetime.now():%Y:%m-%d}")
Они быстрее всех остальных способов вывода, так что, если вам доступен python3.6 рекомендуется использовать именно их.
Одна из наикрутейших фишек python — в нём упаковываются и распаковываются не объекты и примитивы, а параметры и коллекции.
def func(*argv, **kwargs)
Однако, есть один архитектурный недостаток в реализации:
- argv — кортеж, его значения нельзя изменять, нельзя добавлять или удалять значения
- kwargs — словарь, изменяемый, поэтому кеширование невозможно
Недостаток, конечно, не большой, но всё же неприятно, что нельзя напрямую передавать kwargs в кеш, основанный на словаре, с другой стороны, если вы добавите в кортеж список, то такой кортеж тоже нельзя будет просто так добавить в словарь.
Множества тоже создаются на основе хеш-таблицы, это значит, что значения должны быть хешируемы, кроме того само множество является изменяемым и не хешируемым типом, есть специальный тип frozenset — не изменяемое множество (не спрашивайте меня, зачем оно нужно).
Обсуждали создание типа frozendict, однако пока его не добавили (хотя как минимум одно применение ему уже есть — в качестве kwargs). За неизменяемый словарь приходится отдуваться namedtuple. А ещё и за записи и простенькие классы.
Кто в студенческие\школьные годы писал циклы для вывода значений массива и бесился из-за запятой в конце, каждый раз решал, забить или переписать, чтобы было красиво, и только на курсе 2-3 узнал о методе join? Или я один такой?
Одна из неприятных особенностей метода join у строк — он работает только с элементами-строками, если в коллекции есть хоть одна нестрока приходится использовать генераторное выражение, что выглядит слишком сложным решением такой простой задачи, однако, есть способ упростить вывод значений списков (без скобок).
a = list(range(5))
print(" ".join(a)) # -> TypeError: sequence item 0: expected str instance, int found
print(" ".join(str(i) for i in a)) # -> 0 1 2 3 4
print(*a) # -> 0 1 2 3 4
Так как строки — тоже коллекции, то их так же можно «джойнить».
print('-'.join("hello")) # -> h-e-l-l-o
Рассмотрим строку из предыдущего примера.
print(" ".join(str(i) for i in a)) # -> 0 1 2 3 4
Генераторное выражение передано в ф-цию join без каких-либо скобок, круглые скобки можно опускать для упрощения чтения кода. Python заботится о выразительности.
print(sum(i**2 for i in range(10))) # -> 285
Кроме того, круглые скобки можно опускать и при создании кортежей:
article = "python", 2018, "LinearLeopard" # объявление кортежа
theme, year, author = "python", 2018, "LinearLeopard"# распаковка кортежа
theme, year, _ = "python", 2018, "LinearLeopard" # слева и справа должно
# находиться одинаковое количество
# переменных, можно выделить,
# что какая-то вам не нужна,
# обозначив её через
# подчёркивание
theme, _, _ = "python", 2018, "LinearLeopard" # имена могут повторяться
theme, *, author = "python", 2018, "LinearLeopard" # можно объявить жадный
# параметр, который съест
# все неподходящие,
# разумеется, допустим
# только один
# жадный оператор
Звёздочку можно использовать и в объявления функций, таким образом можно создать параметры, которые можно указать только по ключу.
def sortwords(*wordlist, case_sensitive=False):
Можно передавать в ф-цию сколько угодно параметров без боязни, что один из них будет воспринят как значение параметра case_sensitive.
Можно и так.
def func(first, second, *, kwonly):
Внимательнее рассмотрим, чем просто * отличается от *args.
def func(first, second, *, kwonly=True):
print(first, second, kwonly)
def func2(first, second, *args, kwonly=True):
print(first, second, *args, kwonly)
func(1) #-> TypeError: func() missing 1 required positional argument: 'second'
func(1, 2) #-> 1 2 True
func(1, 2, False) #-> TypeError: func() takes 2 positional arguments but 3 were given
# используя * в объявлении вы укажете, что
# ваша функция должна быть вызвана с двумя
# позиционными параметрами
func(1, 2, kwonly=False) #-> 1 2 False
func2(1, 2, False) #-> 1 2 False True
# *args заберёт в себя все позиционные
# параметры, то есть вашу функцию может будет
# вызывать с неограниченным (>2) числом
# параметров
С параметрами по умолчанию связана одна интересная особенность: они вычисляются на этапе компиляции модуля в байт-код, так что лучше не использовать там изменяемые типы. Объявим функцию, которая добавляет элемент в конец списка, если второй аргумент опущен, функция возвращает новый список в котором содержится только этот элемент.
def add_to(elem, collection=[]):
collection.append(elem)
return collection
a = ["a", "c"]
print(add_to("b", a)) # -> ['a', 'c', 'b']
print(add_to("a")) # -> ['a']
print(add_to("b")) # -> ['a', 'b'] Откуда здесь 'a'?
Значения по умолчанию ф-ция хранит в поле __defaults__, можно в любой момент узнать, что там находится.
print(add_to.__defaults__) # -> (['a', 'b'],)
Так как аргумент по умолчанию (пустой список) создался в момент старта программы и не пересоздаётся каждый раз заново, мы получили именно такое поведение.
Исправить подобное поведение можно, если сделать значение по умолчанию неизменяемым типом, а список создавать в теле функции:
def add_to(elem, collection=None):
collection = collection or []
collection.append(elem)
return collection
Обратите внимание на команду
collection = collection or []
это более короткий (и менее понятный, хотя не для всех) аналог
collection = collection if collection else []
Ссылка на следующую часть
Понимание итераторов в Python / Хабр
Python — особенный язык в плане итераций и их реализации, в этой статье мы подробно разберём устройство итерируемых объектов и пресловутого цикла for
.
Особенности, с которыми вы часто можете столкнуться в повседневной деятельности
1. Использование генератора дважды
>>> numbers = [1,2,3,4,5]
>>> squared_numbers = (number**2 for number in numbers)
>>> list(squared_numbers)
[1, 4, 9, 16, 25]
>>> list(squared_numbers)
[]
Как мы видим в этом примере, использование переменной squared_numbers
дважды, дало ожидаемый результат в первом случае, и, для людей незнакомых с Python в достаточной мере, неожиданный результат во втором.
2. Проверка вхождения элемента в генератор
Возьмём всё те же переменные:
>>> numbers = [1,2,3,4,5]
>>> squared_numbers = (number**2 for number in numbers)
А теперь, дважды проверим, входит ли элемент в последовательность:
>>> 4 in squared_numbers
True
>>> 4 in squared_numbers
False
Получившийся результат также может ввести в заблуждение некоторых программистов и привести к ошибкам в коде.
3. Распаковка словаря
Для примера используем простой словарь с двумя элементами:
>>> fruits_amount = {'apples': 2, 'bananas': 5}
Распаковываем его:
>>> x, y = fruits_amount
Результат будет также неочевиден, для людей, не понимающих устройство Python, «под капотом»:
>>> x
'apples'
>>> y
'bananas'
Последовательности и итерируемые объекты
По-сути, вся разница, между последовательностями и итерируемымыи объектами, заключается в том, что в последовательностях элементы упорядочены.
Так, последовательностями являются: списки, кортежи и даже строки.
>>> numbers = [1,2,3,4,5]
>>> letters = ('a','b','c')
>>> characters = 'habristhebestsiteever'
>>> numbers[1]
2
>>> letters[2]
'c'
>>> characters[11]
's'
>>> characters[0:4]
'habr'
Итерируемые объекты же, напротив, не упорядочены, но, тем не менее, могут быть использованы там, где требуется итерация: цикл for
, генераторные выражения, списковые включения — как примеры.
# Can't be indexed
>>> unordered_numbers = {1,2,3}
>>> unordered_numbers[1]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'set' object is not subscriptable
>>> users = {'males': 23, 'females': 32}
>>> users[1]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 1
# Can be used as sequence
>>> [number**2 for number in unordered_numbers]
[1, 4, 9]
>>>
>>> for user in users:
... print(user)
...
males
females
Отличия цикла for
в Python от других языков
Стоит отдельно остановиться на том, что цикл for
, в Python, устроен несколько иначе, чем в большинстве других языков. Он больше похож на for...each
, или же for...of
.
Если же, мы перепишем цикл for
с помощью цикла while
, используя индексы, то работать такой подход будет только с последовательностями:
>>> list_of_numbers = [1,2,3]
>>> index = 0
>>> while index < len(list_of_numbers):
... print(list_of_numbers[index])
... index += 1
...
1
2
3
А с итерируемыми объектами, последовательностями не являющимися, не будет:
>>> set_of_numbers = {1,2,3}
>>> index = 0
>>> while index < len(set_of_numbers):
... print(set_of_numbers[index])
... index += 1
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
TypeError: 'set' object is not subscriptable
Если же вам нужен index
, то следует использовать встроенную функцию enumerate
:
>>> set_of_numbers = {1,2,3}
>>> for index, number in enumerate(set_of_numbers):
... print(number, index)
...
1 0
2 1
3 2
Цикл for
использует итераторы
Как мы могли убедиться, цикл for
не использует индексы. Вместо этого он использует так называемые итераторы.
Итераторы — это такие штуки, которые, очевидно, можно итерировать 🙂
Получить итератор мы можем из любого итерируемого объекта.
Для этого нужно передать итерируемый объект во встроенную функцию iter
:
>>> set_of_numbers = {1,2,3}
>>> list_of_numbers = [1,2,3]
>>> string_of_numbers = '123'
>>>
>>> iter(set_of_numbers)
<set_iterator object at 0x7fb192fa0480>
>>> iter(list_of_numbers)
<list_iterator object at 0x7fb193030780>
>>> iter(string_of_numbers)
<str_iterator object at 0x7fb19303d320>
После того, как мы получили итератор, мы можем передать его встроенной функции next
.
>>> set_of_numbers = {1,2,3}
>>>
>>> numbers_iterator = iter(set_of_numbers)
>>> next(numbers_iterator)
1
>>> next(numbers_iterator)
2
При каждом новом вызове, функция отдаёт один элемент. Если же в итераторе элементов больше не осталось, то функция next
породит исключение StopIteration
.
>>> next(numbers_iterator)
3
>>> next(numbers_iterator)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
По-сути, это единственное, что мы может сделать с итератором: передать его функции next
.
Как только итератор становится пустым и порождается исключение StopIteration
, он становится совершенно бесполезным.
Реализация цикла for
с помощью функции и цикла while
Используя полученные знания, мы можем написать цикл for
, не пользуясь самим циклом for
. 🙂
Чтобы сделать это, нам нужно:
- Получить итератор из итерируемого объекта.
- Вызвать функцию
next
. - Выполнить ‘тело цикла’.
- Закончить цикл, когда будет получено исключение
StopIteration
.
def for_loop(iterable, loop_body_func):
iterator = iter(iterable)
next_element_exist = True
while next_element_exist:
try:
element_from_iterator = next(iterator)
except StopIteration:
next_element_exist = False
else:
loop_body_func(element_from_iterator)
Стоит заметить, что здесь мы использовали конструкцию try-else
. Многие о ней не знают. Она позволяет выполнять код, если исключения не возникло, и код был выполнен успешно.
Теперь мы знакомы с протоколом итератора.
А, говоря простым языком — с тем, как работает итерация в Python.
Функции iter
и next
этот протокол формализуют. Механизм везде один и тот же. Будь то пресловутый цикл for
или генераторное выражение. Даже распаковка и «звёздочка» используют протокол итератора:
coordinates = [1,2,3]
x, y, z = coordinates
numbers = [1,2,3,4,5]
a,b, *rest = numbers
print(*numbers)
Генераторы — это тоже итераторы
Генераторы тоже реализуют протокол итератора:
>>> def custom_range(number):
... index = 0
... while index < number:
... yield index
... index += 1
...
>>> range_of_four = custom_range(4)
>>> next(range_of_four)
0
>>> next(range_of_four)
1
>>> next(range_of_four)
2
>>> next(range_of_four)
3
>>> next(range_of_four)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
В случае, если мы передаём в iter
итератор, то получаем тот же самый итератор
>>> numbers = [1,2,3,4,5]
>>> iter1 = iter(numbers)
>>> iter2 = iter(iter1)
>>> next(iter1)
1
>>> next(iter2)
2
>>> iter1 is iter2
True
Подытожим.
Итерируемый объект — это что-то, что можно итерировать.
Итератор — это сущность порождаемая функцией iter
, с помощью которой происходит итерирование итерируемого объекта.
Итератор не имеет индексов и может быть использован только один раз.
Протокол итератора
Теперь формализуем протокол итератора целиком:
- Чтобы получить итератор мы должны передать функции
iter
итерируемый объект. - Далее мы передаём итератор функции
next
. - Когда элементы в итераторе закончились, порождается исключение
StopIteration
.
Особенности:
- Любой объект, передаваемый функции
iter
без исключенияTypeError
— итерируемый объект. - Любой объект, передаваемый функции
next
без исключенияTypeError
— итератор. - Любой объект, передаваемый функции
iter
и возвращающий сам себя — итератор.
Плюсы итераторов:
Итераторы работают «лениво» (en. lazy). А это значит, что они не выполняют какой-либо работы, до тех пор, пока мы их об этом не попросим.
Таким образом, мы можем оптимизировать потребление ресурсов ОЗУ и CPU, а так же создавать бесконечные последовательности.
Итераторы повсюду
Мы уже видели много итераторов в Python.
Я уже упоминал о том, что генераторы — это тоже итераторы.
Многие встроенные функции является итераторами.
Так, например, enumerate
:
>>> numbers = [1,2,3]
>>> enumerate_var = enumerate(numbers)
>>> enumerate_var
<enumerate object at 0x7ff975dfdd80>
>>> next(enumerate_var)
(0, 1)
А так же zip
:
>>> letters = ['a','b','c']
>>> z = zip(letters, numbers)
>>> z
<zip object at 0x7ff975e00588>
>>> next(z)
('a', 1)
И даже open
:
>>> f = open('foo.txt')
>>> next(f)
'bar\n'
>>> next(f)
'baz\n'
>>>
В Python очень много итераторов, и, как уже упоминалось выше, они откладывают выполнение работы до того момента, как мы запрашиваем следующий элемент с помощью next
. Так называемое, «ленивое» выполнение.
Создание собственного итератора
Так же, в некоторых случаях, может пригодится знание того, как написать свой собственный итератор и ленивый итерируемый объект.
В моей карьере этот пункт был ключевым, так как вопрос был задан на собеседовании, которое, как вы могли догадаться, я успешно прошёл и получил свою первую работу:)
class InfiniteSquaring:
"""Класс обеспечивает бесконечное последовательное возведение в квадрат заданного числа."""
def __init__(self, initial_number):
# Здесь хранится промежуточное значение
self.number_to_square = initial_number
def __next__(self):
# Здесь мы обновляем значение и возвращаем результат
self.number_to_square = self.number_to_square ** 2
return self.number_to_square
def __iter__(self):
"""Этот метод позволяет при передаче объекта функции iter возвращать самого себя, тем самым в точности реализуя протокол итератора."""
return self
>>> squaring_of_six = InfiniteSquaring(6)
>>> next(squaring_of_six)
36
>>> next(squaring_of_six)
1296
>>> next(squaring_of_six)
1679616
>>> next(squaring_of_six)
2821109907456
>>> next(squaring_of_six)
7958661109946400884391936
>>> # И так до бесконечности...
Так же:
>>>iter(squaring_of_six) is squaring_of_six
True
Таким образом мы написали бесконечный и ленивый итератор.
А это значит, что ресурсы он будет потреблять только при вызове.
Не говоря уже о том, что без собственного итератора имлементация бесконечной последовательности была бы невозможна.
А теперь вернёмся к тем особенностям, которые были изложены в начале статьи
1. Использование генератора дважды
>>> numbers = [1,2,3,4,5]
>>> squared_numbers = (number**2 for number in numbers)
>>> list(squared_numbers)
[1, 4, 9, 16, 25]
>>> list(squared_numbers)
[]
В данном примере, список будет содержать элементы только в первом случае, потому что генераторное выражение — это итератор, а итераторы, как мы уже знаем — сущности одноразовые. И при повторном использовании не будут отдавать никаких элементов.
2. Проверка вхождения элемента в генератор
>>> numbers = [1,2,3,4,5]
>>> squared_numbers = (number**2 for number in numbers)
А теперь дважды проверим, входит ли элемент в последовательность:
>>> 4 in squared_numbers
True
>>> 4 in squared_numbers
False
В данном примере, элемент будет входить в последовательность только 1 раз, по причине того, что проверка на вхождение проверяется путем перебора всех элементов последовательности последовательно, и как только элемент обнаружен, поиск прекращается. Для наглядности приведу пример:
>>> 4 in squared_numbers
True
>>> list(squared_numbers)
[9, 16, 25]
>>> list(squared_numbers)
[]
Как мы видим, при создании списка из генераторного выражения, в нём оказываются все элементы, после искомого. При повторном же создании, вполне ожидаемо, список оказывается пуст.
3. Распаковка словаря
При использовании в цикле for
, словарь будет отдавать ключи:
>>> fruits_amount = {'apples': 2, 'bananas': 5}
>>> for fruit_name in fruits_amount:
... print(fruit_name)
...
apples
bananas
Так как распаковка опирается на тот же протокол итератора, то и в переменных оказываются именно ключи:
>>> x, y = fruits_amount
>>> x
'apples'
>>> y
'bananas'
Выводы
Последовательности — итерируемые объекты, но не все итерируемые объекты — последовательности.
Итераторы — самая простая форма итерируемых объектов в Python.
Любой итерируемый объект реализует протокол итератора. Понимание этого протокола — ключ к пониманию любых итераций в Python.
python — что означает [:]?
Переполнение стека- Товары
- Клиенты
- Случаи использования
- Переполнение стека Публичные вопросы и ответы
- Команды Частные вопросы и ответы для вашей команды
- предприятие Частные вопросы и ответы для вашего предприятия
- работы Программирование и связанные с ним технические возможности карьерного роста
- Талант Нанимать технический талант
- реклама Связаться с разработчиками по всему миру
— Что означает + = в Python?
Переполнение стека- Товары
- Клиенты
- Случаи использования
- Переполнение стека Публичные вопросы и ответы
- Команды Частные вопросы и ответы для вашей команды
- предприятие Частные вопросы и ответы для вашего предприятия
- работы Программирование и связанные с ним технические возможности карьерного роста
- Талант Нанимать технический талант
- реклама Связаться с разработчиками по всему миру
- Товары
- Клиенты
- Случаи использования
- Переполнение стека Публичные вопросы и ответы
- Команды Частные вопросы и ответы для вашей команды
- предприятие Частные вопросы и ответы для вашего предприятия
- работы Программирование и связанные с ним технические возможности карьерного роста
- Талант Нанимать технический талант
— Что значит « в Python?
Переполнение стека- Товары
- Клиенты
- Случаи использования
- Переполнение стека Публичные вопросы и ответы
- Команды Частные вопросы и ответы для вашей команды
- предприятие Частные вопросы и ответы для вашего предприятия
- работы Программирование и связанные с ним технические возможности карьерного роста
- Талант Нанимать технический талант
- реклама Связаться с разработчиками по всему миру
Загрузка…