99% 人会做错的python题

Python常用机器学习库习题 随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。Python常用机器学习库习题Matplotlib、Opencv、PIL例如:以上就是今天要讲的内容,本文在学习python常用机器学习库的前提下进行习题上机练习。 阅读详情


本文含 2693 字,5 图表截屏

建议阅读 15 分钟

引言

题目:在不运行下面代码(Python 3 不是 Python 2)的情况下选择答案。

def f( x=[] ):
    x.append(1)
    return x
 
print( f(), f() )

很多人选第二个吧,[1] [1]。理由如下:一开始 x 是空列表,添加一个 1 不就是 [1] 吗?然后函数 f() 运行两遍。

还有人会选第三个吧,[1] [1, 1]。能选第三个的已经很强了,至少了解列表是可更改对象(mutable object),作为函数的默认参数(default argument)每次会更新参数的默认值。很棒,但是忽略了 print() 函数的运行机制。

答案是第四个, [1, 1] [1, 1]。

如果你选了第四个,你可以关闭页面,如果不是,请往下看,绝对能学到一些新的知识。你能需要的知识点是:

  1. 了解什么是不可更改对象和可更改对象

  2. 了解函数的默认参数

  3. 了解在 Python 3 里面 print() 是函数而不是语句(在 Python 2 里是语句)

不可更改对象 VS 可更改对象

判断一个数据类型 X 是不是可更改的呢?两种方法:

  • 方法一:用 id(X) 函数,对 X 进行某种操作,比较操作前后的 id,如果不一样,则 X 不可更改,如果一样,则 X 可更改。

  • 方法二:用 hash(X) 函数,只要不报错,证明 X 可被哈希,即不可更改,反过来不可被哈希,即可更改。

我们用方法一,id() 函数,来验证整数和列表是否可更改。

先看整数 i:

i = 1print( id(i) )i = i + 2print( id(i) )

1607630928
1607630992

整数 i 在加 1 之后的 id 和之前不一样,因此加完之后的这个 i (虽然名字没变),但是不是加前的那个 i 了,因此整数是不可更改的。

下图给上述过程做了可视化,在 Python 中,给 i 赋值 1 其实是创建一个 PyObject(有个字段存储的值为 1),然后将变量 i 指向这个 PyObject。当更新 i = i + 2 时,其实是新创建了个 PyObject(有个字段存储的值为 3),而将变量 i 指向新的 PyObject,旧的 PyObject 最后会被“回收”。

从新建 PyObject 这个特点可看出,整数不能更改。

再看列表 l:

l = [1, 10.31]print( id(l) )l.append('Python')print( id(l) )

2022027856840
2022027856840

列表 l 在附加 'Python' 之后的 id 和之前一样,因此列表是可更改的。

下图给上述过程做了可视化。我们发现,列表作为容器型数据,它本身的 PyObject,在添加或者删除元素的时候,没有改变。换句话说,列表是可更改的。

函数默认参数

先回顾一下题目中的代码:

def f( x=[] ):
    x.append(1)
    return x

在函数 f 中,x 是默认参数,默认值是空列表。

在 Python 中

默认参数值只能被初始化一次

如果使用可更改对象作为默认参数,那么被更改后的值将一直保留。

那么下面代码的运行结果就好理解了吧(注意我先用两个 print 函数打印 f() 值)。

print( f() )
print( f() )
[1]
[1, 1]

在运行第一行代码时,没有给参数值,则用其默认值 [],然后添加元素 1,结果是 [1],没任何问题。

在运行第二行代码时,也没有给参数值,还是用其默认值,但这个时候默认参数的类型是可更改的列表,它在第一次运行函数 f() 的时候已经变成了 [1],而这个 [1] 就更新为默认值了。再添加元素 1,结果为 [1, 1]。

So far so good,那为什么两个 f() 一起打印出来会得到 [1,1] [1,1] 呢?

print( f(), f() )
[1, 1] [1, 1]

