Каков наилучший способ проверить, принадлежит ли данный объект заданному типу? Как насчет проверки, наследуется ли объект от данного типа?
Допустим, у меня есть объект o. Как я могу проверить, является ли это str?
Каков наилучший способ проверить, принадлежит ли данный объект заданному типу? Как насчет проверки, наследуется ли объект от данного типа?
Допустим, у меня есть объект o. Как я могу проверить, является ли это str?
Ответы:
Чтобы проверить, oявляется ли экземпляр strили какой-либо подкласс класса str, используйте isinstance (это будет «канонический» способ):
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)):
type(a) is Objectтогда не правда ли это тоже isinstance(a, Object). Однако, если type(a) is SubClassOfObject, тогда type(a) is Object == False, но isinstance(a, Object) == True. Правильно?
a is bозначает, что a и b - это одно и то же, то есть ссылки на один и тот же объект в памяти. Так aи bдолжно быть точно такой же класс, а не подклассы, как с isinstance(). Смотрите, например, stackoverflow.com/a/133024/1072212
Наиболее Pythonic способ проверить тип объекта является ... не проверить.
Поскольку Python поощряет Duck Typing , вы должны просто try...exceptиспользовать методы объекта так, как вы хотите их использовать. Так что если ваша функция ищет доступный для записи объект файла, не проверяйте, является ли он подклассом file, просто попробуйте использовать его .write()метод!
Конечно, иногда эти красивые абстракции ломаются и isinstance(obj, cls)это то, что вам нужно. Но используйте экономно.
if hasattr(ob, "write") and callable(ob.write): Или сохранить некоторый доступ к func = getattr(ob, "write", None) if callable(func): ...
hasattrтолько ошибка AttributeError - см. docs.python.org/3.4/library/functions.html#hasattr
isinstance(o, str)вернет, Trueесли oявляется strили имеет тип, который наследуется от str.
type(o) is strвернется, Trueесли и только если oэто ул. Он вернетсяFalse если oимеет тип, который наследуется от str.
isinstanceи type(var) == type('')не ясна.
После того, как вопрос был задан и получен ответ, в 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 вообще не проверяет типы вообще и полагается на типизацию с утиным типом. Типовые подсказки являются относительно новыми, и жюри все еще остается в стороне, когда они являются наиболее питонским решением. Относительно неоспоримое, но очень общее сравнение: подсказки типов предоставляют форму документации, которую можно применять, позволяют генерировать код раньше и легче понимать ошибки, могут отлавливать ошибки, которые не могут быть введены при печати, и могут быть проверены статически (в необычном случае). смысл, но это все еще вне времени выполнения). С другой стороны, типизация утки долгое время была питонской, не накладывает когнитивных издержек на статическую типизацию, менее многословна и будет принимать все жизнеспособные типы, а затем и некоторые.
mypyпредставляют собой модуль Python, который использует importlibдля доступа к этим данным. Является ли это «статической проверкой типов» - это философский вопрос, но он отличается от того, чего большинство ожидают, поскольку в нем задействованы обычный интерпретатор языка и механизм импорта.
Вот пример, почему печатание на уток - зло, не зная, когда это опасно. Например: вот код 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)с неприятным побочным эффектом, который проявляется только спустя годы. Тебе было бы лучше просто присматривать за своим ребенком (и тщательно проверять его игрушки :)
__file__атрибут (обычно используемый для идентификации файловых объектов), чтобы обозначить что-то другое.
isinstance(o, str)
Я думаю, что классная вещь в использовании динамического языка, такого как Python, заключается в том, что вам не нужно проверять что-то подобное.
Я бы просто вызвал необходимые методы для вашего объекта и поймал бы AttributeError. Позже это позволит вам вызывать ваши методы с другими (казалось бы, не связанными) объектами для выполнения различных задач, таких как насмешка над объектом для тестирования.
Я использовал это много, когда получаю данные из Интернета с urllib2.urlopen() которых возвращал файл, подобный объекту. Это, в свою очередь, может быть передано практически любому методу, который читает из файла, потому что он реализует то же самоеread() метод, что и реальный файл.
Но я уверен, что есть время и место для использования isinstance(), иначе его, вероятно, не было бы :)
Для более сложных проверок типов мне нравится подход валидации 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'
Хьюго:
Вы, вероятно, имеете в виду, listа неarray , но это указывает на всю проблему с проверкой типов - вы не хотите знать, является ли рассматриваемый объект списком, вы хотите знать, является ли это какой-то последовательностью или это один объект. Поэтому попробуйте использовать его как последовательность.
Допустим, вы хотите добавить объект в существующую последовательность или, если это последовательность объектов, добавить их все
try:
my_sequence.extend(o)
except TypeError:
my_sequence.append(o)
Одна хитрость в этом заключается в том, что если вы работаете со строками и / или последовательностями строк - это сложно, поскольку строку часто рассматривают как отдельный объект, но это также последовательность символов. Хуже того, так как это действительно последовательность строк одинарной длины.
Я обычно выбираю дизайн своего API так, чтобы он принимал только одно значение или последовательность - это облегчает работу. Нетрудно [ ]обойти ваше единственное значение, когда вы передаете его, если это необходимо.
(Хотя это может привести к ошибкам со строками, так как они выглядят (являются) последовательностями.)
Простой способ проверить тип - сравнить его с чем-то, чей тип вы знаете.
>>> a = 1
>>> type(a) == type(1)
True
>>> b = 'abc'
>>> type(b) == type('')
True
Я думаю, что лучший способ - это правильно набирать переменные. Вы можете сделать это с помощью библиотеки "typing".
Пример:
from typing import NewType
UserId = NewType ('UserId', int)
some_id = UserId (524313) `
Вы можете проверить с помощью строки ниже, чтобы проверить, какой тип символа заданное значение:
def chr_type(chrx):
if chrx.isalpha()==True:
return 'alpha'
elif chrx.isdigit()==True:
return 'numeric'
else:
return 'nothing'
chr_type("12)