Некоторые особенности языка Python

Синтаксис языка Python весьма мощный и выразительный. Следовательно, на нем можно легко реализовать любой алгоритм. Возможно, именно поэтому Python очень популярен в машинном обучении, так как там при разработке моделей нужно много экспериментировать.

Новичку в Python, имеющему опыт работы в других языках программирования, синтаксис языка Python будет понятен, но иногда может показаться странным. Если вы, переходя на Python, раньше писали на C++ или Java, то, скорее всего, ваши программы не будут сразу «питоническими» (Pythonic).

В данном руководстве мы как раз рассмотрим несколько важных языковых конструкций, которые отличаются от других языков программирования.

Итак, приступим.

Оглавление

  1. Операторы
  2. Встроенные структуры данных
  3. Специальные переменные
  4. Встроенные функции

Операторы

Большая часть операторов используется в Python точно так же как и в других языках. Настоящая таблица, где операторы Python расположены в порядки приоритета исполнения, взята из главы 6 Python Language Reference:

ОПЕРАТОРОПИСАНИЕ
(expressions…), [expressions…], {key: value…}, {expressions…}связывание или скобочное выражение, отображение списка, отображение словаря, отображение множества
x[index], x[index:index], x(arguments…), x.attributeобращение по индексу, вырезка, вызов функции, ссылка на атрибут
await xотложенное исполнение
**возведение в степень
+x, -x, ~xположительное, отрицательное , побитовое NOT
*, @, /, //, %умножение, матричное умножение, деление, целочисленное деление, остаток от деления
+, –сложение и вычитание
<<, >>сдвиги
&побитовое AND
^побитовое XOR
|побитовое OR
in, not in, is, is not, <, <=, >, >=, !=, ==сравнения и проверки принадлежности
not xбулево NOT
andбулево AND
orбулево OR
if – elseусловный оператор
lambdaлямбда выражения
:=присваивание

Вот ключевые отличия от других языков:

  • булевы операторы прописаны буквами, в то время как побитовые операторы — символами &^ и |;
  • возведение в степень производиться следующим образом 2 ** 3;
  • целочисленное деление производится посредством оператора //, а оператор / всегда в результате дает число с плавающей запятой (тип float);
  • тернарный оператор: если вам знакомо выражение (x)?a:b из языка C, то в Python это будет выглядеть как if x else b;
  • сравнение двух сущностей может производится как при помощи оператора ==, так и с помощью оператора is. Оператор == похож на аналогичные операторы в других языках, но он несколько строже. Он требует, чтобы переменные ссылались на один и тот же объект;

В Python в операторах сравнения допускается конкатенация. Например, чтобы проверить, находится ли значение в диапазоне от -1 до 1 мы можем написать:

if value > -1 and value < 1:
    ...

Но мы также можем то же самое сделать следующим образом:

if -1 < value < 1:
    ...
[python_ad_block]

Встроенные структуры данных

Как и во многих других языках, в Python есть целочисленный тип данных и числа с плавающей запятой. Но есть также комплексные числа (например, 3 + 1j), булевы (логические) константы (True и False), строки, а также фиктивный тип None.

Но основная сила языка Python происходит из того, что в нем есть встроенные типы контейнеров: массивы под названием списки (list), которые могут автоматически расширяться, и ассоциативные массивы или хэш-таблицы под названием словари (dict). Также существуют кортежи (tuple) — неизменяемые списки и множества (set), состоящие из уникальных (неповторяющихся) элементов. Например, в C++, чтобы получить такие возможности, нужно импортировать библиотеку STL.

Словарь (dict), вероятно, является самой мощной структурой данных в Python и создает нам определенные удобства при написании кода. Например, в задаче классификации изображений собак и кошек наша модель машинного обучения дает нам на выходе значение 0 (для кошек) или 1 (для собак). Если вы хотите напечатать название распознанного изображения, мы можем написать следующий код:

value = 0 # This is obtained from a model
 
value_to_name = {0: "cat", 1: "dog"}
print("Result is %s" % value_to_name[value])

Результат:

Result is cat

В данном случае мы использовали словарь value_to_name в качестве справочной таблицы. Точно так же мы можем использовать словарь для создания счетчика:

sentence = "Portez ce vieux whisky au juge blond qui fume"
counter = {}
for char in sentence:
    if char not in counter:
        counter[char] = 0
    counter[char] += 1
 
print(counter)

Результат:

{'P': 1, 'o': 2, 'r': 1, 't': 1, 'e': 5, 'z': 1, ' ': 8, 'c': 1, 'v': 1, 'i': 3, 'u': 5, 'x': 1, 'w': 1, 'h': 1, 's': 1, 'k': 1, 'y': 1, 'a': 1, 'j': 1, 'g': 1, 'b': 1, 'l': 1, 'n': 1, 'd': 1, 'q': 1, 'f': 1, 'm': 1}

Данный код создаёт словарь под названием counter, который отображает каждый символ из предложения и количество его вхождений в него.

Списки Python также имеют мощный синтаксис. В отличие от некоторых других языков, в список Python мы можем поместить что угодно:

A = [1, 2, "fizz", 4, "buzz", "fizz", 7]
A += [8, "fizz", "buzz", 11, "fizz", 13, 14, "fizzbuzz"]
print(A)

Результат:

[1, 2, 'fizz', 4, 'buzz', 'fizz', 7, 8, 'fizz', 'buzz', 11, 'fizz', 13, 14, 'fizzbuzz']

Также для конкатенации списков мы можем использовать оператор +. Выше для расширения списка A мы использовали оператор +=.

Списки Python имеют синтаксис срезов. Например, мы можем взять срез списка A из приведенного выше примера. То есть мы можем произвести операцию A[1 : 3], что даст нам список из 1 и 2 элементов списка A. Соответственно A[1:1] даст нам пустой список. Разумеется, мы также можем использовать данный синтаксис для присвоения новых значений либо удаления элементов списка. Например, вот так:

 ...
A[2:2] = [2.1, 2.2]
print(A)

Результат:

[1, 2, 2.1, 2.2, 'fizz', 4, 'buzz', 'fizz', 7, 8, 'fizz', 'buzz', 11, 'fizz', 13, 14, 'fizzbuzz']

И затем вот так:

...
A[0:2] = []
print(A)

Результат:

[2.1, 2.2, 'fizz', 4, 'buzz', 'fizz', 7, 8, 'fizz', 'buzz', 11, 'fizz', 13, 14, 'fizzbuzz']

У кортежей (tuple) схожий со списками синтаксис, за исключением того, что используются круглые скобки вместо квадратных.

A = ("foo", "bar")

Кортежи неизменяемы. Это означает, что после того как мы их определили, изменять их нельзя. Если вы в Python возьмете в скобки несколько элементов, разделенных при этом запятыми, то это будет считаться кортежем.

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

a = 42
b = "foo"
print("a is %s; b is %s" % (a,b))
a, b = b, a # swap
print("After swap, a is %s; b is %s" % (a,b))

Результат:

a is 42; b is foo
After swap, a is foo; b is 42

Наконец, как вы видели в приведенных выше примерах, строки Python поддерживают замену на лету. Мы можем использовать %s для замены строки или %d для замены целого числа, что аналогично использованию функции printf() в языке C. Мы также можем использовать %.3f для замены числа с плавающей запятой на число с тремя десятичными знаками после запятой. Ниже приведен пример такого кода:

template = "Square root of %d is %.3f"
n = 10
answer = template % (n, n**0.5)
print(answer)

Результат:

Square root of 10 is 3.162

И это один из многих способов для решения подобной задачи. Можно, например, использовать f-строки или метод format().

Специальные переменные

В языке Python есть несколько предопределенных «специальных переменных». Переменная __name__ сообщает текущее пространство имен, а __file__ сообщает имя файла сценария.

Еще больше таких переменных можно найти внутри объектов, но почти все из них не используются в обычном режиме напрямую.

По соглашению (т.е. это просто обычай, никто не заставляет вас это делать) мы объявляем внутренние переменные с подчеркиванием или двойным подчеркиванием в качестве префикса. Если вы пришли из C++ или Java, то они эквивалентны закрытым членам класса, хотя технически и не являются приватными.

Одна примечательная «особая» переменная, которую вы часто можете видеть в коде Python, — это _, то есть просто символ подчеркивания. По соглашению так именуют малозначимые переменные. Откуда же берутся такие переменные? Например, иногда надо недолго хранить значение, возвращаемое функцией. В примере ниже мы сканируем строки датафрейма из библиотеки pandas:

import pandas as pd
A = pd.DataFrame([[1,2,3],[2,3,4],[3,4,5],[5,6,7]], columns=["x","y","z"])
print(A)

for _, row in A.iterrows():
    print(row["z"])

Результат:

x y z
0 1 2 3
1 2 3 4
2 3 4 5
3 5 6 7

3
4
5
7

В приведенном выше примере мы видим, что датафрейм имеет три столбца «x», «y» и «z», а строки проиндексированы от 0 до 3.

При помощи метода A.iterrows() мы получаем индекс и саму строку, но индекс нас абсолютно не интересует. Нам приходится создать переменную для его хранения, хотя использовать его мы не будем.