这就需要了解一下 print() 函数的细节了。

print() 函数

在 Python 3 中,print() 是个函数 (function) 而不是语句 (statement)。因此 print() 函数的所有参数要

在调用函数前先被估值

因此

    print( f(), f() ) 

等价于

    x1 = f()

    x2 = f()

    print( x1, x2 )


解释如下:

  • 第一次调用 f() 产生 PyObject 并赋值给 x1 时,x1 指向 PyObject 而且其值为 [1]

  • 第二次调用 f() 赋值给 x2 时,PyObject 里的值更新为 [1, 1],而 x1 和 x2 指向它,因此两个值都更新为 [1, 1]

用一张图可视化下上述过程:

用代码验证一下,注意 id(x1) 和 id(x2) 一样,就是说 x1 和 x2 指向同一个 PyObject。

x1 = f()
x2 = f()
print( id(x1), id(x2) )
print( x1, x2 )
2457681941960 2457681941960
[1, 1] [1, 1]

由于我们在调用 print() 函数前就完成了对 x1 和 x2 的评估,所以它们的值都为 [1, 1]。

如果分开调用 print(f()) 呢?那么结果就是 [1] [1,1] 了。看代码:

print( f() )
print( f() )
[1]
[1, 1]

为什么结果不是 [1, 1] [1, 1] 呢?看下面的等价代码先:

x1 = f()
print( x1 )


x2 = f()
print( x2 )
[1]
[1, 1]

不难发现,我们在评估 x2 之前就把 x1 的值 [1] 打印出来了,在评估 x2 之后 x1 也更新成 [1,1] 但是没打印出来,不过我们可以验证一下是不是这样。

x1 = f()
print( x1 )


x2 = f()
print( x2 )


print( x1 )
[1]
[1, 1]
[1, 1]

到现在你应该明晰所有难点了吧。再回到开始,其实我们就是希望这个函数就是在传入参数的列表上添加一个元素 1,那么怎么操作呢?用 None! 

None

None 和整数、浮点数、布尔一样,是一种数据类型,而且不可更改,它的类型是 NoneType。

type(None)
NoneType

正因为它的不可更改性质,如果你在函数中需要传入一个默认参数值,用 None !

因此上面代码更改成:

def f( x=None ):
    if x is None:
        x = []
    x.append(1)
    return x

核心点是“如果 x 值是 None ,那么重新给 x 赋值一个空列表 []”。

再运行结果正常。

print( f(), f() )
[1] [1]

总结

你看,一个小题目能引出这么多 Python 的细节知识点(如变量是指针、PyObject、(不)可更改对象、函数默认参数、print 函数内部机制、NoneType 变量),而且这些知识点很多人都没有深挖过。我觉得这个题目作为面试题挺合适的,不要求你能完全做对,但在分析的过程可以检查你对基本知识点的理解有多深。

朋友们,这道题你做对了吗?如果做错了现在学到新知识点了吗?五一快乐!

欢迎添加小编微信,一起交流学习:

机器学习试题-试卷.docx 机器学习笔试选择题及答案 1. 在回归模型中,下列哪一项在权衡欠拟合(under-fitting)和过拟合(over-fitting)中影响最大? 立即下载

相关推荐

Python100经典练习题

Python100经典练习题适用于刚入门的新手学习使用,配合相应的Python教程可以更好的巩固学习效果

听说你会玩 Python 系列 2 - 99% 人会做错的题

