Определите, является ли переменная Python экземпляром встроенного типа

Мне нужно определить, является ли данная переменная Python экземпляром собственного типа: str, int, float, bool, list, dict и так далее. Есть ли элегантный способ сделать это?

Или это единственный способ:

if myvar in (str, int, float, bool):
    # do something

person Aleksandr Motsjonov    schedule 24.08.2009    source источник
comment
Что вы подразумеваете под родным типом? Вы имеете в виду встроенный? Почему вы должны знать это? Python — это не C++ или Java, поэтому нет разницы между простыми и нативными типами. Что ты пытаешься сделать?   -  person S.Lott    schedule 24.08.2009
comment
Да, наверное, я имею в виду встроенные типы. Мне нужно такое представление объекта, чтобы я мог использовать его в сериализации JSON. simplejson обрабатывает только такие типы. В других случаях (когда объект является экземпляром самодельных классов) мне нужно создавать объекты dict.   -  person Aleksandr Motsjonov    schedule 24.08.2009
comment
Вы знаете, что в simplejson есть что-то, что называется декодированием объектов и кодированием объектов?   -  person    schedule 24.08.2009
comment
Да, но как я понял - я должен написать такой декодер для каждого класса, который я хочу сериализовать. Я не хочу этого делать.   -  person Aleksandr Motsjonov    schedule 24.08.2009
comment
@Aleksandr Motsjonov: Пожалуйста, обновите свой вопрос, указав, что вас интересуют типы, которые simplejson обрабатывает по умолчанию.   -  person S.Lott    schedule 24.08.2009
comment
@Aleksandr Motsjonov: Даже если вам нужен один декодер для каждого типа, не имеет значения, встроен ли этот тип или нет. Я обновил свой ответ, чтобы отразить вашу актуальную проблему.   -  person Lennart Regebro    schedule 24.08.2009
comment
вам действительно следует взглянуть на ответ С.Лотта, потому что он лучше, чем тот, который вы выбрали... Я добавил некоторый код, чтобы показать, как он будет использоваться на самом деле, но вам действительно все равно, является ли что-то встроенным или нет, вместо этого вы должны увидеть, поддерживается ли то, что вы пытаетесь сделать, и в противном случае попробуйте что-то еще   -  person Terence Honles    schedule 25.08.2009


Ответы (10)


Лучший способ добиться этого — собрать типы в список кортежей с именем primitiveTypes и:

if isinstance(myvar, primitiveTypes): ...

types модуль содержит коллекции всех важных типов, которые могут помочь в создании списка/кортежа .

Работает, начиная с Python 2.2

person Aaron Digulla    schedule 24.08.2009
comment
использование типов из 'types' ничем не отличается от прямого использования более простых имен (int, str, float,...)! - person u0b34a0f6ae; 24.08.2009
comment
Да, именно так работают типы. Но это делает ваше намерение более ясным, и если вы используете предопределенные наборы (StringTypes), вы получаете дополнительную переносимость между версиями Python. - person Aaron Digulla; 24.08.2009
comment
Это также немного быстрее ... ;) - person Aaron Digulla; 24.08.2009
comment
Я не уверен, что это лучший подход. В основном вы импортируете типы из модулей types и проверяете их, но документы не одобряют этот способ, начиная с python 2.2. В соответствии с документами использование isinstance предпочтительнее. Во втором примере кода показан простой случай. - person Paolo; 18.11.2012
comment
@Guandalino: Спасибо, улучшил мой ответ. - person Aaron Digulla; 19.11.2012
comment
Обратите внимание, что модуль types на самом деле не предоставляет полный список типов. Например, там нет int. Однако есть модуль buildins, который предоставляет большинство встроенных функций, поэтому можно сделать builtin_types = tuple(getattr(builtins, t) for t in dir(builtins) if isinstance(getattr(builtins, t), type)), а затем использовать isinstance(value, builtin_types). - person Bakuriu; 10.06.2016
comment
..dict и т. д.: вдруг isinstance(NamedTuple, tuple) == true. Имя/встроенные классы также должны быть проверены. - person Denis Barmenkov; 15.04.2020
comment
isinstance верно для подклассов встроенных типов, тогда как type(value) in (bool, str, int, float, tuple, list, dict) верно только для экземпляров встроенных типов. Это различие указано в этом ответе: stackoverflow.com/a/6392016/1959808 - person Ioannis Filippidis; 20.04.2020

Это старый вопрос, но, похоже, ни один из ответов на самом деле не отвечает на конкретный вопрос: «(Как) определить, является ли переменная Python экземпляром встроенного типа». Обратите внимание, что это не "[...] встроенного типа конкретного/данного", а a.

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

def is_builtin_class_instance(obj):
    return obj.__class__.__module__ == '__builtin__'

