Karinoya 学习室 资格考试 Cloud / AI / Python 合格实验室 异常、类与标准库
日本語 English Français Bahasa Indonesia 한국어 Română ไทย Tiếng Việt 简体中文 繁體中文
资格考试 · Cloud / AI / Python 合格实验室
异常、类与标准库 可以用简体中文阅读题目和解说。讲义(解说文章)仅有日文版。
查看日文版(含讲义) →
第1题 | try语句的顺序
执行以下代码时,按从上到下的顺序输出的行是哪一项?
def calc(a, b): try: print("try") r = a / b except ZeroDivisionError: print("except") else: print("else") finally: print("finally") calc(9, 3) try、else、except try、else、finally try、except、else try、except、finally 正确答案 B. try、else、finally 9 / 3不会引发异常,因此不会进入except。只有在没有发生异常时才会执行的是else子句,因此try之后会执行else。finally子句无论有无异常都一定会执行,因此最后运行。因此结果是try、else、finally这3行。含有except的选项,是误以为发生了异常时的排列,这次调用不会产生ZeroDivisionError。缺少finally的选项,是把finally误解为『发生异常时的善后处理』时的排列。
第2题 | else子句
关于try语句的else子句被执行的条件,正确的是哪一项?
无论是否发生异常,总是最后执行 只有在try节发生异常时才会执行 在与任何except节都不匹配时执行 只有在try节没有发生异常时才会执行 正确答案 D. 只有在try节没有发生异常时才会执行 try语句的else子句,只有在try节没有引发异常地执行到最后时才会执行。与if语句的else是『条件为假时』相对,try语句的else是站在『顺利成功』一侧的,方向相反,可以这样来记。发生异常时执行的是except节。无论是否发生异常都一定会执行的是finally节。如果与任何except都不匹配,并不会落到else,而是该异常会继续向调用方传播。
第3题 | finally优先
执行以下代码时的输出是哪一项?
def f(): try: return "T" finally: print("F") def g(): try: return "T" finally: return "N" print(f(), g()) 输出2行:F 和 T T 输出2行:F 和 T N 输出2行:T T 和 F 输出2行:T N 和 F 正确答案 B. 输出2行:F 和 T N f()准备好要return的值之后,在真正返回之前会先执行finally节。因此F会先显示,返回值仍保持T。g()的finally节中含有return,这会覆盖try节中的return,因此返回值变为N。print会先对f()和g()求值,再汇总到一行显示,因此F那一行在前,T N那一行在后。得到T T的选项,是认为finally的return会被忽略时的答案;F排在后面的选项,是认为finally在return之后才运行时的答案。
第4题 | 无法被捕获的异常
写成except Exception的except节无法捕获的异常是哪一项?
FileNotFoundError ZeroDivisionError KeyboardInterrupt ModuleNotFoundError 正确答案 C. KeyboardInterrupt KeyboardInterrupt直接位于BaseException之下,并未继承Exception。issubclass(KeyboardInterrupt, Exception)为False。它是用户按下Ctrl-C想要中止程序时产生的,为了不被写得较宽泛的except Exception不小心吞掉,特意把层级分开。SystemExit也处于同样的位置。其余三个都是Exception的后代:ZeroDivisionError在ArithmeticError之下,FileNotFoundError在OSError之下,ModuleNotFoundError在ImportError之下,因此都能被except Exception捕获。
第5题 | 异常的父类
IndexError与KeyError共同的最近父类是哪一项?
ReferenceError ArithmeticError AttributeError LookupError 正确答案 D. LookupError IndexError和KeyError都具有『用下标或键去查找却没有找到』这一相同性质,因此被放在共同的父类LookupError之下。写成except LookupError,就能把列表越界访问和字典中不存在的键这两种情况一并接住。ArithmeticError是ZeroDivisionError等的父类,用于计算本身无法成立的场合。AttributeError是属性找不到时的异常,ReferenceError是弱引用所指对象已消失时的异常,两者都直接位于Exception之下,与LookupError属于不同的谱系。
第6题 | except的顺序
执行以下代码时,正确的输出是哪一项?
try: x = 8 / 0 except ArithmeticError: print("A") except ZeroDivisionError: print("Z") 什么都不输出就停止 只输出Z 输出A和Z 只输出A 正确答案 D. 只输出A 8 / 0会抛出ZeroDivisionError,而ZeroDivisionError是ArithmeticError的子类。except节会按从上到下的顺序匹配,一旦匹配就停止,因此先写的except ArithmeticError会先接住它,只输出A。后面的except ZeroDivisionError没有出场的机会。由于只会执行匹配到的那一个except,A和Z不会同时输出。原则是把较窄的(子类)放在前面、较宽的(父类)放在后面,本题的代码正好把这个顺序反了过来。
第7题 | 多个异常
执行以下代码时显示的1行是哪一项?
def conv(s): try: return int(s) * 2 except (ValueError, TypeError) as e: return type(e).__name__ print(conv("21"), conv("abc"), conv(None)) 42 ValueError TypeError 42 TypeError TypeError 42 ValueError ValueError 42 TypeError ValueError 正确答案 A. 42 ValueError TypeError 在except后面写用圆括号括起来的元组,只要匹配其中任意一个就会执行。conv("21")中int("21")得到21,因此返回42。conv("abc")虽然能作为字符串传入,但无法解释为数值,因此会是ValueError。conv(None)不是int()能接受的类型,因此是TypeError。类型正确但值不合适则是ValueError,类型本身就不对则是TypeError,这一区分正好对应答案的排列。
第8题 | 重新抛出
使用自定义异常和不带参数的raise的以下代码,其输出是哪一项?
class LoadError(Exception): pass def load(): try: raise LoadError("bad") except LoadError: print("inner") raise try: load() except Exception as e: print("outer", type(e).__name__) 只有inner,outer不会输出 inner和outer Exception共2行 inner和outer LoadError共2行 输出inner之后在LoadError处停止 正确答案 C. inner和outer LoadError共2行 在except内部只写raise而不带参数,会把当前正在处理的异常原样重新抛给调用方。因此显示inner之后,LoadError会传到load()的外部,被外层的except Exception接住。由于LoadError继承自Exception,能被except Exception捕获,因此不会停止。type(e).__name__返回的是实际被抛出的异常类的名字,因此显示的不是捕获一方的类型名Exception,而是LoadError。只输出inner,是没有重新抛出、而是当场吞掉时的输出。
第9题 | 未被捕获的异常
执行以下代码会得到怎样的结果?
def get(seq, key): try: return seq[key] except IndexError: return "not found" print(get([1, 2, 3], 1)) print(get({"a": 1}, "z")) 显示2之后,在KeyError处停止 输出2行:2 和 not found 输出2行:2 和 KeyError 输出2行:2 和 None 正确答案 A. 显示2之后,在KeyError处停止 第一次调用是列表的下标1,因此返回2。第二次是查找字典中不存在的键,因此会引发KeyError,但except中写的只有IndexError。IndexError和KeyError虽然都是LookupError的子类,但彼此之间并非父子关系,因此IndexError的except接不住KeyError。未被捕获的异常会传到调用方,由于没有人接住,程序会停止。想同时接住两者,应写成except LookupError,或者用元组把两者并列。
第10题 | assert
关于assert语句的说明,正确的是哪一项?
条件为假时抛出AssertionError,在python3 -O下会被禁用 条件为假时抛出AssertionError,即使在python3 -O下也一定会执行 条件为真时抛出AssertionError,在python3 -O下会被禁用 条件为假时抛出ValueError,即使在python3 -O下也一定会执行 正确答案 A. 条件为假时抛出AssertionError,在python3 -O下会被禁用 assert 条件, 消息 会在条件为假时抛出AssertionError。条件为真时什么都不会发生。重要的是,若以python3 -O这样的优化模式启动,assert语句会被整体移除,一行也不会执行。因此不应把assert用于检查用户输入这一目的,那种用途应该用if判断条件后抛出raise ValueError(...)。可以把assert理解为在开发过程中记录内部前提的工具,这样区分二者的角色比较合适。
第11题 | self
关于方法的第1个参数self的说明,正确的是哪一项?
用于引用父类属性而保留的名字 调用它的实例自身被自动传入的参数 用于生成实例并返回给调用方的参数 类本身会被自动传入的保留名字 正确答案 B. 调用它的实例自身被自动传入的参数 写成 d.speak() 时,Python会把它改写为 Dog.speak(d) 来调用。此时进入第1个参数位置的,正是发起调用的实例本身。self这个拼写只是约定俗成,并非语言保留的名字。规范只规定了第1个参数接收自身这一位置,因此即使自己写成 Dog.speak(d) 也能同样运作。创建并返回实例是__new__和类调用机制的职责,__init__只是对已经创建好的实例进行初始化。引用父类需要使用super()。
第12题 | 类变量
改写类变量的以下代码,其输出是哪一项?
class Dog: kind = "canine" def __init__(self, name): self.name = name a = Dog("Rex") b = Dog("Mia") Dog.kind = "wolf" print(a.kind, b.kind) wolf wolf canine wolf canine canine wolf canine 正确答案 A. wolf wolf kind是写在class正下方的类变量,由该类创建出的所有实例共享同一个。a和b自己的__dict__中都没有kind,因此读取该属性时会一路追溯到类那一侧,看到相同的值。对 Dog.kind 的赋值改写的正是这个被共享的唯一对象,因此已经创建好的a和b两者都会看到wolf。创建实例时并不会把值复制一份,因此不会得到保留canine的选项。
第13题 | 属性的阴影
在实例一侧赋值的以下代码,其输出是哪一项?
class Dog: kind = "canine" def __init__(self, name): self.name = name a = Dog("Rex") b = Dog("Mia") a.kind = "husky" print(a.kind, b.kind, Dog.kind) print(sorted(a.__dict__)) husky husky husky 以及 ['name'] husky canine canine 以及 ['kind', 'name'] husky canine canine 以及 ['name'] husky husky husky 以及 ['kind', 'name'] 正确答案 B. husky canine canine 以及 ['kind', 'name'] 对 a.kind 赋值不会改写类变量,而是在a的实例字典中新建一个名为kind的条目。此后读取a.kind时会优先找到这个新条目,从而遮住了类变量,形成『阴影』。b和Dog.kind仍保持原来的canine不变。因此a.__dict__中除了__init__放入的name之外还并列着kind,排序后得到['kind', 'name']。全部变成husky的选项,是误以为对实例的赋值会改写类变量时的答案;只剩['name']的选项,是认为不会产生阴影时的答案。
第14题 | 被共享
把列表设为类变量的以下代码,其输出是哪一项?
class Basket: items = [] def add(self, x): self.items.append(x) p = Basket() q = Basket() p.add(1) q.add(2) print(p.items, q.items) p.items 为 [1],q.items 为 [1, 2] p.items 为 [1, 2],q.items 为 [2] p.items 为 [1, 2],q.items 为 [1, 2] p.items 为 [1],q.items 为 [2] 正确答案 C. p.items 为 [1, 2],q.items 为 [1, 2] self.items.append(x) 并不是对self.items赋值,而只是调用了通过self.items找到的那个对象。由于p和q都没有自己的items,找到的都是类变量那同一个列表。结果无论是从p添加的1,还是从q添加的2,都进入了同一个列表,从哪个实例来看都是[1, 2]。如果想让每个实例各自拥有独立的容器,需要在__init__中通过 self.items = [] 来赋值创建,这样就会分别得到[1]和[2]。
第15题 | super()
使用继承与super()的以下代码,其输出是哪一项?
class Animal: def __init__(self, name): self.name = name def cry(self): return self.name + " ?" class Cat(Animal): def __init__(self, name, color): super().__init__(name) self.color = color def cry(self): return self.name + " meow" c = Cat("Tama", "black") print(c.cry(), c.color, isinstance(c, Animal)) Tama meow None True Tama ? black True Tama meow black False Tama meow black True 正确答案 D. Tama meow black True Cat的__init__调用了super().__init__(name),因此父类Animal会替它设置好self.name。之后再把black存入self.color,两个属性因此都齐备。cry在子类中被重新定义,父类的实现被覆盖,因此调用的是meow那一个。isinstance(c, Animal)由于Cat继承自Animal,结果为True。如果忘记写super(),name就不会被设置,会引发AttributeError,而不会像选项中那样悄悄变成None这种失败方式。
第16题 | MRO
多重继承的以下代码,其输出是哪一项?
class A: def who(self): return "A" class B(A): def who(self): return "B" class C(A): def who(self): return "C" class D(B, C): pass print(D().who()) print([k.__name__ for k in D.__mro__]) B 与 ['D', 'B', 'C', 'A', 'object'] C 与 ['D', 'C', 'B', 'A', 'object'] B 与 ['D', 'B', 'A', 'C', 'object'] A 与 ['D', 'B', 'C', 'A', 'object'] 正确答案 A. B 与 ['D', 'B', 'C', 'A', 'object'] 方法解析顺序由C3线性化这一规则决定,并非单纯的深度优先。共同的父类A会被放在所有继承自A的子类之后,因此排列为D、B、C、A、object。如果是钻进B就直接走到A的深度优先方式,会得到D、B、A、C、object,但实际并非如此,这正是需要留意的地方。who()会从MRO开头查找,使用最先找到的那个,因此返回B。如果写成 class E(C, B),就会得到E、C、B、A、object,写在前面的优先。
第17题 | MRO的矛盾
在已定义 class B(A) 的情况下,写出 class F(A, B): pass 会发生什么?
能够定义成功,F().who() 调用的是A的方法 能够定义成功,__mro__ 会是 F、A、B、object 能够定义成功,F().who() 调用的是B的方法 在类定义的时刻发生 TypeError 正确答案 D. 在类定义的时刻发生 TypeError C3线性化有两条规则:要保持列出基类的顺序,并且父类必须排在子类之后。F(A, B)指定要把A排在B之前,但B是A的子类,因此父类A必须排在子类B之后。这两点无法同时满足,因此判定为无法构造出一致的MRO,在对类定义求值的那一刻就会发生TypeError。这不是要等到实际运行才会发现,而是在通过class语句的瞬间就会失败。正确写法应是 class F(B, A),把子类写在前面。
第18题 | 名称修饰
拥有以下划线开头属性的以下代码,其输出是哪一项?
class P: def __init__(self): self._one = 1 self.__two = 2 p = P() print(p._one, p._P__two) print(sorted(p.__dict__)) 1 2 与 ['_one', '_two'] 1 2 与 ['_P__one', '_P__two'] 1 2 与 ['__two', '_one'] 1 2 与 ['_P__two', '_one'] 正确答案 D. 1 2 与 ['_P__two', '_one'] 以单个下划线开头的_one只是按惯例表示供内部使用,名字本身不会改变,从外部也能照常读取。以两个下划线开头的__two会触发名称修饰,实际的属性名会被改写为_P__two,即『_类名__名字』的形式。因此写成p.__two会得到AttributeError,但写成p._P__two就能读到。__dict__中排列的也是修饰后的名字,因此排序后得到['_P__two', '_one']。只有以两个下划线开头的才会被修饰,_one不在此列。
第19题 | 特殊方法
定义了特殊方法的以下代码,其输出是哪一项?
class Vec: def __init__(self, x, y): self.x = x self.y = y def __str__(self): return "V({}, {})".format(self.x, self.y) def __repr__(self): return "Vec(x={}, y={})".format(self.x, self.y) def __len__(self): return 2 def __add__(self, o): return Vec(self.x + o.x, self.y + o.y) v = Vec(1, 2) print(v) print([v]) print(len(v), v + Vec(3, 4)) Vec(x=1, y=2) 与 [Vec(x=1, y=2)] 与 2 V(4, 6) V(1, 2) 与 [Vec(x=1, y=2)] 与 2 V(4, 6) V(1, 2) 与 [Vec(x=1, y=2)] 与 2 Vec(x=4, y=6) V(1, 2) 与 [V(1, 2)] 与 2 V(4, 6) 正确答案 B. V(1, 2) 与 [Vec(x=1, y=2)] 与 2 V(4, 6) print(v)与str(v)使用的是__str__,因此得到V(1, 2)。而放入列表或字典等容器中显示时,每个元素会使用__repr__,因此得到[Vec(x=1, y=2)]。这一区分正是本题的要点。len(v)是__len__返回的2,v + Vec(3, 4)是__add__返回的新Vec,把它传给print时又会用到__str__,因此显示为V(4, 6)。没有定义__str__的类会用__repr__代替,但反过来__str__不会代替__repr__被使用。
第20题 | __eq__
只定义了__eq__的以下代码,其输出是哪一项?
class Point: def __init__(self, x): self.x = x def __eq__(self, other): return self.x == other.x p = Point(1) q = Point(1) print(p == q, p is q) print(Point.__hash__ is None) try: print(len({p, q})) except TypeError: print("TypeError") True False 与 False 与 2 True False 与 True 与 TypeError True False 与 False 与 1 True True 与 True 与 TypeError 正确答案 B. True False 与 True 与 TypeError 由于定义了__eq__,p == q 会比较属性x,结果为True,但p和q是分别创建的两个对象,因此p is q仍为False。这里重要的是:定义了__eq__的类,其__hash__会被自动设为None,因此 Point.__hash__ is None 为True。没有哈希值的对象无法用作集合或字典的键,因此试图构造{p, q}会引发TypeError。如果也想把它放入集合,需要自己定义一个在相等时返回相同值的__hash__。
第21题 | math
使用math模块的以下代码,其输出是哪一项?
import math print(math.sqrt(16)) print(math.floor(-1.5), math.ceil(-1.5)) 4.0 与 -2 -1 4.0 与 -1 -2 4 与 -2 -1 4 与 -1 -1 正确答案 A. 4.0 与 -2 -1 math.sqrt即使能整除也会返回float,因此16的平方根不是显示为4而是4.0。math.floor是向数轴下方截断,因此-1.5变为-2;math.ceil是向上方,因此-1.5变为-1。要注意的是,对于负数,朝0方向截断的int(-1.5)会得到-1,这与floor的结果不一致。如果把floor和ceil弄反,就会得到-1 -2的排列;如果误以为sqrt的返回值类型是int,就会得到4。
第22题 | os.path
os.path.splitext('/tmp/z.txt') 与 os.path.basename('/tmp/z.txt') 返回值的组合是哪一项?
('/tmp/z', '.txt') 与 'z.txt' ('/tmp', 'z.txt') 与 '/tmp' ('/tmp/z', 'txt') 与 'z.txt' ('/tmp/z.txt', '') 与 'z.txt' 正确答案 A. ('/tmp/z', '.txt') 与 'z.txt' os.path.splitext只会把扩展名切分出来,点仍保留在扩展名一侧,返回一个2元素的元组。因此结果是 ('/tmp/z', '.txt'),不会出现点被去掉、变成'txt'的情况。os.path.basename返回路径末尾的名字,因此是'z.txt'。返回目录一侧'/tmp'的是os.path.dirname,如果想要把两者一并得到的元组,应使用os.path.split。可以这样区分记忆:splitext是按扩展名切分,而不是按目录分隔符切分。
第23题 | re的匹配
使用re模块的以下代码,其输出是哪一项?
import re print(re.match("b", "abc")) print(re.search("b", "abc").group()) print(re.findall(r"\d+", "a1b22c333")) b 与 None 与 ['1', '22', '333'] None 与 b 与 ['1', '22', '333'] b 与 b 与 ['1', '22', '333'] None 与 b 与 ['a1', 'b22', 'c333'] 正确答案 B. None 与 b 与 ['1', '22', '333'] re.match只从字符串开头开始匹配,'abc'的开头是'a',与'b'不匹配,因此返回None。re.search会在中途也进行查找,因此能匹配到'b',用.group()可以取出匹配到的字符串b。这一区别是re中最常被考查的地方。re.findall会返回一个收集了所有与模式匹配部分的列表,\\d+表示连续的数字,因此结果是['1', '22', '333'],不会连分隔用的字符也包含进去。如果没有匹配,则返回空列表。
第24题 | datetime
使用datetime的以下代码,其输出是哪一项?
import datetime d = datetime.date(2026, 8, 22) print(d) print(d.strftime("%Y/%m/%d")) print(d + datetime.timedelta(days=10)) 2026/08/22 与 2026/08/22 与 2026/09/01 2026-08-22 与 2026/08/22 与 2026-09-01 2026-08-22 与 2026/08/22 与 10 days, 0:00:00 2026-08-22 与 2026/08/22 与 2026-08-32 正确答案 B. 2026-08-22 与 2026/08/22 与 2026-09-01 直接print一个date对象,会以ISO格式、用连字符分隔显示为2026-08-22。想改变格式时使用strftime,传入'%Y/%m/%d'会返回用斜杠分隔的字符串2026/08/22。给date加上timedelta(days=10),返回的不是timedelta,而是指向10天后的新date,因此print出来是2026-09-01。跨月的计算由datetime一方负责处理,因此不会出现只是把日期数字加10、变成不存在的日期(如2026-08-32)这种情况。如果认为print(d)会与strftime相同格式,就会误以为是斜杠分隔,但默认显示是连字符分隔。日期相减得到的不是date而是timedelta,其显示会是像10 days, 0:00:00这样的形式。
第25题 | Counter
使用collections.Counter的以下代码,其输出是哪一项?
from collections import Counter c = Counter("abracadabra") print(c.most_common(2)) print(c["a"], c["z"]) [('a', 5), ('b', 2)] 与 5 与 KeyError [('a', 5), ('r', 2)] 与 5 0 [('a', 5), ('b', 2)] 与 5 0 [('a', 5), ('b', 2), ('r', 2)] 与 5 0 正确答案 C. [('a', 5), ('b', 2)] 与 5 0 'abracadabra'中a有5个,b和r各有2个,c和d各有1个。most_common(2)会按数量从多到少只返回前2项,形式是(元素, 个数)组成的元组列表,因此是[('a', 5), ('b', 2)]。个数相同的b和r,先出现的排在前面,因此采用b。Counter虽是字典的一种,但查找不存在的元素不会引发KeyError,而是返回0,这一点与普通字典不同。这样设计是为了不必先确认存在与否就能直接计数。
第26题 | namedtuple
使用namedtuple创建的类型的以下代码,其输出是哪一项?
from collections import namedtuple Pt = namedtuple("Pt", "x y") p = Pt(1, 2) print(p) print(p.x, p[0], isinstance(p, tuple)) (1, 2) 与 1 1 True Pt(x=1, y=2) 与 1 1 False Pt(x=1, y=2) 与 1 1 True Pt(1, 2) 与 1 1 False 正确答案 C. Pt(x=1, y=2) 与 1 1 True namedtuple创建的类型,显示时会呈现出带有类型名和字段名的Pt(x=1, y=2)这种形式。值既可以按名字读取,也可以按下标读取,因此p.x和p[0]都是1。而且namedtuple是元组的派生类型,因此isinstance(p, tuple)为True。也就是说它是元组的一种,元素事后不能被改写。如果想持有事后可改的值,需要使用会创建替换了值的新实例的_replace,或者定义普通的类。
第27题 | 用尽
把同一个map对象传给list()两次的以下代码,其输出是哪一项?
m = map(str, [1, 2, 3]) print(list(m)) print(list(m)) 第1行为 ['1', '2', '3'],第2行为 None 第1行为 ['1', '2', '3'],第2行为 [] 第1行为 [1, 2, 3],第2行为 [] 第1行和第2行都为 ['1', '2', '3'] 正确答案 B. 第1行为 ['1', '2', '3'],第2行为 [] map返回的不是列表而是迭代器,每次next()只递送一个下一个值,用尽后就没有了。第1次list()就已把3个值全部取出,因此第2次list()会得到一个什么都不剩的空列表。它既不会报错也不会变成None,而是悄悄变空,因此不容易察觉。map(str, ...)会把各元素转成字符串,因此第1次的内容不是数值,而是['1', '2', '3']。同样的情况也会发生在filter、zip、enumerate以及生成器上,如果要遍历多次,应在拿到后立即用list()固定下来。
第28题 | filter与all
使用filter、all、any的以下代码,其输出是哪一项?
print(list(filter(None, [0, 1, "", 2, None, "a"]))) print(all([]), any([])) [1, 2, 'a'] 与 False False [0, '', None] 与 True False [1, 2, 'a'] 与 True False [1, 2, 'a'] 与 False True 正确答案 C. [1, 2, 'a'] 与 True False 给filter的第1个参数传入None,会按元素本身的真假来筛选。0、空字符串、None都会被判为假而被剔除,剩下的是[1, 2, 'a'],不是被剔除的那些留了下来。all的规格是只要没有一个假元素就返回True,因此对一个元素都没有的空列表也会返回True。any的规格是只要有一个真元素就返回True,因此为空时返回False。传入空序列时这两者给出相反的结果,正是容易被考查的地方。
第29题 | 生成器
调用含有yield的函数的以下代码,输出行的顺序是哪一项?
def gen(): print("start") yield 1 print("mid") yield 2 g = gen() print("created") print(next(g)) print(next(g)) 按 start mid created 1 2 的顺序 按 created start mid 1 2 的顺序 按 created start 1 mid 2 的顺序 按 start created 1 mid 2 的顺序 正确答案 C. 按 created start 1 mid 2 的顺序 即使调用了含有yield的函数,函数体也一行都不会执行。返回的只是一个生成器对象,因此会先显示created。第一次next(g)才会真正从头开始运行,显示start之后在yield 1处停下并返回1。下一次next(g)会从停下的地方继续,显示mid,在yield 2处停下并返回2。这种延迟执行正是与普通函数的决定性区别,如果再调用一次next(g),函数就会结束并引发StopIteration。
第30题 | is与==
并列使用is运算符与==运算符的以下代码,其输出是哪一项?
a = [1, 2] b = [1, 2] c = a print(a == b, a is b) print(a == c, a is c) True False 与 True False True True 与 True True False False 与 True True True False 与 True True 正确答案 D. True False 与 True True ==是询问值是否相等的运算符,由于内容相同,a和b会得到True。is是询问是否为同一个对象的运算符,a和b是分别创建的两个列表,因此为False。而 c = a 并没有创建新列表,只是给同一个对象起了别名,因此 a is c 为True。也就是说,通过c改写列表,从a这一侧也能看到变化。None是唯一存在的特殊对象,因此写成 x is None 是惯用写法,但想比较值时应始终使用==。
练习:做本页的题目 这是随机出题的练习工具(在启用 JavaScript 时运行)。即使不使用此工具,也可以阅读上方的全部题目和解说。
※ 解说是供学习用的信息。考试的出题范围和制度每年可能变化,请务必确认主办机构的官方公告。
本页面译自日文原文。如译文与原文内容不一致,以日文版为准。 查看日文原文