本文含2693字,5图表截屏建议阅读15分钟本文是听说你会玩 Python 系列的第二篇1 - 六酷技巧2 - 99% 的人会做错的题引言题目:在不运行下面代码(Python ...

weixin_38753422的博客 226

机器学习笔试题(30题).pdfpython面试

机器学习笔试题(30题).pdfpython面试

python计算机二级选择题汇总14(易混淆)

问题描述:python计算机二级选择题汇总(易混淆)问题解答:有些函数比如ls.remove()、sorted( )返回值是新的一个列表还是旧的列表,需要搞清楚。问题描述:4、I/O方式中的程序查询方式是指()。

weixin_43501408的博客 1050

基于opencv自定义网格板的相机标定软件源码

本软件开发版使用的是VS2013和QT5.7, 安装版的需要安装VS核心库(目录里的vcredist_x64.exe, 已安装VS的不需要)。采用强大的模板匹配算法,本程序适用于自定义大范围网格标定(本例程网格使用的是自己画的网格板31*21*10cm),网格点识别度高,矫正速度快,精度高。 使用步骤 第1步: 打开图片,打开标定工具GridCalibTool.exe, 然后选择打开一张待标定的图(CalibFiles文件夹下的500.jpg)。如下图: 第2步: 提取待标定区域(去掉多余部分,只保留网

qq_33138437的博客 1121

ESP32S3 Korvo2V3四通道AEC配置实战:基于AFE的回声消除优化

本文详细介绍了在ESP32S3 Korvo2V3平台上配置四通道AEC(回声消除)的实战经验。通过AFE算法优化和硬件连接调试,实现高质量回声消除,显著提升智能音箱和会议设备的语音交互体验。重点解析了四通道配置、数据格式对齐和参数调优等关键技术要点。

elastic6hunter的博客 935

计算机二级Python错题

计算机二级Python错题

zjjaibc的博客 5569

添加odbc数据源时的一些问题和解决办法

pl/sql

Mr_Syh的博客 9644

春招苦短,我用百道Python面试题备战

对于机器学习算法工程师而言,Python是不可或缺的语言,它的优美与简洁令人无法自拔。那么你了解过Python编程面试题吗?从Python基础到网页爬虫你是否能全方位Hold住?今天,机器之心为读者们推荐一个Github项目。 在这个项目中,作者 kenwoodjw 准备了近 300 道 Python 面试题,同时还包含解决方案与代码。作者主要从 Python 基础、高级语句、网页应用、数据...

weixin_43901866的博客 595

【Diffusion分割】医学图像分割中去噪扩散技术

扩散模型(DPM)在图像生成方面表现出了卓越的性能,其性能往往优于其他生成模型。自其问世以来,强大的噪声-图像去噪管道已被扩展到各种判别任务中,包括图像分割。在医学成像中,图像往往是大型三维扫描图像,由于内存消耗大、迭代采样过程耗时,使用 DPM 对一幅图像进行分割的效率极低。在这项工作中,我们提出了一种(LDSeg),可在潜空间中执行扩散,用于医学影像分割。我们。潜空间条件扩散不仅能确保对多标签对象进行精确的 n-D 图像分割,还能缓解基于 DPM 的传统分割法的主要潜在问题:(。

qq_43583311的博客 1171

操作系统知识点汇总(王道)

操作系统不论是就业还是升学都是核心的一门课程,对于大部分工科更是必修课程。本文章是对《王道操作系统》所有知识点的总结笔记,以供大家学习以及在备考期间复习使用。让我们一起把知识往脑子里旋好吗!!!......

S mile0804的博客 5万+

99% 人会做错的Python题

文章来源:王的机器作者:王圣元本文含2693字,5图表截屏建议阅读15分钟本文是听说你会玩 Python 系列的第二篇1 - 六酷技巧2 - 99% 的人会做错的题引言题目:在...

简说Python的博客 496

HEVC/VVC中R-Lambda码率控制算法原理

文章目录1. 比特分配1.1 GOP级比特分配1.2 帧级比特分配1.3 LCU级比特分配2. 码率控制2.1 λ的计算和更新2.2 参数QP的确定 VVC中码率控制算法沿用了HEVC中经典的R-λ码率控制模型,R-λ由中科大的李斌博士提出(详情参考JCTVC-K0103)。R-λ模型的基础为视频编码中 R(比特 bpp)和 D(失真 MSE)之间的双曲线模型,即 D(R)=CR−KD(R) = ...

Aidoneus_y 6137

一道99% 人会做错的Python题

还有人会选第三个吧,[1] [1, 1]。在运行第二行代码时,也没有给参数值,还是用其默认值,但这个时候默认参数的类型是可更改的列表,它在第一次运行函数 f() 的时候已经变成了 [1],而这个 [1] 就更新为默认值了。第二次调用 f() 赋值给 x2 时,PyObject 里的值更新为 [1, 1],而 x1 和 x2 指向它,因此两个值都更新为 [1, 1]方法一:用 id(X) 函数,对 X 进行某种操作,比较操作前后的 id,如果不一样,则 X 不可更改,如果一样,则 X 可更改。

2401_83642079的博客 993

SCS 43. 利用Scissor算法从单细胞数据中挖掘临床表型关联的细胞亚群

本文详细介绍了Scissor算法在单细胞转录组数据分析中的应用,该算法能够精准挖掘与临床表型关联的细胞亚群。通过建立单细胞RNA测序数据与临床预测模型的直接关联,Scissor避免了传统聚类方法的局限性,为疾病机制研究和个性化医疗提供了新工具。文章还涵盖了数据预处理、模型选择、结果验证等实战技巧。

weixin_28736335的博客 492

【人工智能】在 cc-switch 中配置 AnyRouter 接入 Claude Code 完整指南

本文介绍了在cc-switch工具中配置AnyRouter中转服务以接入Claude Code的详细步骤。主要内容包括:1) 准备API令牌和端点地址;2) 填写基础信息和模型参数;3) 保存配置并重启终端生效;4) 常见问题排查方法。重点强调了API地址格式、模型ID准确性以及配置写入的必要性,帮助用户顺利完成中转服务配置,实现Claude 4.5版本的正常使用。

