Python 如何检查对象是否是namedtuple的实例?

Python 如何检查对象是否是namedtuple的实例?,python,introspection,namedtuple,isinstance,Python,Introspection,Namedtuple,Isinstance,如何检查对象是否是集合的实例?调用函数集合。namedtuple提供了一个新类型,它是元组的子类(没有其他类),成员名为\u fields,该元组的项都是字符串。因此,您可以检查以下各项: def isnamedtupleinstance(x): t = type(x) b = t.__bases__ if len(b) != 1 or b[0] != tuple: return False f = getattr(t, '_fields', None)

如何检查对象是否是集合的实例?

调用函数
集合。namedtuple
提供了一个新类型,它是
元组的子类(没有其他类),成员名为
\u fields
,该元组的项都是字符串。因此,您可以检查以下各项:

def isnamedtupleinstance(x):
    t = type(x)
    b = t.__bases__
    if len(b) != 1 or b[0] != tuple: return False
    f = getattr(t, '_fields', None)
    if not isinstance(f, tuple): return False
    return all(type(n)==str for n in f)

有可能从中得到假阳性,但前提是有人千方百计地创建一个看起来像一个命名元组但不是一个的类型;-)

如果在对其调用namedtuple特定函数之前需要进行检查,那么只需调用它们并捕获异常即可。这是python中的首选方法。

我使用

isinstance(x, tuple) and isinstance(x.__dict__, collections.abc.Mapping)
在我看来,这最能反映命名元组本质的字典方面。
它看起来对将来可能发生的一些更改也很健壮,如果碰巧存在这样的情况,它还可能与许多第三方namedtuple ish类一起工作。

如果要确定对象是否是特定namedtuple的实例,可以执行以下操作:

from collections import namedtuple

SomeThing = namedtuple('SomeThing', 'prop another_prop')
SomeOtherThing = namedtuple('SomeOtherThing', 'prop still_another_prop')

a = SomeThing(1, 2)

isinstance(a, SomeThing) # True
isinstance(a, SomeOtherThing) # False

改进Lutz发布的内容:

def isinstance_namedtuple(x):                                                               
  return (isinstance(x, tuple) and                                                  
          isinstance(getattr(x, '__dict__', None), collections.Mapping) and         
          getattr(x, '_fields', None) is not None)                                  
3.7+


在我看来,这可能是Python3.6及更高版本的最佳解决方案

在实例化namedtuple时,您可以设置自定义的
\uuuuuuu模块\uuuuuuuu
,并在以后进行检查

从集合导入namedtuple
#python 3.6中添加的模块参数
namespace=namedtuple(“namespace”,“foo-bar”,module=\uuuuu-name\uuuuu+”.namespace”)
然后检查是否有
\uuuuu模块\uuuuu


如果getattr(x,“\uuuuu module\uuuuuuu”,None)=“xxxx.namespace”:

您需要绝对了解,还是启发式可以?如果是后者,您可以检查例如obj.\u asdict.\uu doc\uuuu=='返回一个新的OrderedDict,它将字段名称映射到它们的值(也可能是其他因素)。当然是绝对的。但是,由于我只在
assert
语句中使用这个“检查”(我正在编写一个对namedtuples的扩展,其中mixin断言它与namedtuples一起用作其同级基类),启发式检查也可以。我认为在下面Alex的代码中添加你的
\uuuu doc\uuuuuu
检查是值得的。FWIW,这是一个“bug”(不确定我是否同意):我在上面给Matthew的回复中解释了我在哪里使用这个检查。为什么namedtuple的设计师要让它可以进行类型检查,Sridhar?在Python中,通常避免进行类型检查,在这种情况下,不会告诉您任何有用的信息—一个包含
x
y
字段的命名偶和一个包含
成本
价格
数量
字段的命名偶将不可互换。它们可以互换的唯一级别是它们都是元组。即使在使用namedtuple工厂生成的类的用例中,它们也只是正常的类,有充分的理由,可以像类似的手工类一样使用。@Srindhar:您实际上不需要检查这是否是namedtuple生成的类的实例,您只需要将其用于mixin即可。一个写坏代码的愚蠢用户不能通过检查来修复,而一个使用你的代码的聪明用户只会受到检查的潜在阻碍。(另外,由于
assert
s不能保证运行,因此它们不是检查您需要检查的内容的正确工具。)@mixin不需要只用于断言的检查@MikeGraham古代邮政,但是。。。检查
namedtuple
类型的一个原因是,如果要序列化/封送它的实例。编组
namedtuple
的方式与普通元组的方式有很大不同,因为您希望以某种方式保留名称。@MikeGraham For
json.dumps
。或者其他任何你想做不同操作的场合。除非我遗漏了什么,否则这似乎是最好、最简洁的答案。namedtuple创建一个新类型,isinstance将检查某个类型是否为该类型。这与接受的答案不同——这个答案检查特定namedtuple的一个实例,而接受的答案检查任何namedtuple的一个实例。它不再有
\u dict\u
def isinstance_namedtuple(obj) -> bool:
    return (
            isinstance(obj, tuple) and
            hasattr(obj, '_asdict') and
            hasattr(obj, '_fields')
    )