Какой канонический способ проверить тип в Python?

Как лучше всего проверить, принадлежит ли данный объект заданному типу? Как насчет проверки того, наследуется ли объект от данного типа?

Допустим, у меня есть объект o. Как проверить, str ли это?

Что ж, канонический подход в Python - вообще не проверять тип (если вы не отлаживаете). Обычно вы просто пытаетесь использовать его как строку (например, объединять с другими строками, выводить на консоль и т. д.); если вы думаете, что это может привести к сбою, используйте try / except или hasattr. Тем не менее, принятый ответ - это канонический способ делать то, что вам обычно «не следует делать» в мире Python. Для получения дополнительной информации введите в Google "Python duck typing" или прочтите: voidspace.org.uk/python/articles/duck_typing.shtmlstackoverflow.com/questions/610883/…

Jon Coombs 11.12.2014 23:52

Я думаю, что мистер Кумбс упускает из виду такие примеры, как сериализуемые классы без JSON. Если передать большой кусок данных через функцию (на код которой нельзя повлиять), вы можете захотеть преобразовать определенные части этих данных, например, в <str> перед их передачей. По крайней мере, так я оказался на этой странице ...

John Carrell 24.11.2015 21:45

Кажется, что наиболее частая причина, по которой спрашивают об этом, заключается в том, что кто-то хочет различать строки и итерации строк. Это сложный вопрос, потому что строки являются итерируемые строки - односимвольная строка даже является последовательностью самой себя (в прошлый раз, когда я проверял - на нее, вероятно, не стоит полагаться). Но разве кому-нибудь понадобится что-нибудь похожее на струну? да. Итак, ответ на вопрос «Что мне делать, чтобы различать строки и другие итерации строк?» правильно: «Это зависит от того, что вы пытаетесь сделать». :-D

clacke 28.07.2016 15:22

Аннотации типов Python теперь в ходу. Взгляните на mypy

Sheena 05.10.2018 11:54
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1 416
4
993 625
12
Перейти к ответу Данный вопрос помечен как решенный

Ответы 12

isinstance(o, str)

Ссылка на документы

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

EKons 09.08.2016 11:59

isinstance(o, str) вернет True, если o является str или имеет тип, унаследованный от str.

type(o) is str вернет True тогда и только тогда, когда o является строкой. Он вернет False, если o имеет тип, унаследованный от str.

Конечно, это не удастся, если объект не является экземпляром 'str', а вместо этого является чем-то вроде строки. Как unicode, mmap, UserString или любой другой определяемый пользователем тип. Обычный подход в Python - не проводить проверку типов.

Thomas Wouters 30.09.2008 15:07

Это очень полезно. Потому что разница между isinstance и type(var) == type('') непонятна.

sastanin 12.01.2009 14:18
Ответ принят как подходящий

Чтобы проверить, является ли o экземпляром str или любым подклассом str, используйте это экземпляр (это будет «каноническим» способом):

if isinstance(o, str):

Чтобы проверить, совпадает ли тип o с str (исключая подклассы):

if type(o) is str:

Следующее также работает и может быть полезно в некоторых случаях:

if issubclass(type(o), str):

См. Встроенные функции в Справочнике по библиотеке Python для получения соответствующей информации.

Еще одно замечание: в этом случае, если вы используете Python 2, вы действительно можете использовать:

if isinstance(o, basestring):

потому что это также будет перехватывать строки Unicode (unicode не является подклассом str; как str, так и unicode являются подклассами basestring). Обратите внимание, что basestring больше не существует в Python 3, где есть строгое разделение строк (str) и двоичных данных (bytes).

В качестве альтернативы isinstance принимает кортеж классов. Это вернет True, если o является экземпляром любого подкласса любого из (str, unicode):

if isinstance(o, (str, unicode)):

