1 Python 2 和 3 除法区别
Python 2 和 Python 3 在除法运算上的区别主要体现在 /
运算符的行为上,这是两个版本之间一个重要的语法差异,具体区别如下:
-
/
运算符的行为- Python 2 :
- 当两个操作数都是整数时,
/
执行整数除法(地板除),结果会向下取整为整数。 - 例如:
5 / 2 = 2
,9 / 4 = 2
,10 / 3 = 3
- 如果至少有一个操作数是浮点数,
/
会返回浮点数结果。 - 例如:
5.0 / 2 = 2.5
,9 / 4.0 = 2.25
- 当两个操作数都是整数时,
- Python 3 :
- 无论操作数是整数还是浮点数,
/
始终执行真除法,结果为浮点数。 - 例如:
5 / 2 = 2.5
,9 / 4 = 2.25
,10 / 3 = 3.333...
- 无论操作数是整数还是浮点数,
- Python 2 :
-
//
运算符(地板除)- 两个版本中,
//
的行为一致,均执行地板除(向下取整),结果的类型取决于操作数: - 若操作数都是整数,结果为整数;若有浮点数,结果为浮点数。
- 例如:
- Python 2 和 Python 3 中均有:
5 // 2 = 2
,9 // 4 = 2
,5.0 // 2 = 2.0
- Python 2 和 Python 3 中均有:
- 两个版本中,
总结来说,核心差异就是 \
运算符在处理整数除法时的行为:Python 2 中整数相除会截断为整数,而 Python 3 中整数相除也会返回浮点数。如果需要在两个版本中都实现地板除功能,使用 //
是统一的方式。
这个区别在代码迁移或跨版本兼容时需要特别注意,避免因除法行为不同导致计算错误。
2 Python 中字符串的find()
方法的用法
python
在Python3中关于下列字符串程序运行结果为( )
str1 = "exam is a example!"
str2 = "exam"
print(str1.find(str2, 7))
A -1
B 14
C 0
D 10
正确答案:D
这道题考查的是 Python 中字符串的find()
方法的用法,我们一步步来分析:
1. 先明确find()
方法的作用
str.find(sub, start)
表示:在字符串 str
中,从 start
索引位置开始(包含该位置),查找子字符串 sub
第一次出现的起始索引。
- 如果找到,返回对应的索引值;
- 如果没找到,返回
-1
。
2. 分析题目中的变量
str1 = "exam is a example!"
(字符串内容)str2 = "exam"
(要查找的子字符串)- 要执行的操作:
str1.find(str2, 7)
,即从str1
的索引7
位置开始,查找str2
第一次出现的位置。
3. 拆解str1
的索引(关键!)
字符串的索引从 0
开始,我们逐个标记 str1
的每个字符及其索引:
字符 | e | x | a | m | 空格 | i | s | 空格 | a | 空格 | e | x | a | m | p | l | e | ! |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
索引 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
4. 执行查找过程
str1.find(str2, 7)
的含义是:从索引 7
开始,找 sub="exam"
第一次出现的位置。
- 索引
7
对应的字符是空格,从这里往后看: - 索引
10
开始的字符是e
,后续依次是x
(11)、a
(12)、m
(13),刚好组成sub="exam"
。
因此,"exam"
从索引 10
开始出现,所以返回 10
。
答案总结
正确答案是 D。
3 有关闭包的陷阱的题目
python
执行下列程序,输出结果为()
def fn():
t = []
i = 0
while i < 2:
t.append(lambda x: print(i*x,end=","))
i += 1
return t
for f in fn():
f(2)
A 4,4,
B 2,2,
C 0,1,
D 0,2,
正确答案:A
让我们详细分析这个程序的执行过程和结果。
首先,我们来看这个程序的结构:
- 定义了一个函数
fn()
,它会创建一个列表t
并返回 - 在
fn()
中,通过while
循环向列表t
中添加两个 lambda 函数 - 最后通过
for
循环调用这两个函数,传入参数2
关键在于理解 lambda 函数和变量作用域的关系。
当我们在循环中执行t.append(lambda x: print(i*x,end=","))
时,lambda 函数并没有立即时执行,它只是被创建并添加到列表中。这个 lambda 函数引用了变量i
,但这里需要注意:lambda 函数捕获的是变量i
本身,而不是它在定义时的值。
循环执行过程:
- 第一次循环:i=0,添加一个 lambda 函数到 t 中,此时这个函数引用的是变量 i
- i 变为 1
- 第二次循环:i=1,再添加一个 lambda 函数到 t 中,这个函数也引用变量 i
- i 变为 2,循环结束
此时,列表 t 中有两个 lambda 函数,它们都引用着同一个变量 i,而此时 i 的值已经是 2(因为循环结束条件是 i<2)。
当我们执行for f in fn(): f(2)
时:
- 第一个函数调用:计算 i*2,此时 i=2,结果为 4
- 第二个函数调用:同样计算 i*2,i 仍然是 2,结果为 4
所以最终的输出结果是:4,4,
这个例子展示了 Python 中闭包(closure)的一个常见陷阱:**内部函数引用外部变量时,捕获的是变量本身,而不是变量在定义时的值。**如果想要捕获变量在定义时的值,需要将其作为参数传入 lambda 函数,例如:
python
运行
python
t.append(lambda x, i=i: print(i*x, end=","))
这样修改后,输出结果才会是0,2,
。
4 Python 中闭包(closure)与变量作用域
缺少对 Python 中闭包(closure)与变量作用域 的理解,尤其是 函数对外部变量的延迟绑定 这一特性。具体来说,你可能需要补充以下知识点:
1. 闭包与变量的引用方式
闭包指的是 "嵌套在函数内部的函数,引用了外部函数的变量"。
在这个题目中:
lambda x: print(i*x, end=",")
是一个闭包,它引用了外部函数fn()
中的变量i
。- 关键误区:闭包 不会保存变量在定义时的值 ,而是 保存对变量本身的引用 。也就是说,lambda 函数记住的是 "
i
这个变量",而**不是**它在循环中每次的具体值(0 或 1)。
2. 变量的作用域与生命周期
- 变量
i
是在fn()
函数内部定义的,它的生命周期是整个fn()
函数执行期间。 - 循环结束后,
i
的值已经变成了 2(因为i
从 0 开始,经过两次自增后,i < 2
的条件不成立,最终i = 2
)。 - 当后续调用 lambda 函数时,它会去读取
i
当前的值(即 2),而不是定义时的值。
3. 函数的延迟执行特性
- 循环中
t.append(lambda ...)
只是将 lambda 函数 "保存" 到列表中,并没有立即执行。 - 只有当后续
for f in fn(): f(2)
时,lambda 函数才被真正调用。此时它才会去查找变量i
的当前值。
总结
这个题目本质上是在考察 闭包对外部变量的延迟绑定机制 。如果你之前没意识到 "函数会引用变量本身,而不是定义时的值",就很容易误以为两个 lambda 函数会分别使用 i=0
和 i=1
来计算,从而得到错误结果(比如 0,2,
)。
理解了这一点后,类似的问题(比如循环中定义函数、闭包引用外部变量)就会迎刃而解了。