奶爸的编程之路,也就一周冷个三天 3103

最新一道99% 人会做错的Python题

在运行第二行代码时,也没有给参数值,还是用其默认值,但这个时候默认参数的类型是可更改的列表,它在第一次运行函数 f() 的时候已经变成了 [1],而这个 [1] 就更新为默认值了。第二次调用 f() 赋值给 x2 时,PyObject 里的值更新为 [1, 1],而 x1 和 x2 指向它,因此两个值都更新为 [1, 1]在运行第一行代码时,没有给参数值,则用其默认值 [],然后添加元素 1,结果是 [1],没任何问题。那么结果就是 [1] [1,1] 了。为什么结果不是 [1, 1] [1, 1] 呢?

2401_84584338的博客 886

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

一道99% 人会做错的Python题(1)

在运行第二行代码时,也没有给参数值,还是用其默认值,但这个时候默认参数的类型是可更改的列表,它在第一次运行函数 f() 的时候已经变成了 [1],而这个 [1] 就更新为默认值了。第二次调用 f() 赋值给 x2 时,PyObject 里的值更新为 [1, 1],而 x1 和 x2 指向它,因此两个值都更新为 [1, 1]方法一:用 id(X) 函数,对 X 进行某种操作,比较操作前后的 id,如果不一样,则 X 不可更改,如果一样,则 X 可更改。为什么结果不是 [1, 1] [1, 1] 呢?

2401_83817769的博客 613

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

python默认参数只被解释一次_一道99% 人会做错的Python题

点击上方“早起Python”,关注并“星标”每日接收Python干货! 本文含2693字,5图表截屏建议阅读15分钟引言题目:在不运行下面代码(Python 3 不是 Python 2)的情况下选择答案。def f( x=[] ):x.append(1)return xprint(f(),f())很多人选第二个吧,[1] [1]。理由如下:一开始 x 是空列表,添加一个 1 不就是 [1] ...

weixin_39626211的博客 266

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

上一篇: 哪些“双一流”更得华为偏爱?这所高校人数远超清北华五
下一篇: 10000字Pandas基础+进阶笔记!
机器学习算法那些事
博客等级 码龄9年 1633粉丝 62原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值