Функция Python type() — это базовая функция Python для работы с типами. Как часть реализации Python, это часть ядра языка.
- Для чего нужна функция type() в Python?
- Используйте type() для определения типа объекта
- Создайте новый тип с помощью type()
- Как работает функция Python type()?
- Как функция type() используется в Python?
- Проверьте аргументы функции в Python на их тип
- Отладка Python REPL с помощью функции type()
- Динамически создавать классы Python с помощью функции type()
- Где функция type() достигает своего предела?
- Разбейте иерархию наследования с помощью isinstance()
- Упростите определение типа объекта Python с помощью match-case
Для чего нужна функция type() в Python?
Функция type() используется в Python для двух очень разных вариантов использования :
- Получить тип объекта Python
- Динамически создать новый тип
Сначала рассмотрим первый случай. Это гораздо полезнее в повседневном использовании.
Используйте type() для определения типа объекта
Python — это язык с динамической типизацией. Это означает, что типы определяются во время выполнения и привязываются к значениям, а не к переменным. Это обстоятельство приводит к необходимости определения типа объекта во время выполнения.
Мы вызываем функцию Python type(), передавая объект в качестве единственного параметра. В качестве возврата мы получаем тип объекта, например. Б. intили str:
# Type of `42` is `int` assert type(42) == int # Type of `str(42)` is `str` assert type(str(42)) == str
Если мы вызовем функцию type() в Python REPL, текстовое представление будет содержать «класс» вместо «тип» :
# Returns "<class 'int'>" inside REPL type(42)
То, что на первый взгляд кажется запутанным, имеет смысл, потому что в Python применяется следующее: «Все является объектом». В Python тип объекта — это его класс. Таким образом, вызов функции type() обычно эквивалентен чтению атрибута __class__:
# Should hold in most cases assert type(obj) is obj.__class__
Создайте новый тип с помощью type()
Теперь давайте посмотрим на второе использование функции type(). Функция, вызываемая с тремя аргументами, позволяет нам динамически создавать новый тип:
type(name, bases, dict, **kwds)
В этой форме функция Python type() действует аналогично ключевому classслову. Код примерно соответствует следующему определению класса:Type = type(«Type», bases, dict)
class <Type>(<bases>): <dict>
Ниже мы покажем несколько конкретных примеров использования функции Python type() для создания новых типов. Сначала обзор аргументов:
| name | bases | dict | **kwds |
| Имя нового типа в виде строки | Кортежи с базовыми классами | Dict с атрибутами нового класса | Дополнительные аргументы в пользу создания экземпляра метакласса |
Как работает функция Python type()?
При использовании функции type() для определения типа объекта возвращаемое значение является не строкой, а отдельным объектом :
# Value returned by `type(42)` is not a string assert type(42) != 'int' # We get back an object named `int` assert type(42) == int
Давайте рассмотрим несколько примеров возвращаемых значений из функции type() для объектов разных типов:
# Python objects of different types different_objs = None, True, 42, 'John', ('Walter', 'White'), ... # Print out the type of each object for obj in different_objs: print(f"{obj}: {type(obj)}")
| вызов типа() | Текстовое представление |
| type(None) | <class ‘NoneType’> |
| type(True) | <class ‘bool’> |
| type(42) | <class ‘int’> |
| type(‘John’) | <class ‘str’> |
| type((‘Walter’, ‘White’)) | <class ‘tuple’> |
| type(…) | <class ‘ellipsis’> |
Возникает вопрос: каков тип объекта, возвращаемого функцией type() ? Давай попробуем. Мы вызываем функцию Python type() и передаем возвращаемое значение другого вызова type():
# Returns: "<class 'type'>" type(type(42))
Мы видим: помимо встроенной в Python функции type() существует тип с таким же именемtype. Это тип всех других типов Python, как мы показываем:
# DifferentPython objects different_objs = None, True, 42, 'John', ('Walter', 'White'), ... # Check the type of each object's type for obj in different_objs: # Show that the type's type is always `type` assert type(type(obj)) is type
Таким образом, тип любого типа Python — это type. Если это звучит запутанно, то это еще лучше: даже тип объекта typeсноваtype. Это продолжается вечно, как змея, кусающая себя за хвост:
# It's `type` all the way down assert type(type(type(type))) is type
Устранение путаницы требует более глубокого понимания ООП-системы Python. Встроенный typeобъект Python представляет то, что называется метаклассом. Метакласс относится к классу так же, как класс к объекту. Другими словами, метакласс — это шаблон для класса, а класс — это шаблон для объекта:
| Template | Instanz |
|---|---|
| Klasse | Objekt |
| Metaklasse | Klasse |
Beispiel: type | int, stretc. |
Beispiel:int | 42 |
Beispiel: str | “Walter White” |
Как функция type() используется в Python?
Функция Python type() обычно используется для определения типа объекта во время выполнения. Это полезно, потому что Python — язык с динамической типизацией. В статически типизированном языке, таком как Java, тип привязывается к переменной посредством объявления и не может быть изменен во время выполнения:
// Declare variable as `boolean` boolean answer; // Attempting to assign `int` value // Throws type error answer = 42;
Напротив, переменные в Python — это просто имена, которые относятся к типизированным значениям. В любой момент выполнения кода имя может ссылаться на значение другого типа. Итак, чтобы определить тип переменной Python во время выполнения, нам нужна функция type():
# Assign boolean value answer = True # Show that type is `bool` assert type(answer) is bool # Reassign integer value answer = 42 # Show that type is now `int` assert type(answer) is int
Проверьте аргументы функции в Python на их тип
При определении функции часто необходимо проверять аргументы по определенным критериям. Например, аргумент может находиться только в определенных пределах или разрешены только аргументы подходящих типов. Это позволяет избежать ошибок во время выполнения.
Давайте воспользуемся примером, чтобы проиллюстрировать использование функции type(): Мы определяем функцию, которая суммирует список чисел. Чтобы это работало, нам нужно убедиться, что каждый аргумент на самом деле является числом. Мы используем type() внутри assertоператора:
# Function to add up numeric arguments def add_numbers(*args): result = 0 # Check each argument for arg in args: # Abort with error message if argument is not an `int` or `float` assert type(arg) in (int, float), f"Argument `{arg}` is not a number" # Add argument's value to total result += arg return result # Show that it works for numbers assert add_numbers(35, 7) == 42 # The following will fail add_numbers(29, 'thirteen')
Отладка Python REPL с помощью функции type()
Одним из преимуществ использования интерпретируемого языка, такого как Python, является то, что код может выполняться интерактивно в REPL (Read-Eval-Print-Loop). Такой подход позволяет быстро создавать прототипы и выполнять прямую отладку путем проверки объектов в памяти.
Давайте представим следующий сценарий: наш код содержит переменную answer, которая должна содержать логическое значение. Мы определяем, что тип не соответствует ожидаемому, и используем функцию Python type() для вывода фактического типа. Как оказалось, мы случайно написали логическое значение в кавычках — распространенная оплошность среди новичков:
# Accidentally set to string answer = 'False' # Assertion will fail assert type(answer) is bool # Correct to boolean value answer = False # Now assertion holds assert type(answer) is bool
Динамически создавать классы Python с помощью функции type()
Как мы видели, классы Python можно создавать динамически, то есть во время выполнения, с помощью функции type(). Это полезно, помимо прочего, для семейств классов, которые мы проиллюстрируем на примере тегов HTML. Во-первых, мы создаем базовый класс Tag, объекты которого могут представлять себя в виде HTML-кода:
# Class representing HTML tag class Tag: # Initialize HTML tag with contents def __init__(self, *args): # Join contents of tag self.content = "".join([arg.__str__() for arg in args]) # String representation returns HTML def __str__(self): return f"<{self.name}>{self.content}</{self.name}>"
Затем мы специализируем базовый класс путем наследования для соответствующих конкретных тегов, таких как или. Для этого мы вызываем функцию type() с тремя аргументами:
# Create `P` class P = type('P', (Tag,), {"name": 'p'})
1. Имя нового класса в виде строки.
2. Кортежи с базовыми классами.
Python допускает множественное наследование; чтобы вывести только из одного класса, мы используем обозначение.(ClassName,)
3. Dict с названием класса и любыми другими записями.
Записи также могут быть функциями.
Затем мы создаем экземпляр pтега и проверяем правильность рендеринга:
# Instantiate `p` tag greeting = P("Hello world") assert str(greeting) == '<p>Hello world</p>'
Тот же эффект может быть достигнут с помощью аналогичного определения класса :
# Create `P` class class P(Tag): name = 'p'
В качестве другого примера мы используем type() для создания классов для заголовков. Поскольку классы создаются динамически, классы для всех шести уровней заголовков могут быть созданы одним махом с использованием понимания списка :
h_1_to_6 = ( f"h{n}" for n in range(1, 7) ) headings = [type(heading, (Tag,), {"name": heading}) for heading in h_1_to_6]
Как мы показали, стоит использовать функцию type() для удобного создания нескольких связанных подклассов. Мы покажем этот подход на более сложном примере определения классов для моделирования игральных карт. Во-первых, мы определяем суперкласс Cardпо classключевому слову:
# Class representing abstract playing card class Card: def __init__(self, number): self.number = number # String representation def __str__(self): return f"{self.number} of {self.suite}"
Затем мы создаем подклассы для четырех мастей карт, используя type():
# Create concrete types for each suite Clubs = type('Clubs', (Card,), {'suite': 'Clubs'}) Diamonds = type('Diamonds', (Card,), {'suite': 'Diamonds'}) Hearts = type('Hearts', (Card,), {'suite': 'Hearts'}) Spades = type('Spades', (Card,), {'suite': 'Spades'})
Отдельные карты теперь могут быть созданы без проблем :
# Instantiate a 7 of Spades card = Spades(7) # Show that it worked assert str(card) == '7 of Spades'
Где функция type() достигает своего предела?
Функция Python type() полезна. Однако есть некоторые случаи использования, когда функция достигает своих пределов, когда дело доходит до их решения. К счастью, Python знает соответствующие подходы; давайте посмотрим на некоторые из них.
Разбейте иерархию наследования с помощью isinstance()
type() определяет только фактический тип объекта Python, игнорируя иерархию наследования. Мы проиллюстрируем возникшую дилемму на примере с игральными картами из предыдущего раздела. Тип пиковой 7 должен быть как «игральной картой», так и «пиковой». Однако это нельзя определить с помощью type():
# Create a Seven of Spades card = Spades(7) # Our card is a Spade alright assert type(card) is Spades # But not a card?? assert type(card) is not Card
Чтобы правильно декодировать лежащий в основе полиморфизм, мы используем функцию.isinstance()
# Seven of Spades is a `Spade` assert isinstance(card, Spades) # And is also a `Card` assert isinstance(card, Card)
Упростите определение типа объекта Python с помощью match-case
Как мы показали ранее, функция type() часто используется для определения типа объекта во время выполнения. Чтобы различать несколько возможных типов, можно использовать конструкцию :if-elif-else
# Determine type of object if type(obj) is int: print("Int") elif type(obj) is float: print("Float") elif type(obj) is ...: print("...") else: print("Something else")
Однако, начиная с версии 3.10, Python знает это утверждение. Помимо прочего, это позволяет распознавать типы без вызова функции type().match-case
caseФункции конструктора, подобные или, могут использоваться внутри блока. Блок соответствует, если объект имеет соответствующий тип:int(obj)str(obj)
# Example object obj = 42 # Determine object type match obj: case int(obj): print(f"{obj} is `int`") case float(obj): print(f"{obj} is `float`") case _: print(f"{obj} is something else")