str .__ subclasses __ () возвращает только прямые подклассы str и не делает то же самое, что issubclass () или isinstance (). (Для этого вам нужно будет рекурсивно вызвать .__ подклассы __ ().

Thomas Wouters 30.09.2008 16:22

Это хороший ответ, но я думаю, что его действительно следует начинать с предупреждения о том, что обычно не следует делать этого в Python. Как бы то ни было, это, кажется, подтверждает предположение, что это «каноническая вещь, которую можно делать в Python», но это не так.

Jon Coombs 11.12.2014 23:54

В чем разница между экземпляром и «точно»? Если type(a) is Object, то не правда ли, что isinstance(a, Object). Но если type(a) is SubClassOfObject, то type(a) is Object == False, но isinstance(a, Object) == True. Верно?

mavavilj 03.05.2017 16:49

@mavavilj - a is b означает, что a и b - это одно и то же, то есть ссылки на один и тот же объект в памяти. Таким образом, a и b должны быть одним и тем же классом, а не подклассами, как в isinstance(). См. Например stackoverflow.com/a/133024/1072212

Terry Brown 09.06.2017 20:47

@JonCoombs Согласно логике PEP 622, isinstance() - вторая по популярности встроенная функция после len(). Я думаю, мы должны признать, что isinstance является каноническим Python де-факто.

BallpointBen 04.07.2020 19:10

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

Я бы просто вызвал необходимые методы вашего объекта и поймал бы AttributeError. Позже это позволит вам вызывать свои методы с другими (кажущимися несвязанными) объектами для выполнения различных задач, таких как имитация объекта для тестирования.

Я часто использовал это при получении данных из Интернета с помощью urllib2.urlopen(), который возвращает объект файл как. Это, в свою очередь, может быть передано практически любому методу, который читает из файла, потому что он реализует тот же метод read(), что и реальный файл.

Но я уверен, что есть время и место для использования isinstance(), иначе его, наверное, не было бы :)

Хороший пример использования должен - это анализ динамического объекта json. Вы не знаете заранее, является ли поле строкой или словарем.

Gray 09.01.2019 23:34

самый Pythonic способ проверки типа объекта - это ... не проверять его.

Поскольку Python поддерживает Утка печатает, вам следует просто try...except использовать методы объекта так, как вы хотите их использовать. Итак, если ваша функция ищет объект файла с возможностью записи, не проверяет, что это подкласс file, просто попробуйте использовать его метод .write()!

Конечно, иногда эти красивые абстракции ломаются, и isinstance(obj, cls) - это то, что вам нужно. Но используйте экономно.

ИМХО, самый питонический способ - справиться с любым аргументом, который приводится. В моем коде я часто не могу знать, получаю ли я объект или массив объектов, и использую внутреннюю проверку типов для преобразования одного объекта в одноэлементный список.

sastanin 12.01.2009 14:21

Вместо того, чтобы просто пытаться использовать его метод записи, бывают случаи, когда вы хотите сделать это, не вызывая исключения. В этом случае вы можете сделать ... if hasattr(ob, "write") and callable(ob.write): Или сохранить доступ к диктовке ... func = getattr(ob, "write", None)if callable(func): ...

ideasman42 25.08.2012 23:41

Утиная печать - это с использованием библиотека. Проверка типа касается пишу библиотеки. Не та же проблемная область.

RickyA 07.12.2012 00:26

Итак, вы говорите, что неправильно иметь функцию, которая принимает и строку, и список строк?

yo' 02.03.2014 20:41

@RickyA, я не согласен. Утиная типизация - это взаимодействие с объектами с использованием интерфейсов с хорошо известной семантикой. Это может относиться либо к коду библиотеки, либо к коду, который использует такую ​​библиотеку.

Dan Lenski 16.06.2014 23:27

@tohecz, я не думаю, что это неправильный, но если у вас есть способ относиться к объектам более широко, а не явно проверять их тип, тогда ваш код может быть более универсальным. Я в целом согласен с подходом @sastanin к типу часто используемой вспомогательной функции, которая может принимать либо один элемент, либо их список: list_OF_strings = [list_OR_string] if isinstance(list_OR_string, basestring) else list_OR_string.

Dan Lenski 16.06.2014 23:31

@ ideasman42 Обратите внимание, что hasattr игнорирует все исключения, включая KeyboardInterrupt и подобные. Вам следует использовать getattr(obj, attr, None).

nyuszika7h 25.12.2014 22:07

@ nyuszika7h, в Python3 hasattr подавляет только AttributeError - см .: docs.python.org/3.4/library/functions.html#hasattr

ideasman42 26.12.2014 06:46

Меня смущает предложение. Прямо сейчас я пишу код, имитирующий алгебраические выражения, и хочу найти в дереве выражений любые два числа, которые можно суммировать, как один шаг в процессе упрощения. Как найти в дереве выражений два числа, которые можно сложить, не проверяя их типы?

Addem 25.12.2015 03:41

@Addem: если они, вероятно, будут добавляться, обычное дело, просто попробуйте! try: a + b except TypeError: something_appropriate. Если вы проводите проверку типов чисел, вы, скорее всего, пропустите некоторые из них, поскольку существует множество способов хранения чисел, которые не являются подклассами классов базовых чисел.

Excalabur 07.03.2016 08:50

«Самый питонический способ проверить тип объекта - это ... не проверять его». Это совершенно не помогает, когда я пытаюсь отладить свой код ...

user5359531 16.06.2016 20:44

Утиная печать - это не форма абстракции (имеется в виду ответ). Поскольку он избегает фактического набора текста (набор текста - это абстракция) и имеет дело с конкретными реализациями - например, «существует ли этот метод» или, может быть, более подходящим «Взрывается ли мой план ядерной энергетики или включаются ли вентиляторы, если я запускаю powerplant.blow()» (кто знает: ))

dualed 26.05.2017 17:54

Что, если я передам объект, который имеет тот же метод, но возвращает что-то другое? Он пройдет try, но будет вести себя неожиданно.

Rodrigo E. Principe 18.08.2017 15:22

@sastanin Я с вами не согласен. Python, как правило, является языком со строгой типизацией, поэтому функция НЕ должна работать с любым типом, который она получает. Если вы ожидаете int, просто попробуйте использовать его как int. Будет хорошо, если вы получите bool, потому что это подкласс int. Но не используйте проверку типов для обнаружения str и его преобразования в этом случае. Использование str как int, скорее всего, не удастся. Это нормально, и это то, чего ожидает пользователь.

Bachsau 27.04.2018 19:17

@ RodrigoE.Principe: звучит как метод, перехватывающий подпись родительского класса. Вы можете привести пример? Во всяком случае, поэтому была введена статическая проверка типов.

smci 10.09.2018 02:57

Помимо упоминания try...except, вы также должны сказать, что except не должен быть голым except, это всегда должен указывать конкретное именованное исключение (я), которое могло произойти, если тип объекта был неправильным, например. except TypeError, KeyError, UserDefinedYachtError:. Он не должен неявно перехватывать другие исключения: MemoryError, OSError и т. д., Особенно опасные. Голый, кроме того, что считается плохим

smci 10.09.2018 03:06

Писать API с такой философией вредно. Я предпочитаю вводить проверку для целого числа / str, на самом деле это необходимо даже при разработке API

H.Rabiee 18.05.2020 13:49

Шаблон try ... except не принесет никакой пользы, если результат "неправильный" для вашего варианта использования, но не вызывает исключения. Например, учитывая список смешанных типов, вы можете захотеть вызвать json.dumps только для dicts в этом списке, прежде чем передавать результат в модуль записи csv, из-за того, что в конечном итоге происходит с цитированием в выходных данных.

Jacob Lee 01.06.2020 20:54

Хьюго:

Вы, вероятно, имеете в виду list, а не array, но это указывает на всю проблему с проверкой типов - вы не хотите знать, является ли рассматриваемый объект списком, вы хотите знать, является ли это какой-то последовательностью или это единичный объект. Так что попробуйте использовать это как последовательность.

Допустим, вы хотите добавить объект в существующую последовательность, или, если это последовательность объектов, добавьте их все.

try:
   my_sequence.extend(o)
except TypeError:
  my_sequence.append(o)

Один из приемов заключается в том, что вы работаете со строками и / или последовательностями строк - это сложно, поскольку строка часто рассматривается как один объект, но это также и последовательность символов. Хуже того, поскольку это действительно последовательность строк одной длины.

Обычно я предпочитаю разрабатывать свой API так, чтобы он принимал только одно значение или последовательность - это упрощает работу. Нетрудно поставить [ ] вокруг вашего единственного значения, когда вы передаете его, если это необходимо.

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

Вот пример того, почему утиная печать - зло, не зная, когда это опасно. Например: вот код Python (возможно, без правильного отступа), обратите внимание, что это Ситуации можно избежать, если позаботиться о функциях isinstance и issubclassof, чтобы убедиться, что когда вам действительно понадобится утка, вы не получите бомбу.

class Bomb:
    def __init__(self):
        ""

    def talk(self):
        self.explode()

    def explode(self):
        print "BOOM!, The bomb explodes."

class Duck:
    def __init__(self):
        ""
    def talk(self):
        print "I am a duck, I will not blow up if you ask me to talk."    

class Kid:
    kids_duck = None

    def __init__(self):
        print "Kid comes around a corner and asks you for money so he could buy a duck."

    def takeDuck(self, duck):
        self.kids_duck = duck
        print "The kid accepts the duck, and happily skips along"

    def doYourThing(self):
        print "The kid tries to get the duck to talk"
        self.kids_duck.talk()

myKid = Kid()
myBomb = Bomb()
myKid.takeDuck(myBomb)
myKid.doYourThing()

Даже с проверкой типа вы можете создать class EvilDuck(Duck) и переопределить talk (). Или, что более вероятно, class ChineseCancerDuck(Duck), с неприятным побочным эффектом, который проявляется только спустя годы. Вам лучше просто присмотреть за своим ребенком (и тщательно протестировать его игрушки :)

Brett Thomas 20.02.2013 19:30

Бомбы не разговаривают. Не добавляйте бессмысленные методы, и этого не произойдет.

rightfold 18.03.2014 15:04

@ Дмитрий, это обычная критика Duck Typing: en.wikipedia.org/wiki/Duck_typing#Criticism ... вы в основном говорите, что любой интерфейс, семантика которого не поддерживается языком, является злом. Я считаю, что это больше подход Java. Вся суть утиной печати в Python заключается в том, что она работает только тогда, когда существует общепринятое соглашение о том, что означают конкретные интерфейсы. Например, вы можете обработать большой объем кода Python, переопределив атрибут __file__ (обычно используемый для идентификации файловоподобных объектов), чтобы он означал что-то другое.

Dan Lenski 16.06.2014 23:38

Все сводится к старой шутке «Доктор, мне больно, когда я это делаю». ... «Тогда не делай этого.». Неудовлетворительно для тех, кто привык «компилировать - запускать», но именно поэтому одержимость тестированием выросла из мира динамических языков.

clacke 28.07.2016 14:46

@clacke, это было 2 года назад, но это правда. Я сильно преувеличиваю вопрос. Проверка типов в «динамическом пространстве» сильно отличается от проверки «в пространстве времени компиляции». Во время выполнения, чтобы компьютер мог понять, чего мы от него хотим, ему необходимо сделать гораздо больше неизбежной работы, чем вы бы сделали в удобном пространстве времени компиляции. Когда я писал этот пример, я в основном кодировал на C и Java и почти не понимал динамическое пространство, поэтому казалось плохим, что такие вещи могут происходить без возможности предотвратить это с помощью статического анализа.

Dmitry 28.07.2016 14:52

@clacke окончательная реальность такова, что в динамическом пространстве предпочтительнее утиная типизация, потому что для того, чтобы примитивы имели смысл во время выполнения, у них должны быть накладные расходы, а именно карты и метаданные, которые позволяют этим собственным объектам быть значимыми во время выполнения. На данный момент все в основном представляет собой карту от строки к объекту, а объект - это выбранная коллекция «плавающих типов», которые вы определили при написании языка, например «число», «строка», «функция» и т. д. накладные расходы на анализ того, как их не следует использовать, значительно дороже во время выполнения, чем во время компиляции.

Dmitry 28.07.2016 14:57

@clacke в принципе, слишком дорого обеспечивать строгое соблюдение типов во время выполнения, потому что ВСЕ должно быть объектом (чтобы отображать из строки в любой возможный тип), и слишком удобно, чтобы не использовать ducktyping, потому что ducktyping позволяет действительно мощные методы прототипирования, которые преодолевают вещи, обычно очень сложно сделать с жесткими интерфейсами. Кроме того, любой статический язык сталкивается с проблемой, когда ему нужно создать утиную типизацию с помощью динамических библиотек, оценки и строкового преобразования или интерфейсов, и эти вещи по своей сути не делают его злом, просто очень мощным.

Dmitry 28.07.2016 15:02

@clacke Хотя я признаю, что мой пример ОЧЕНЬ надуманный, интерфейсы очень плохие. Это правильно с точки зрения «очень мощный» - это «зло», но неверно с точки зрения внутренней проблемы, которая все разрушает. В реалистичной демонстрации у вас не будет доступа к Малышу на стороне клиента, и если вы это сделаете, вы сможете делать гораздо более опасные или прямые вещи, чем просто передать им Бомбу (которую, по-видимому, у меня есть способность создать очень большое количество по моей прихоти на основе моего кода). Протокол обсуждения очень надуманный.

Dmitry 28.07.2016 15:06

@clacke так фундаментально да, как вы говорите: «доктор, доктор, мне больно, когда я продолжаю взрывать себя собственными бомбами». это в основном ситуация, и в языке для нее нет ничего изначально зла, так как вы создаете сцену, в которой вы взрываете себя. Это легко предотвратить, не позволяя клиенту иметь прямой доступ к ребенку, и пусть ребенок будет немного умнее в отношении того, что он ожидает от утки, прежде чем вызывать внедренный клиентский код, поскольку код не может выполняться сам. Эта проблема безопасности сервер-клиент будет существовать всегда, и ее можно легко решить, если разобраться в ней.

Dmitry 28.07.2016 15:12

@dmitry В основном я согласен с большей частью того, что вы только что сказали, но утиная печать предпочтительнее, потому что она дает возможность неожиданного повторного использования и перенаправления кода, а не потому, что это необходимо для динамического языка. Вы можете использовать Python, как если бы вы использовали Java, без утиной типизации, и при этом все равно выигрываете от того, что Python является языком с динамической типизацией. Культура утиного набора текста (и это вопрос культуры, а не технический вопрос) просто выводит эту полезность на новый уровень. Безопасность как таковая в него не входит, сервер никогда не должен доверять данным, предоставленным клиентом, независимо от того, статически или динамически типизирован язык.

clacke 28.07.2016 17:26

Принуждение типа @clacke java работает только потому, что оно скомпилировано в байт-код, поэтому у него есть передышка для статического анализа без перетекания его во время выполнения, где выполнение этих проверок является дорогостоящим. По сути, Java может быть перестроена так, чтобы вести себя таким же образом, используя карты, отражение и Class.forName для "JavaScriptify", хотя вам также потребуется создать подкласс Object, который имеет дополнительную карту для добавления к нему методов / свойств. во время выполнения. Java построен как язык со статической типизацией, который хочет поддерживать динамическую типизацию, но оболочка отражения препятствует:

Dmitry 28.07.2016 17:35

@clacke люди от перенастройки Java для еще более общих целей. Хотя он идет в этом направлении с множеством новых функций, таких как функциональные интерфейсы, а также с существованием Scala (который вроде хочет быть javascript на стероидах, но люди не позволяют ему получить возможность писать себя на уровень, который может JavaScript). Я хочу сказать, что языки, которые полностью доступны во время выполнения, являются дорогостоящими, чтобы разрешить статическую проверку типов: компиляция позволяет вам получать их бесплатно, но во время выполнения требуется гораздо больше работы, чтобы обеспечить ее соблюдение.

Dmitry 28.07.2016 17:38

@clacke, если вы не запустите средство проверки статического типа перед публикацией кода, и у него также есть проблемы (отсутствие схемы Ridgid для принудительного применения означает меньше вещей, которые он может проверить, java имеет схему Ridgid, вы не можете просто поместить новый метод или частный в существующий объект, поскольку объекты определены, если вы не добавите свою собственную строку карты в Object и не выполните собственное отражение).

Dmitry 28.07.2016 17:40

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

def foo(i: int):
    return i

foo(5)
foo('oops')

