Типизация в 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 # 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 # len(123) # TypeError: object of type 'int' has no len()
Заключение
Каждый из вариантов типизации имеет свои преимущества и недостатки. Создатели языков программирования выбирали их комбинации, исходя из своих целей. Гвидо Ван Россум хотел сделать Python максимально удобным и понятным. Благодаря неявной, динамической и утиной типизации, программы на Python выходят лаконичными и простыми для понимания. В то же время, Python имеет строгую типизацию, почти не допускающую неявных преобразований.
Практический Python для начинающих
Станьте junior Python программистом за 7 месяцев
Python: Сильная (или Строгая) типизация
Python — один из языков, который строго относится к типам данных. Поэтому на любую несовместимость типов он ответит ошибкой. Все дело в сильной типизации.
Нам известно про два разных типа данных: числа и строки. Например, мы могли складывать числа, потому что операция сложения — это операция для типа «числа». А что, если применить эту операцию не к двум числам, а к числу и строке?
print(1 + '7') # TypeError: unsupported operand type(s).
Python не разрешит сложить число 1 и строку ‘7’ , потому что это значения разных типов. Нужно сначала либо сделать строку числом, либо число строкой. Как это сделать, мы поговорим позже.
Такое педантичное отношение к совместимости типов называется строгой типизацией или сильной типизацией. Python — язык со строгой типизацией.
Не все языки так делают. Например, PHP — это язык со слабой типизацией. Он знает о существовании разных типов, но относится к их использованию не очень строго. PHP пытается преобразовывать информацию, когда это кажется разумным. То же самое относится к JavaScript:
// Как тебе такое, Илон Маск? // Число 1 + Строка 7 = Строка 17 1 + '7'; // '17'
С одной стороны, автоматическое неявное преобразование типов и правда кажется удобным. Но на практике это свойство языка создает множество ошибок и проблем, которые трудно найти. Код может иногда работать, а иногда не работать — в зависимости от того, «повезло» ли с автоматическим преобразованием. Программист это заметит не сразу и потратит много времени на отладку.
Задание
Выведите на экран результат выражения: 7 — (-8 — -2) . Попробуйте сделать число 7 не числом, а строкой. Сработает ли такой код? Поэкспериментируйте с другими числами тоже.
Упражнение не проходит проверку — что делать?
Если вы зашли в тупик, то самое время задать вопрос в «Обсуждениях». Как правильно задать вопрос:
- Обязательно приложите вывод тестов, без него практически невозможно понять что не так, даже если вы покажете свой код. Программисты плохо исполняют код в голове, но по полученной ошибке почти всегда понятно, куда смотреть.
В моей среде код работает, а здесь нет
Тесты устроены таким образом, что они проверяют решение разными способами и на разных данных. Часто решение работает с одними входными данными, но не работает с другими. Чтобы разобраться с этим моментом, изучите вкладку «Тесты» и внимательно посмотрите на вывод ошибок, в котором есть подсказки.
Мой код отличается от решения учителя
Это нормально , в программировании одну задачу можно выполнить множеством способов. Если ваш код прошел проверку, то он соответствует условиям задачи.
В редких случаях бывает, что решение подогнано под тесты, но это видно сразу.
Прочитал урок — ничего не понятно
Создавать обучающие материалы, понятные для всех без исключения, довольно сложно. Мы очень стараемся, но всегда есть что улучшать. Если вы встретили материал, который вам непонятен, опишите проблему в «Обсуждениях». Идеально, если вы сформулируете непонятные моменты в виде вопросов. Обычно нам нужно несколько дней для внесения правок.
Кстати, вы тоже можете участвовать в улучшении курсов: внизу есть ссылка на исходный код уроков, который можно править прямо из браузера.
Решение модуля 2.1 Добрый, добрый Python
Модуль 2.1 — Переменные, оператор присваивания, функции type и id.
Что представляет собой переменная в Python?
ссылка на объект в памяти
создает переменную, если ее ранее не было связывает переменную с данными
Какая типизация реализована в Python? Отметьте все верные варианты.
динамическая типизация строгая типизация
Что происходит при присваивании одной переменной другой (a = b)?
копирование ссылки и обе переменные ссылаются на один и тот же объект
Как называется присваивание вида a = b = c = 0?
каскадным присваиванием
Как называется присваивание вида a, b = 1, 2?
множественным присваиванием
Для чего используется функция type?
для определения типа переменной или объекта
Выберите только правильные имена переменных.
P.S. Все буквы латинские
TT1 var_a __arg_c__ _b d25 S
Различаются ли имена переменных arg, Arg, ARG?
Выберите верные варианты присвоения данных переменной b (считается, что других переменных в программе нет).
b = 5.8 b = "hello" b = "True"
Что произойдет, если функции type присвоить число 7 (type = 7)?
переменная type будет ссылаться на число 7
Если у вас не отображается решение последних задач, значит у вас включен блокировщик рекламы который вырезает эти ответы
Подробнее о Python — Python: Настройка окружения
Чтобы глубже погрузиться в настройку окружения Python, нам нужно вспомнить теоретические основы этого языка. Они помогут глубже разобраться в окружении и работе с ним.
Язык программирования
Что такое язык программирования? За этим понятием скрываются две связанных, но независимых темы.
С одной стороны, языком программирования называют синтаксические и семантические правила, по которым записывается и работает исходный код.
В отличие от естественных языков, эти правила достаточно строги. Любая мельчайшая ошибка приведет к тому, что код либо не запустится, либо будет работать некорректно.
Например, в Python нельзя написать my name = 5 с пробелом в имени переменной. Эти правила существуют не только в книгах, но и в головах конкретных программистов и разработчиков языка.
Часто весь свод правил существует в виде отдельного специального документа и называется спецификацией.
С другой стороны, языком программирования называют программу, которая запускает и компилирует наш код. Обычно ее называют средой выполнения.
Среда выполнения — это конкретное воплощение спецификации, поэтому ее иногда называют реализацией.
У конкретного языка может существовать несколько реализаций, в том числе эталонная реализация, на которую равняются все остальные. Различные реализации могут разрабатываться разными людьми и компаниями.
У Python нет выделенной спецификации, но есть эталонная реализация. Она называется CPython — это интерпретатор Python, реализованный на языке C. Если вы слышите разговоры про Python, то скорее всего имеется в виду именно эталонная реализация CPython.
Прочие варианты обычно имеют свои названия. Например, реализация языка для запуска программ на платформе .NET называется IronPython .
Python
Python — интерпретируемый язык программирования с сильной динамической типизацией. Разберем эти слова по отдельности.
Интерпретируемый язык программирования
Существуют языки программирования, в которых есть стадия компиляции в машинный код. Например, компиляция есть у языков C, Rust, Go. Это компилируемые языки.
Python работает по-другому. Программа исполняется интерпретатором шаг за шагом, а не запускается напрямую на процессоре компьютера. Поэтому для запуска программы на Python всегда нужна среда исполнения (интерпретатор). Только она может выполнять Python-программы.
Строго говоря, и у Python есть фаза компиляции, но при этом внешне он ведет себя именно как интерпретируемый язык программирования:
- Вы запускаете программу
- Интерпретатор открывает файлы программы и загружает из них исходный код
- Затем интерпретатор преобразует исходный код в байткод, проверяет ошибки синтаксиса и начинает исполнять по шагам
Динамическая типизация
Есть языки, в которых интерпретатор производит проверку типов, доступности функций и переменных во время выполнения кода. Такие языки называются динамически типизированными. Если мы случайно ошиблись и вызвали несуществующую функцию, то ошибка всплывет только во время вызова этой функции.
В статически типизированных языках подобные ошибки отслеживаются раньше — на этапе анализа исходного текста без запуска кода на выполнение. Слово «статический» как раз означает, что программа не выполняется.
Обычно статическими проверками занимаются компиляторы, но существуют и специальные инструменты — статические анализаторы кода. Для некоторых языков с динамической типизацией такие анализаторы тоже существуют, но отслеживают значительно меньшее число ошибок.
Сильная типизация
Открыть доступ
Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно
- 130 курсов, 2000+ часов теории
- 1000 практических заданий в браузере
- 360 000 студентов
Наши выпускники работают в компаниях: