学习日志25 python

1 Python 2 和 3 除法区别

Python 2 和 Python 3 在除法运算上的区别主要体现在 / 运算符的行为上,这是两个版本之间一个重要的语法差异,具体区别如下:

  1. / 运算符的行为

    • Python 2
      • 当两个操作数都是整数时,/ 执行整数除法(地板除),结果会向下取整为整数。
      • 例如:5 / 2 = 29 / 4 = 210 / 3 = 3
      • 如果至少有一个操作数是浮点数,/ 会返回浮点数结果。
      • 例如:5.0 / 2 = 2.59 / 4.0 = 2.25
    • Python 3
      • 无论操作数是整数还是浮点数,/ 始终执行真除法,结果为浮点数。
      • 例如:5 / 2 = 2.59 / 4 = 2.2510 / 3 = 3.333...
  2. // 运算符(地板除)

    • 两个版本中,// 的行为一致,均执行地板除(向下取整),结果的类型取决于操作数:
    • 若操作数都是整数,结果为整数;若有浮点数,结果为浮点数。
    • 例如:
      • Python 2 和 Python 3 中均有:5 // 2 = 29 // 4 = 25.0 // 2 = 2.0

总结来说,核心差异就是 \ 运算符在处理整数除法时的行为: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

让我们详细分析这个程序的执行过程和结果。

首先,我们来看这个程序的结构:

  1. 定义了一个函数fn(),它会创建一个列表t并返回
  2. fn()中,通过while循环向列表t中添加两个 lambda 函数
  3. 最后通过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=0i=1 来计算,从而得到错误结果(比如 0,2,)。

理解了这一点后,类似的问题(比如循环中定义函数、闭包引用外部变量)就会迎刃而解了。

相关推荐
鹿野素材屋10 分钟前
C#中对于List的多种排序方式
开发语言·c#
whxnchy14 分钟前
C++刷题 - 7.27
开发语言·c++
王者鳜錸19 分钟前
PYTHON从入门到实践-18Django从零开始构建Web应用
前端·python·sqlite
-Xie-29 分钟前
JVM学习日记(十三)Day13
jvm·学习
冗量30 分钟前
PPT自动化 python-pptx - 8: 文本(text)
python·自动化·powerpoint
白日梦想家-K1 小时前
题单【模拟与高精度】
开发语言·c++·算法
超级晒盐人1 小时前
用落霞归雁的思维框架推导少林寺用什么数据库?
java·python·系统架构·学习方法·教育电商
鹦鹉0071 小时前
IO流中的字节流
java·开发语言·后端
重生之我是Java开发战士1 小时前
【C语言】内存函数与数据在内存中的存储
c语言·开发语言·算法
haaaaaaarry1 小时前
Element Plus常见基础组件(二)
开发语言·前端·javascript