В этом случае мы хотим, чтобы для foo('oops') вызывалась ошибка, поскольку аннотированный тип аргумента - int. Подсказка добавленного типа не причина ошибка, возникающая при нормальном запуске сценария. Однако он добавляет атрибуты к функции, описывающие ожидаемые типы, которые другие программы могут запрашивать и использовать для проверки ошибок типа.

Одна из этих других программ, которая может использоваться для поиска ошибки типа, - mypy:

mypy script.py
script.py:12: error: Argument 1 to "foo" has incompatible type "str"; expected "int"

(Возможно, вам потребуется установить mypy из диспетчера пакетов. Я не думаю, что он поставляется с CPython, но, похоже, имеет некоторый уровень «официальности».)

Этот способ проверки типов отличается от проверки типов в статически типизированных компилируемых языках. Поскольку типы в Python являются динамическими, проверка типов должна выполняться во время выполнения, что требует затрат - даже для правильных программ - если мы настаиваем на том, чтобы это происходило при любой возможности. Явные проверки типов также могут быть более строгими, чем необходимо, и вызывать ненужные ошибки (например, действительно ли аргумент должен быть точно типа list или достаточно ли чего-либо итеративного?).

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

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

Пакет typing предлагает переменные типа, которые можно использовать в подсказках типов для выражения необходимого поведения, не требуя определенных типов. Например, он включает такие переменные, как Iterable и Callable, для подсказок, чтобы указать необходимость в любом типе с таким поведением.

Хотя подсказки типов - это наиболее питонический способ проверки типов, часто даже более Pythonic не проверяет типы вообще и полагается на утиную типизацию. Подсказки типа являются относительно новыми, и пока еще нет мнения, когда они будут наиболее питоническим решением. Относительно спорное, но очень общее сравнение: Тип подсказки предоставляют форму документации, которая может быть взыскана, позволяет код для генерации раньше и легче понять ошибки, может поймать ошибки, утиная типизация не может, а может быть проверено статический (в необычном смысл, но это все еще вне времени выполнения). С другой стороны, утиная типизация долгое время использовалась в Pythonic, не накладывает когнитивных накладных расходов на статическую типизацию, менее многословна и принимает все жизнеспособные типы, а затем и некоторые.

-1: mypy специально называет себя «средством проверки статического типа», поэтому я не уверен, откуда у вас «проверка типов должна выполняться во время выполнения».

Kevin 12.08.2018 03:48

@Kevin Оглядываясь назад, можно сказать, что это было ненужное отступление, но чтобы углубиться в него, подсказки типов Python превращаются в данные времени выполнения, а mypy - это модуль Python, который использует importlib для доступа к этим данным. Является ли это «статической проверкой типов» - это философский вопрос, но он отличается от того, чего можно было бы ожидать, поскольку задействованы интерпретатор нормального языка и механизм импорта.

Praxeolitic 12.08.2018 09:20

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

Kevin 12.08.2018 18:56

Для более сложных проверок типов мне нравится подход Typeguard к проверке на основе аннотаций подсказок типа python:

from typeguard import check_type
from typing import List

try:
    check_type('mylist', [1, 2], List[int])
except TypeError as e:
    print(e)

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

check_type('foo', [1, 3.14], List[Union[int, float]])
# vs
isinstance(foo, list) and all(isinstance(a, (int, float)) for a in foo) 

Вы можете проверить тип переменной, используя __name__ типа.

Бывший:

>>> a = [1,2,3,4]  
>>> b = 1  
>>> type(a).__name__
'list'
>>> type(a).__name__ == 'list'
True
>>> type(b).__name__ == 'list'
False
>>> type(b).__name__
'int'

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

Aaron D. Marasco 30.09.2019 23:58

Я думаю, что лучший способ - это хорошо напечатать свои переменные. Вы можете сделать это, используя библиотеку "набора текста".

Пример:

from typing import NewType UserId = NewType ('UserId', int) some_id = UserId (524313) `

См. https://docs.python.org/3/library/typing.html

Простой способ проверить тип - сравнить его с чем-то, тип которого вам известен.

>>> a  = 1
>>> type(a) == type(1)
True
>>> b = 'abc'
>>> type(b) == type('')
True

Другие вопросы по теме