确定Python变量是否为内置类型的实例

42
我需要确定一个给定的Python变量是否是本地类型的实例:strintfloatboollistdict等等。有没有更优雅的方法来完成它?
或者这是唯一的方法:
if myvar in (str, int, float, bool):
    # do something

6
“native” type是什么意思?你的意思是内置类型吗?你为什么需要知道这个?Python不同于C++或Java,所以没有“简单”或“本地”类型的区别。你想要做什么? - S.Lott
是的,我想我的意思是“内置”类型。我需要这样一种对象的表示形式,以便我可以在JSON序列化中使用它。simplejson仅“处理”此类类型。在其他情况下(当对象是“自制”类的实例时),我需要创建字典对象。 - Aleksandr Motsjonov
1
你知道simplejson有一个叫做"对象解码"和"对象编码"的功能吗? - lutz
是的,但据我所理解,我应该为我想要序列化的每种类别编写这样的解码器。我不想这么做。 - Aleksandr Motsjonov
你应该真正看看S.Lott的答案,因为它比你选择的更好...我添加了一些代码来展示它实际上是如何使用的,但你真的不应该关心某个东西是否是内置的,而是应该看看你正在尝试做的事情是否被支持,否则就尝试其他方法。 - Terence Honles
显示剩余3条评论
11个回答

33

这是一个老问题,但似乎没有一个答案真正回答了这个具体问题:“(如何)确定Python变量是否是内置类型的实例”。请注意,它不是“[...]特定/给定的内置类型”,而是任意一个。

确定一个给定对象是否是内置类型/类的实例的正确方法是检查对象的类型是否在模块__builtin__中定义。

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

警告:如果obj是一个类而不是实例,无论这个类是否为内置类,都会返回True,因为一个类也是一个对象,是type的一个实例(即AnyClass.__class__type)。


5
在Python3中,该模块被称为 __builtins__ - niekas
18
在Python 3.7中,该模块被称为 builtins - Mikaelblomkvistsson
@glarrain,您如何修改此代码以处理您提到的一般情况,即obj是一个类而不是一个实例? - jtlz2
@jtlz2 你可以将名称存储在一个变量中,并将其与该变量进行比较,例如builtin_module_name=dict().__class__.__module__ - MichaelMoser

12

虽然我不知道为什么你想这样做,因为在Python中没有任何“简单”的类型,它们都是对象。但是这个方法是可行的:

type(theobject).__name__ in dir(__builtins__)

但是明确列出类型可能更好,因为这样更清晰。或者更好的方法是:改变应用程序,使您不需要知道差异。

更新:需要解决的问题是如何为对象(甚至内置对象)制作序列化器。最好的方法不是制作一个大而臃肿的序列化器将内置对象与其他对象区别对待,而是根据类型查找序列化器。

类似于这样:

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)

通过这种方式,您可以轻松地添加新的序列化程序,并且代码易于维护和清晰,因为每种类型都有自己的序列化程序。请注意一些类型是内置的事实已经完全不相关了。:)


+1 “改变应用程序,以便您不需要知道差异。” 有时(非常罕见)需要知道,但很可能不需要。 - Esteban Küber

12

最好的方法是将类型收集到一个名为primitiveTypes的元组列表中:

if isinstance(myvar, primitiveTypes): ...

types模块包含了许多重要的类型,可以帮助构建列表/元组。

自Python 2.2以来可用


2
使用'types'中的类型与直接使用更简单的名称(int,str,float,...)没有任何区别! - u0b34a0f6ae
它也稍微快一点... ;) - Aaron Digulla
我不确定这是否是最佳方法。基本上,您从“types”模块导入类型并对其进行检查,但自Python 2.2以来,文档不鼓励使用此方式。根据文档,使用“isinstance”更为推荐。第二个代码示例显示了一个简单的情况 - Paolo
3
请注意,types 模块并没有提供完整的类型列表。例如其中没有 int。但是有 builtins 模块提供了大部分内置类型,因此可以使用 builtin_types = tuple(getattr(builtins, t) for t in dir(builtins) if isinstance(getattr(builtins, t), type)) 来获取内置类型列表,并使用 isinstance(value, builtin_types) 进行判断。 - Bakuriu
1
isinstance 对于内置类型的子类返回 True,而 type(value) in (bool, str, int, float, tuple, list, dict) 仅对内置类型的实例返回 True。这个差异在这个答案中指出:https://dev59.com/e2w15IYBdhLWcg3wzO1_#6392016 - 0 _
显示剩余3条评论

7

您似乎对确保simplejson能够处理您的类型感兴趣。这可以通过简单地进行以下操作来完成:

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

比起猜测你的JSON实现处理哪些类型更可靠。

这更符合Python的风格,因为如果对象可以被转储(例如simplejson添加了更多支持),那么它将首先被使用,然后在except中调用通用功能。+1 - Terence Honles
如果对象是一个巨大的字典,那么不会浪费资源吗? - ניר

2
在Python中,“原生类型”是什么?请不要基于类型编写代码,使用“鸭子类型”。详情请见鸭子类型

谢谢,我会三思而后行的 =) - Aleksandr Motsjonov

2

现在是2020年,我正在使用Python 3.7版本,但是现有的解答都无法解决我的问题。相反,builtins模块可以解决我的问题。下面是解决方法:

import builtins
type(your_object).__name__ in dir(builtins)

1
您可以通过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)

1

对我来说,最好的选择是:

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

当值为模块且value.__class__.__module__ == '__builtin__'时,此修复将失败。


0
问题要求检查非类类型。这些类型没有__dict__成员(您也可以测试__repr__成员,而不是检查__dict__)。其他答案提到要检查types.__dict__.values()中的成员资格,但此列表中的某些类型是类。
def isnonclasstype(val):
    return getattr(val,"__dict__", None) != None

a=2
print( isnonclasstype(a) )

a="aaa"
print( isnonclasstype(a) )

a=[1,2,3]
print( isnonclasstype(a) )

a={ "1": 1, "2" : 2 }
print( isnonclasstype(a) )

class Foo:
    def __init__(self):
        pass

a = Foo()
print( isnonclasstype(a) )

给我:

> python3 t.py
False
False
False
False
True
> python t.py
False
False
False
False
True

numpy数组没有__dict__。 - slav

0
基于S.Lott的回答,你应该有类似这样的代码:

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可以处理对象,则会使用它。否则,将触发您的万能功能,并且可能(取决于是否使用可选部分)对象可以定义自己的序列化。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接