Предупреждение: если obj является классом, а не экземпляром, независимо от того, встроен этот класс или нет, будет возвращено значение True, поскольку класс также является объектом, экземпляром type (т. е. AnyClass.__class__ является type).

person glarrain    schedule 22.07.2013
comment
В Python3 модуль называется __builtins__. - person niekas; 29.08.2019
comment
в Python 3.7 модуль называется builtins - person Mikaelblomkvistsson; 03.09.2019
comment
@glarrain, как бы вы изменили это, чтобы справиться с упомянутым вами общим случаем, в котором obj является классом, а не экземпляром? - person jtlz2; 20.05.2021

Не то чтобы я знал, почему вы хотели бы это сделать, поскольку в Python нет «простых» типов, это все объекты. Но это работает:

type(theobject).__name__ in dir(__builtins__)

Но явное перечисление типов, вероятно, лучше, так как это понятнее. Или еще лучше: изменить приложение, чтобы вам не нужно было знать разницу.

Обновление: проблема, требующая решения, заключается в том, как сделать сериализатор для объектов, даже встроенных. Лучший способ сделать это — не создавать большой phat-сериализатор, который по-разному обрабатывает встроенные функции, а искать сериализаторы на основе типа.

Что-то вроде этого:

def IntSerializer(theint):
    return str(theint)

def StringSerializer(thestring):
    return repr(thestring)

def MyOwnSerializer(value):
    return "whatever"

serializers = {
    int: IntSerializer,
    str: StringSerializer,
    mymodel.myclass: MyOwnSerializer,
}

def serialize(ob):
    try:
        return ob.serialize() #For objects that know they need to be serialized
    except AttributeError:
        # Look up the serializer amongst the serializer based on type.
        # Default to using "repr" (works for most builtins).
        return serializers.get(type(ob), repr)(ob)

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

person Lennart Regebro    schedule 24.08.2009
comment
+1 Изменение приложения, чтобы вам не нужно было знать разницу. Некоторые (крайне редкие) моменты необходимо знать, но, скорее всего, нет. - person Esteban Küber; 24.08.2009

Похоже, вы заинтересованы в том, чтобы simplejson справился с вашими типами. Это делается тривиально

try:
    json.dumps( object )
except TypeError:
    print "Can't convert", object

Это более надежно, чем пытаться угадать, какие типы обрабатывает ваша реализация JSON.

person S.Lott    schedule 24.08.2009
comment
это более pythonic, потому что, если объект может быть сброшен (скажем, возможно, simplejson добавляет больше поддержки), то он будет использоваться сначала, а затем, за исключением того, что вы должны вызывать свою функцию приема. +1 - person Terence Honles; 25.08.2009

Что такое «собственный тип» в Python? Пожалуйста, не основывайте свой код на типах, используйте Duck Typing.

person Community    schedule 24.08.2009
comment
Спасибо, я сто раз подумаю, прежде чем делать это =) - person Aleksandr Motsjonov; 24.08.2009

вы можете получить доступ ко всем этим типам с помощью модуля types:

`builtin_types = [ i for i in  types.__dict__.values() if isinstance(i, type)]`

напоминаем, сначала импортируйте модуль types

def isBuiltinTypes(var):
    return type(var) in types.__dict__.values() and not isinstance(var, types.InstanceType)
person jacoolee    schedule 26.03.2015

Встроенная функция типа может быть полезна:

>>> a = 5
>>> type(a)
<type 'int'>
person kolistivra    schedule 24.08.2009

основываясь на ответе С.Лотта, у вас должно быть что-то вроде этого:


from simplejson import JSONEncoder

class JSONEncodeAll(JSONEncoder):
  def default(self, obj):
    try:
      return JSONEncoder.default(self, obj)
    except TypeError:
      ## optionally
      # try:
      #   # you'd have to add this per object, but if an object wants to do something
      #   # special then it can do whatever it wants
      #   return obj.__json__()
      # except AttributeError:
      ##

      # ...do whatever you are doing now...
      # (which should be creating an object simplejson understands)

использовать:


>>> json = JSONEncodeAll()

>>> json.encode(myObject)
# whatever myObject looks like when it passes through your serialization code

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

person Terence Honles    schedule 24.08.2009

Для меня лучший вариант:

allowed_modules = set(['numpy'])
def isprimitive(value):
  return not hasattr(value, '__dict__') or \
  value.__class__.__module__ in allowed_modules

Это исправление, когда значение является модулем, а value.__class__.__module__ == '__builtin__' не работает.

person asterio gonzalez    schedule 26.09.2017

Сейчас 2020 год, я на Python 3.7, и ни один из существующих ответов мне не помог. Вместо этого сработал встроенный модуль . Вот как:

import builtins
type(your_object).__name__ in dir(builtins)
person ifedapo olarewaju    schedule 22.04.2021