Типизация в Python Python

Типизация в Python

Очень часто языки программирования сравнивают по их типизации. Иначе говоря — по тому, как устроена их система типов. Давайте разберемся, какая типизация у Python, и что это означает.

Типизация в Python

Для начала мы можем смело сказать, что типизация в Python существует, а следовательно, он относится к типизированным языкам. У многих низкоуровневых языков (вроде ассемблера) вообще нет типизации — любые структуры в них — не более чем набор битов. Типизация позволяет упростить процесс обработки информации. Если данные имеют тип, то машина будет взаимодействовать с ними по правилам, установленным для этого типа.

Неявная типизация

Неявная типизация подразумевает возможность создавать объекты, не указывая их тип.

a = 1  # int
b = 1.1  # float
c = 'a'  # str

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

def func(a: int, b: str) -> float:
    return round(float(a / len(b)), 2)


var: float = func(3, [1, 1, 1])  # 1.0

# Expected type 'str', got 'list[int]' instead

Это называется аннотацией типов. Ее возможности сильно расширяет модуль typing, активно развивающийся с версии Python 3.5. Аннотации никак не влияют на выполнение программы, но IDE может считывать их и предупреждать, если вы использовали не тот тип.

Сильная типизация

Python - язык с сильной типизацией. Это означает, что различные типы нельзя смешивать в одних выражениях.

2 + '2'
# Traceback (most recent call last):
#   File "C:\main.py", line 1, in <module>
#     2 + '2'
#     ~~^~~~~
# TypeError: unsupported operand type(s) for +: 'int' and 'str'

Если бы Python был языком со слабой типизацией, результатом выполнения такого кода стало бы 22. В ситуации, когда смешиваются разные типы, слабо типизированные языки могут неявно приводить значения к одному из них. Иногда это вызывает непредсказуемые последствия, например, если по неосторожности использовать строку с цифрами вместо числа. Однако Python допускает подобное в некоторых случаях:

2 + 2.2
# 4.2

Типы int и float могут свободно взаимодействовать. Это продиктовано удобством и естественностью таких преобразований.

Сами понятия "сильной" и "слабой" типизации довольно размыты и зависят от множества конкретных решений при разработке языка. Правильнее будет говорить, что какие-то языки более сильные, чем другие.

Динамическая типизация

Python - язык с динамической типизацией. Это означает, что с определенным типом связывается не переменная, а ее значение. Если бы Python был языком со статической типизацией, мы бы не смогли сделать так:

a = 1
a = 'a'
a = SomeClass()

Динамическая типизация - одна из причин популярности Python. Для начала, это просто удобно. Программа может менять типы переменных на лету, пользуясь их особенностями.

a = (1, 1, 1, 3, 1, 1)
a = list(set(a))
# [1, 3]

Не менее важно то, что динамическая типизация позволяет максимально естественно абстрагироваться от типов и заниматься обобщенным программированием.

def second(a):
    try:
        return a[1]
    except TypeError:
        return None

second([1, 2])  # 2
second('abcd')  # b
second(1)  # None

Однако за такое удобство приходится платить. Динамическая типизация, вместе с интерпретацией кода, стала причиной главнейшего проклятия Python - низкой скорости работы. К тому же, в языках со статической типизацией есть свои механизмы обобщенного программирования, использующие шаблоны или дженерики.

Утиная типизация

"If it looks like a duck, swims like a duck, and quacks like a duck, then it probably is a duck."

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

class SomeClass:
    length = 12

    def __len__(self):
        return self.length


len('123')
# 3
len([1, 2])
# 2
len(SomeClass())
# 12
len(123)
# Traceback (most recent call last):
#   File "C:\main.py", line 13, in <module>
#     len(123)
# TypeError: object of type 'int' has no len()

Заключение

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

Практический Python для начинающих
Практический Python для начинающих

Станьте junior Python программистом за 7 месяцев

 7 месяцев

Возможно будет интересно

🏆 Hello, world! Python
Новичок
🏆 Hello, world!

Мы вчера запустили новый www.pylot.me. Должны были в следующую среду, но запустили вчера.

2022-10-04
Как практиковаться в Python? Python
Новичок
Как практиковаться в Python?

Для улучшения качества знаний и повышения уровня программиста, необходим постоянный практикум. Где можно это организовать самостоятельно, и как практиковаться в Python?

2022-10-19
Чем занимаются программисты на питоне? Python
Новичок
Чем занимаются программисты на питоне?

Узнайте, чем занимаются программисты на Питоне.

2022-11-01