Чтобы дать понять, что мы не собираемся его использовать, мы используем _ в качестве переменной для хранения индекса, а строка сохраняется в переменной row.

Встроенные функции

В языке Python есть небольшое количество функций, которые определены как встроенные, в то время как для остальных функций нужно импортировать внешние библиотеки. Список этих функций доступен в Стандартной документации Python. Ниже мы приводим эти функции так, как они определены для версии Python 3.10.

abs()
aiter()
all()
any()
anext()
ascii()
bin()
bool()
breakpoint()
bytearray()
bytes()
callable()
chr()
classmethod()
compile()
complex()
delattr()
dict()
dir()
divmod()
enumerate()
eval()
exec()
filter()
float()
format()
frozenset()
getattr()
globals()
hasattr()
hash()
help()
hex()
id()
input()
int()
isinstance()
issubclass()
iter()
len()
list()
locals()
map()
max()
memoryview()
min()
next()
object()
oct()
open()
ord()
pow()
print()
property()
range()
repr()
reversed()
round()
set()
setattr()
slice()
sorted()
staticmethod()
str()
sum()
super()
tuple()
type()
vars()
zip()
__import__()

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

Функция zip() позволяет объединять несколько списков вместе. Вот пример ее использования:

a = ["x", "y", "z"]
b = [3, 5, 7, 9]
c = [2.1, 2.5, 2.9]
for x in zip(a, b, c):
    print(x)

Результат:

('x', 3, 2.1)
('y', 5, 2.5)
('z', 7, 2.9)

И также эта функция удобна когда вам нужно наоборот, «развернуть» список списков.

a = ["x", "y", "z"]
b = [3, 5, 7, 9]
c = [2.1, 2.5, 2.9]
for x in zip(a, b, c):
    print(x)

Результат:

('x', 'y', 'z')
(3, 5, 7)
(2.1, 2.5, 2.9)

Функция enumerate() очень удобна тогда, когда вам нужно пронумеровать список элементов. Вот пример такого применения:

a = ["quick", "brown", "fox", "jumps", "over"]
for num, item in enumerate(a):
    print("item %d is %s" % (num, item))

Результат:

item 0 is quick
item 1 is brown
item 2 is fox
item 3 is jumps
item 4 is over

Это эквивалентно следующему коду без использования функции enumerate():

a = ["quick", "brown", "fox", "jumps", "over"]
for num in range(len(a)):
    print("item %d is %s" % (num, a[num]))

По сравнению с другими языками, цикл for в Python предназначен для итерации по заранее определенному диапазону, а не для вычисления значений в каждой итерации. Другими словами, нет прямого эквивалента следующему циклу for в языке C:

for (i=0; i<100; ++i) {
...
}

Чтобы сделать тоже самое в Python, нам нужно использовать функцию range():

for i in range(100):
    ...

В аналогичном смысле есть некоторые функции, которые управляют списками (или структурами данных, которые подобны спискам, их в языке Python называют «итерациями» или итерируемыми структурами):

  • max(a): находит максимальное значение списка a.
  • min(a): находит минимальное значение списка a.
  • sum(a): вычисляет сумму элементов списка a.
  • reverse(a): итерирует список a в обратном порядке.
  • sorted(a): возвращает копию списка a с отсортированными элементами.

Дальнейшее изучение

В данное статье мы лишь чуть-чуть осветили некоторые важные особенности языка Python. Общепризнано, что нет более авторитетной документации, чем официальная документация с сайта Python.org. Всем новичкам следует начать с учебника Python (The Python Tutorial) и проверить сведения о синтаксисе в Справочнике по языку Python (The Python Language Reference), а в Стандартной библиотеке (The Python Standard Library) — дополнительные библиотеки, которые поставляются с установкой Python.

Что касается книг, то в первую очередь стоит упомянуть старый, но очень хороший учебник Лутца «Изучаем Python». После этого книга «Fluent Python» Luciano Ramalho лучше поможет понять вам внутреннее устройство языка.

Но если вы хотите освоить язык быстро, то вам может помочь книга Свейгарда «Автоматизация рутинных задач с помощью Python» с конкретными примерами. После первого знакомства с языком вам, возможно, захочется почитать советы по конкретным задачам. Здесь вам придет на помощь «Python Cookbook».

Заключение

В этом руководстве мы с вами рассмотрели отличительные особенности языка Python. В частности, вы познакомились с операторами языка Python, некоторыми возможностями встроенных структур данных и несколькими часто используемыми встроенными функциями.

Перевод статьи Adrian Tam «Some Language Features in Python«.