Что означает -> в определениях функций Python?
Недавно я заметил кое-что интересное, глядя на спецификацию грамматики Python 3.3:
Необязательный блок «стрелка» отсутствовал в Python 2, и я не смог найти никакой информации относительно его значения в Python 3. Оказывается, это правильный Python, и он принят интерпретатором:
Я думал, что это может быть какой-то синтаксис предварительного условия, но:
- Я не могу проверить x здесь, пока он еще не определен,
- Что бы я ни указывал после стрелки (например, 2 < 1 ), это не влияет на поведение функции.
Может ли кто-нибудь, привыкший к этому синтаксису, объяснить это?
5 ответов
Более подробно, Python 2.x имеет строки документации, которые позволяют вам присоединять строку метаданных к различным типам объектов. Это удивительно удобно, поэтому Python 3 расширяет эту функцию, позволяя вам присоединять метаданные к функциям, описывающим их параметры и возвращаемые значения.
Там нет предвзятого варианта использования, но ПКП предлагает несколько. Один очень удобный способ — позволить вам аннотировать параметры с их ожидаемыми типами; тогда было бы легко написать декоратор, который проверяет аннотации или приводит аргументы к нужному типу. Другой — разрешить документацию по конкретным параметрам вместо того, чтобы кодировать ее в строку документации.
Это аннотации функций, описанные в PEP 3107. В частности, -> отмечает аннотацию возвращаемой функции.
Аннотации являются словарями, поэтому вы можете сделать это:
Вы также можете иметь структуру данных Python, а не просто строку:
Или вы можете использовать атрибуты функции для проверки вызываемых значений:
Это просто тип возвращаемого значения, в этом случае целое число не имеет значения, какое число вы пишете.
Как Java :
Но для Python (как сказал Джим Фасаракис Хиллиард) тип возврата — это просто подсказка , поэтому он предлагает возврат, но в любом случае разрешает возвращать другой тип, например, строку.
Это означает тип результата, который возвращает функция, но это может быть None .
Он широко распространен в современных библиотеках, ориентированных на Python 3.x.
Например, это есть в коде библиотеки pandas-profiling во многих местах, например:
В следующем коде:
-> int просто говорит, что f() возвращает целое число (но это не заставляет функцию возвращать целое число). Он называется возвратной аннотацией и доступен как f.__annotations__[‘return’] .
Python также поддерживает аннотации параметров:
: float говорит людям, которые читают программу (и некоторые сторонние библиотеки / программы, например, Pylint), что x должен быть float . К нему обращаются как f.__annotations__[‘x’] , и он сам по себе не имеет никакого значения. Смотрите документацию для получения дополнительной информации:
Указатели Pointer модуля ctypes в Python.
Конкретные типы указателей создаются путем вызова функции ctypes.POINTER() с типом, на который они будут указывать. Это делается автоматически с помощью функции ctypes.pointer() .
Если указатель указывает на массив, то его элементы могут быть прочитаны и записаны с использованием стандартного доступа по индексу и срезу.
Объекты-указатели не имеют размера, поэтому функция len() вызовет исключение TypeError .
Отрицательные индексы будут считываться из памяти перед указателем (как в C), а индексы вне диапазона, сломаются при нарушении прав доступа.
Атрибуты класса ctypes._Pointer
Pointer._type_ :
Атрибут Pointer._type_ возвращает тип, на который указывает указатель.
Pointer.contents :
Атрибут Pointer.contents возвращает объект, на который указывает указатель.
Присвоение этому атрибуту — изменяет указатель на вновь назначенный объект.
Примеры использования указателей модуля ctypes .
Экземпляры указателей создаются путем вызова функции ctypes.pointer() для типа модуля ctypes :
Экземпляры указателей имеют атрибут Pointer.contents , который возвращает объект, на который указывает указатель. Смотрим на что указывает созданный указатель pi в коде выше:
Обратите внимание, что модуль ctypes не имеет OOR (возврат исходного объекта), он создает новый эквивалентный объект каждый раз, когда извлекается атрибут:
Назначение другого экземпляра ctypes.c_int атрибуту указателя .contents приведет к тому, что он будет указывать на то место памяти, где он хранится:
Экземпляры указателя также индексируются целыми числами:
Присвоение целочисленному индексу — изменяет указанное значение:
Также можно использовать индексы, отличные от 0, но при этом необходимо понимать что вы делаете. Как и в C: можно получить доступ к произвольным ячейкам памяти или изменить их. Обычно эту функциональность используют только в том случае, если получают указатель от C-функции, который фактически указывает на массив, а не на отдельный элемент.
За кулисами функция ctypes.pointer() делает больше, чем просто создает экземпляры указателя, она должна сначала создать типы указателей. Это делается с помощью функции ctypes.POINTER() , которая принимает любой тип ctypes и возвращает новый тип:
Вызов типа указателя без аргумента создает нулевой указатель. Нулевые указатели имеют ложное логическое значение:
Модуль ctypes проверяет NULL при разыменовании указателей, но разыменование недопустимых указателей, отличных от NULL , приведет к сбою Python:
Передача указателей или передача параметров по ссылке.
Иногда функция api языка C ожидает указатель на тип данных в качестве параметра, для записи в соответствующее место или, если данные слишком велики, для передачи их по значению. Это также известно как передача параметров по ссылке.
Что означает -> в определениях функций Python?
недавно я заметил кое-что интересное, глядя на спецификация грамматики Python 3.3:
дополнительный блок «стрелка» отсутствовал в Python 2, и я не мог найти никакой информации о его значении в Python 3. Оказывается, это правильный Python, и он принимается интерпретатором:
Я думал, что это может быть какой-то синтаксис условие, но:
- Я не могу проверить x здесь, у него еще не определено,
- независимо от того, что я ставлю после стрелки (например, 2 < 1 ), он не влияет на поведение функции.
может ли кто-нибудь, привыкший к этому синтаксису, объяснить это?
3 ответов
более подробно, Python 2.x имеет docstrings, которые позволяют прикреплять строку метаданных к различным типам объектов. Это удивительно удобно, поэтому Python 3 расширяет эту функцию, позволяя прикреплять метаданные к функциям, описывающим их параметры и возвращаемые значения.
нет предвзятого варианта использования, но PEP предлагает несколько. Один очень удобный, чтобы позволить вам аннотировать параметры с их ожидаемыми типы; тогда было бы легко написать декоратор, который проверяет аннотации или согласовывает аргументы с правильным типом. Другой-разрешить документацию по конкретным параметрам вместо кодирования ее в docstring.
это аннотации функций, описанные в PEP 3107. В частности, -> отмечает аннотацию функции возврата.
аннотации-это словари, поэтому вы можете сделать следующее:
вы также можете иметь структуру данных python, а не только строку:
или вы можете использовать атрибуты функций для проверки вызываемых значений:
Как уже было сказано, -> символ используется как часть аннотации функции. В более поздних версиях Python >= 3.5 , хотя она определена смысл.
PEP 3107 — аннотации функций описал спецификацию, определяющую изменения грамматики, существование func.__annotations__ , в котором они хранятся, а то, что это дело остается открытым.
В Python 3.5 , однако,PEP 484 — Type Намеки придает этому одно значение: -> используется для указания типа, который возвращает функция. Также кажется, что это будет применяться в будущих версиях, как описано в как насчет существующих применений аннотаций:
самая быстрая мыслимая схема введет молчаливое осуждение аннотаций без подсказок в 3.6, полное осуждение в 3.7 и объявить подсказки типа как единственное разрешенное использование аннотаций в Python 3.8.
это фактически не было реализовано с 3.6 насколько я могу судить, поэтому он может столкнуться с будущими версиями.
согласно этому, пример, который вы предоставили:
будет запрещено в будущем (и в текущих версиях будет путать), его нужно будет изменить на:
для его эффективного описания этой функции f возвращает объект типа int .
аннотации никоим образом не используются самим Python, он в значительной степени заполняет и игнорирует их. С ними могут работать сторонние библиотеки.