如何确定参数是对象还是内置类型?

5
我如何确定一个“变量”是否是内置的,比如字符串、列表、字典或数字,而不是“对象”。我正在尝试编写一个类似于deepcopy的函数,用于复制字典中的内置类型,但忽略对象。

2
Python中的所有东西都是对象。您可以使用type(object)来确定对象的类型。 - Ankur Ankan
@AnkurAnkan 这个问题是在询问如何检查内置类型,而不是预定类型。 - jamylak
@jamylak 我相信 @Ankur Ankan 只是在引导使用 type(object) - icedwater
1
请注意,99%的情况下,您不需要进行类型检查。在Python中,鸭子类型是标准,所以只需使用事物,并在它们失败时捕获异常即可。永远不要使用类型检查来检查功能,因为这样会排除像另一个类型一样的类型。 - Gareth Latty
@Lattyware,我知道,但在这种情况下,我没有其他简单的方法来做到这一点。我有一个要记录在数据库中的字典,但我只对可以作为纯文本进行JSON编码的内容感兴趣。在同一个字典中,我有一些回调和其他东西,我不想序列化它们。我不想用“del”按名称删除它们,因为我不想修改原始的字典。 - Prof. Falken
@Prof.Falken 为什么不自己制作一个JSONEncoder子类,忽略掉任何不能正常处理的内容呢? - Gareth Latty
8个回答

3

所有东西都是一个对象。如果你想确定某个对象是字符串、整数或其他类型,使用isinstance()函数:

>>> isinstance("hello!", str)
True
>>> isinstance("hello!", int)
False

因此,在您的情况下,似乎您只想使用字典调用函数:
>>> mylist = [3, "cabbage", 5.43, {'cat':'dog'}, {'horse':'elephant'}, ['another', 'list']]
>>> for i in mylist:
...     if isinstance(i, dict):
...         dostuff()

2

由于内置类型很少,您可以使用 if 进行检查:

if type(a)==int or type(a)==float or type(a)==str or type(a)==list or type(a)==dict:
        #do something

或者使用isinstance()函数。
if isinstance(a,(int,float,str,list,dict,set)):
    #do something

我不确定这是否是正确的方法,但这是检查给定变量是否为任何内置数据类型实例的方法之一。


2
isinstance() 更简洁 :) - TerryA
1
你也可以使用type(3)==int或type(3)==float。 - Ankur Ankan
在我看来,if any(isinstance(a, t) for t in (int, float, str, list, ...) 更符合 Python 风格... - glglgl
1
isinstance函数也可以接受元组作为第二个参数,因此 isinstance(a, (int, float, ...)) 也可以正常工作。 - Volatility
@Volatility:你的回答很好。所以我编辑了答案。 - Aswin Murugesh

1

我认为使用class.__module__属性是最好的选择,它保存了定义该类的模块名称

>>> import __builtin__
>>> int.__module__ == __builtin__.__name__
True

请注意,尽管内置模块会被自动导入,但我们需要导入它以将其引入范围并获取其名称。
对于用户定义的类:
>>> class A: pass
...
>>> A.__module__
'__main__'

说实话,我不知道怎么使用这个。 - Prof. Falken
1
def is_builtin(obj): return type(obj).__module__ == __builtin__.__name__ - icecrime

1

首先,一切皆为对象,所以我想你想要测试内置类型与用户定义类型之间的区别。

选择要排除的内置类型,并比较变量的type()。

if type(yourvar) in [list,set,int,float,str,dict]:
    print "builtin"
else:
    print "object"

通常情况下,isinstance 优于比较 type。但是,对于扩展内置类型的对象,isinstance 将为 True:
>>> class A(list):
    pass

>>> a = A()
>>> isinstance(a,list)
True

因此,如果您想要严格的内置类型,就不应该使用isinstance。

别忘了布尔类型!我在使用时需要添加它使我的代码工作。 :) - Max

0

仅限于CPython(也可能适用于其他实现):

import __builtin__

builtin_types = [x for x in __builtin__.__dict__.values() if isinstance(x, type)]
def is_builtin_type(x):
  for t in builtin_types:
    if isinstance(x, t):
       return True 

这包括内置的异常、字节数组、对象和其他一些东西,其他答案中的人没有提到 :-)


0

首先,在Python中,类和类型之间没有区别:

>>> type("234"), "234".__class__
(str, str)

测试一个对象类型可以具有两个不同的含义:

isinstance 测试您的对象是否为给定类型或子类型:

>>> class mystr(str): pass
>>> s = mystr(4)
>>> s
'4'
>>> ype(s)
__main__.mystr
>>> isinstance(s, str)
True

>>> type(s) is str
False
>>> type(s)
<class '__main__.mystr'>

顺便提一下,你不应该写成type(s) == str,而是type(s) is str
现在针对你的问题,一个可能的答案是:内置类型的模块是__builtin__
>>> str.__module__
'__builtin__'
>>> mystr.__module__
'__main__'

所以你可能可以写

>>> def is_of_builtin_type(obj):
        return type(obj).__module__ == '__builtin__'
>>> is_of_builtin_type("4223")
True
>>> class mystr(str): pass
>>> is_of_builtin_type(mystr(223))
False

注意:我还没有测试这个程序的健壮性。

0

顺便说一下,我采用了这个解决方案:(受this启发)

from six import integer_types, string_types, text_type

_copyable_types = (
    integer_types,
    string_types,
    text_type,
    list,
    dict,
    set,
)


def deepish_copy(org):
    '''
    Will copy a dict but ignore user objects at top level.
    '''
    out = {}

    for k, v in org.iteritems():
        if isinstance(v, _copyable_types):
            try:
                out[k] = v.copy()   # dicts, sets
            except AttributeError:
                try:
                    out[k] = v[:]   # lists, tuples, strings, unicode
                except TypeError:
                    out[k] = v      # ints

    return out

-2

简单明了

对于给定的变量var,使用函数isinstance(var, type),如果var是类型type,则返回True,否则返回False。你可以在解释器中轻松地检查它:

>>> a = 2
>>> isinstance(a, int)
True
>>> b = 'correct'
>>> isinstance(b, int)
False
>>> c = [1,2,3,4]
>>> isinstance(c, list)
True

......等等。因此,如果您想检查item是否为dict

if isinstance(item, dict):
    # handle the dict, do your deep copy
else:
    # meh, whatever

或者

考虑使用类型模块,它允许:

from types import DictType
def dictate(item):
    if isinstance(item, dict):
       # handle the dict
    else:
       # panic!

1
@Prof.Falken:请参考我的答案,其中有很好的解释。 - Aswin Murugesh
2
嘿,@AswinMurugesh,我正要把他引荐给你呢。 - icedwater
1
检查 type(var) 是一个糟糕的想法,它不允许子类化。 - Gareth Latty
谢谢,@Lattyware。我已经用isinstance()替换了它。 - icedwater

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