Python проверяет, есть ли экземпляр любого типа в списке?

87

Как мне питонически делать:

var = 7.0
var_is_good = isinstance(var, classinfo1) or isinstance(var, classinfo2) or isinstance(var, classinfo3) or ... or  isinstance(var, classinfoN)

Кажется глупым, я не могу просто передать список classinfo:

var_is_good = isinstanceofany( var, [classinfo1, classinfo2, ... , classinfoN] )

Так в чем же isinstanceofanyфункция?

Д. Адамс
источник
Если он складывает как число, вычитает как число, умножается как число ... зачем вам знать, является ли это числом? См. Утиный ввод для более подробной информации.
Макото
В моем конкретном случае использования есть функция, которая возвращает (функция, которая возвращает (либо numberИЛИ, оно возвращает симпатичное выражение)). Я хочу проверить, что сгенерированная мной функция выполняет то, что должна делать, когда я передаю ее другим функциям.
D Adams
Почему ваша функция не возвращает что-то однородное? Вот какой здесь запах; вы можете быстро и свободно набирать текст, но вы должны быть последовательны в том, что вы возвращаете.
Макото
Думаю, я всегда мог вернуть симпозиумное выражение, которое иногда оценивается как число, а иногда внутри него остаются переменные.
D Adams
Я думаю, это то, что вы хотите здесь делать; вместо того, чтобы возвращать несколько разных типов, верните один тип и, если необходимо, сократите его до числа.
Макото

Ответы:

191

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

isinstance(var, (classinfo1, classinfo2, classinfo3))

Другими словами, он isinstance() уже предлагает эту функциональность из коробки.

Из isinstance()документации :

Если classinfo не является ни объектом класса, ни объектом типа, он может быть кортежем объектов класса или типа или может рекурсивно содержать другие такие кортежи (другие типы последовательности не принимаются).

Акцент мой; обратите внимание на рекурсивный характер; (classinfo1, (classinfo2, classinfo3))также допустимый вариант.

Мартейн Питерс
источник
Полезно, спасибо!
Яаков Бресслер
11

Вы уже довольно близко подошли к названию своего вопроса. Вы можете использовать anyи список:

var = 7.0
var_is_good = any([isinstance(var, classinfo1),
                   isinstance(var, classinfo2),
                   isinstance(var, classinfo3), ...
                   isinstance(var, classinfoN)])

Но глядя в документацию, isinstanceобнаруживается:

Верните true, если аргумент объекта является экземпляром аргумента classinfo или его (прямого, косвенного или виртуального) подкласса. Если объект не является объектом данного типа, функция всегда возвращает false. Если classinfo не является классом (объект типа), он может быть кортежем объектов типа или может рекурсивно содержать другие такие кортежи (другие типы последовательности не принимаются). Если classinfo не является типом или кортежем типов и таких кортежей, возникает исключение TypeError.

Это означает, что лучший способ сделать это -

var = 7.0
var_is_good = isinstance(var, (classinfo1,
                               classinfo2,
                               classinfo3,
                               ...,
                               classinfoN))
Мартин Тома
источник
2
Повторение isinstanceтолько с classinfoизменением мне не кажется очень питоническим.
Макото
1
Попробуй var.__class__. Это то, что вы хотите? @Makoto: Согласен. Совсем не Pythonic!
фламенко
@Makoto Ага. Но это было то, что Д. Адамс, вероятно, легко мог найти, выполнив поиск в документации по запросу «любой». Я расширил свой ответ до лучшей версии ... но, очевидно, Мартейн Питерс был быстрее ... еще раз.
Мартин Тома
3
any()со списком .. бессмысленно. Используйте выражение генератора, если вам необходимо его использовать any(), тогда вы , по крайней мере, получите преимущество раннего выхода.
Martijn Pieters
Я думаю, что isinstanceс кортежем - это путь. Я просто хотел упомянуть решение, anyкоторое, похоже, было именно тем, о чем он просил в названии.
Мартин Тома,
4

Это решит вашу проблему:

valid_instance_types = <tuple of types you want to allow>
var_is_good = isinstance(var, valid_instance_types)

Судя по документации, существует множество способов передачи значений типов isinstance.

Вы также можете обратить внимание на сладострастие, если пытаетесь провести более сложную проверку, и это лишь часть.

Натаниэль Форд
источник
isinstance () уже предлагает эту функцию, передайте кортеж со всеми необходимыми типами для проверки в качестве второго аргумента
RFV
@ RFV5s Да .... именно это показывает приведенный мною здесь пример. Что вы возражаете?
Натаниэль Форд,
1

Обычно вы не должны использовать isinstance, но то, что вы хотите сделать, может быть выполнено с помощью встроенной функции any () .

var_is_good = any(isinstance(var, t) for t in [type1, type2, type3])
Чад С.
источник
7
Это перебор; isinstance()предлагает функциональность из коробки без использования any().
Мартейн Питерс
@MartijnPieters Я не понимал, что isinstance может принимать несколько типов, но мне кажется, что ответ все еще хороший, потому что вопрос можно трактовать в более широком смысле: «Как проверить, есть ли какое-либо из возвращаемых значений из конкретной функции с разными параметрами верно "
Чад С.
Неважно, стоит ли вам использовать isinstance().
RFV
@ChadS. Я хотел бы спросить вас, почему вы думаете, что ему не следует использовать isinstance()? Спасибо.
idature
Потому что python избегает проверки типов. Это много дополнительного кода (и циклов ЦП) с небольшой пользой. Утиный ввод предпочтительнее.
Чад С.