如何检查不同作用域的namedtuple类型?为何type可用isinstance失败?
当函数内部定义namedtuple时,能否在外部用isinstance()检查类型?
首先直接给结论:不能直接在函数外部用isinstance()做检查,除非你把这个namedtuple类型暴露到外部作用域。
你遇到的type()能成功、isinstance()报错的情况,核心原因是作用域差异,具体拆解如下:
为什么type()能成功,isinstance()会失败?
Parsed_A是局部变量:你在parse_a函数内部定义的Parsed_A属于函数的局部作用域,函数外部的代码根本找不到这个名字,所以直接写isinstance(parsed_a, Parsed_A)会触发NameError——外部完全不知道Parsed_A是什么东西。type()直接从对象拿类型:每个Python对象本身都持有对自己类型的引用,type(parsed_a)是直接从这个对象身上获取它的类型对象,不管这个类型的名字在哪个作用域定义,对象自己都能提供这个信息,所以能正常返回结果。
另外补充一点:namedtuple()是个工厂函数,每次调用它都会创建一个全新的类——哪怕你每次给类起的名字都是Parsed_A,多次调用parse_a返回的对象其实属于不同的类。就算你想办法拿到第一次的Parsed_A类型,第二次调用返回的对象用isinstance检查也会返回False。
可行的解决办法
1. 把namedtuple移到全局作用域(推荐)
直接在函数外面定义Parsed_A,这样内外代码都能访问到这个类型:
from collections import namedtuple # 移到全局作用域 Parsed_A = namedtuple("Parsed_A", "attr1,attr2") def parse_a(raw_string): p = [x.strip() for x in raw_string.split(",")] return Parsed_A(attr1=p[0], attr2=p[1] if len(p) > 1 else None) parsed_a = parse_a("thing1,thing2") print(f'{type(parsed_a)=}') print(f'{isinstance(parsed_a, Parsed_A)=}') # 现在正常返回True
2. 从返回的对象获取类型做检查
如果必须在函数内部定义namedtuple,可以通过对象的__class__属性或者type()的结果来做判断:
parsed_a = parse_a("thing1,thing2") parsed_type = type(parsed_a) print(f'{isinstance(parsed_a, parsed_type)=}') # 返回True
注意:这种方式只能检查同一个函数调用返回的对象,因为每次调用parse_a都会生成新的类型。
3. 让函数同时返回对象和类型
如果不想把类型放到全局作用域,可以让函数把创建的类型也返回出来:
from collections import namedtuple def parse_a(raw_string): Parsed_A = namedtuple("Parsed_A", "attr1,attr2") p = [x.strip() for x in raw_string.split(",")] return Parsed_A(attr1=p[0], attr2=p[1] if len(p) > 1 else None), Parsed_A parsed_a, Parsed_A = parse_a("thing1,thing2") print(f'{isinstance(parsed_a, Parsed_A)=}') # 返回True
内容的提问来源于stack exchange,提问作者dewser_the_board
相关产品推荐
相关产品推荐

