Как лучше всего проверить, является ли данный объект объектом данного типа? Как проверить, наследует ли объект от данного типа?
Допустим, у меня есть объект 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
не является подклассом str
; и str
, и unicode
являются подклассами basestring
). Заметим, что basestring
больше не существует в python 3, где существует строгое разделение строк (str
) и двоичных данных (bytes
).
В качестве альтернативы функция isinstance
принимает кортеж классов. Это вернет True, если x является экземпляром любого подкласса любого из (str, unicode):
if isinstance(o, (str, unicode)):
самый Пифонический способ проверить тип объекта... не проверять это.
Поскольку Python поощряет Duck Typing, вы должны просто попробовать...кроме
использовать методы объекта так, как вы хотите их использовать. Поэтому, если ваша функция ищет объект файла для записи, не проверяйте, что это подкласс file
, просто попробуйте использовать его метод .write ()
!
Конечно, иногда эти приятные абстракции разрушаются, и вам нужна «сущность (объект, cls)». Но используйте экономно.
isinstance(o, str)
вернет True
, если o
является str
или имеет тип, наследуемый от str
.
type(o) is str
вернет True
тогда и только тогда, когда o
является str. Если o
имеет тип, наследуемый от str
, то возвращается False
.
После того, как вопрос был задан и дан ответ, намеки типа были добавлены в 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
type или что-то достаточно?).
Преимущество явной проверки типа заключается в том, что она может выявлять ошибки раньше и давать более четкие сообщения об ошибках, чем притирка. Точные требования типа утки могут быть выражены только с внешней документацией (надеюсь, она тщательная и точная), и ошибки от несовместимых типов могут возникать далеко от места их возникновения.
Подсказки типа Python предназначены для компромисса, когда типы могут быть указаны и проверены, но при обычном выполнении кода дополнительные расходы не требуются.
Пакет typing
предлагает переменные типа, которые можно использовать в подсказках типа для выражения необходимого поведения, не требуя определенных типов. Например, он включает в себя такие переменные, как «Iterable» и «Callable» для подсказок, чтобы указать необходимость любого типа с таким поведением.
Хотя подсказки типа являются наиболее питоническим способом проверки типов, зачастую даже более пифонично вообще не проверять типы и полагаться на типирование утки. Типовые подсказки относительно новы, и жюри все еще отсутствует, когда они являются наиболее питонским решением. Относительно бесспорное, но очень общее сравнение: подсказки типа предоставляют форму документации, которая может быть применена, разрешить коду генерировать раньше и легче понимать ошибки, может уловить ошибки, которые может печатать утка 'т, и может быть проверено статически (в необычном смысле, но это 'все еще вне времени выполнения). С другой стороны, типирование утки долгое время было питонским способом, не накладывает когнитивных накладных расходов на статическое типирование, является менее многословным и принимает все жизнеспособные типы, а затем и некоторые.
Вот пример, почему печатание утки - это зло, не зная, когда это опасно. Например: вот код Python (возможно, не содержащий правильного отступа), обратите внимание, что это ситуации можно избежать, заботясь об обстоятельствах и функциях issuclassof, чтобы убедиться, что когда вам действительно нужна утка, вы не получите бомбу.
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()
isinstance(o, str)
Я думаю, что самое интересное в использовании динамического языка, такого как Python, это то, что вам действительно не нужно проверять что-то подобное.
Я бы просто позвонил нужным методам на вашем объекте и поймал AttributeError
. Позже это позволит вам вызывать ваши методы с другими (кажущимися не связанными) объектами для выполнения различных задач, таких как издевательство над объектом для тестирования.
Я часто использовал это при получении данных из Интернета с помощью urllib2.urlopen ()
, который возвращает объект file like. Это, в свою очередь, можно передать практически любому методу, который читает из файла, поскольку он реализует тот же метод read ()
, что и реальный файл.
Но я уверен, что есть время и место для использования isinstance ()
, иначе его, вероятно, там не было бы :)
Хьюго:
Вы, вероятно, имеете в виду «list», а не «array», но это указывает на всю проблему с проверкой типов - вы не хотите знать, является ли рассматриваемый объект списком, вы хотите знать, является ли это какой-то последовательностью или если это один объект. Поэтому попробуйте использовать его как последовательность.
Скажем, вы хотите добавить объект в существующую последовательность или, если это последовательность объектов, добавить их все
try:
my_sequence.extend(o)
except TypeError:
my_sequence.append(o)
Один трюк с этим заключается в том, что если вы работаете со строками и / или последовательностями строк - это сложно, поскольку строку часто рассматривают как один объект, но это также последовательность символов. Хуже того, так как это действительно последовательность строк в одну длину.
Я обычно выбираю дизайн своего API, чтобы он принимал только одно значение или последовательность - это облегчает ситуацию. Нетрудно поместить []
вокруг вашего единственного значения, когда вы передаете его в случае необходимости.
(Хотя это может вызвать ошибки в строках, так как они выглядят как (являются) последовательностями.)
Для более сложных проверок типов мне нравится подход проверки типа 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 \ \ типа.
Ex:
>>> 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'
Вы можете проверить с помощью строки ниже, чтобы проверить, какой тип символа заданное значение:
def chr_type(chrx):
if chrx.isalpha()==True:
return 'alpha'
elif chrx.isdigit()==True:
return 'numeric'
else:
return 'nothing'
chr_type("12)