python的坑--你知道吗?
python的坑--你知道吗?
1.列表的坑
坑的地方是:因为列表用pop之后,后面的索引都会自动减一
# 列表的坑之一
list1 = ['python','java','php','c','c++','c#','ruby']
# 将索引为奇数的元素删除 ['java','c','c#']
list2 = []
for item in list1:
if list1.index(item) % 2 != 1:
list1.pop(list1.index(item))
print(list1) # ['java', 'php', 'c++', 'c#']
# 这是因为列表用pop之后,后面的索引都会自动减一
# 正确的操作如下:
# 切片
list1 = ['python','java','php','c','c++','c#','ruby']
list2 = list1[1::2]
print(list2) #['java','c','c#']
# 赋值到其他的空列表
list1 = ['python','java','php','c','c++','c#','ruby']
list2 = []
for i in list1:
if list1.index(i)%2==0:
list2.append(i)
print(list2) # ['java','c','c#']
# 倒序删除
list1 = ['python','java','php','c','c++','c#','ruby']
for i in range(len(list1)-1,-1,-1):
if i % 2 == 0:
del li[i]
print(list1) # ['java','c','c#']
2.默认参数的陷阱
# def func(name, sex='男'):
# print(name)
# print(sex)
#
#
# func('zhouqian')
# 输出的结果为:
# zhouqian
# 男
上面的代码是运行正常的,仿佛默认参数并没有什么坑。但是我们用下面的例子就知道了。默认参数的陷阱只针对默认参数是可变的数据类型。
# def func(name, alist=[]):
# alist.append(name)
# return alist
#
#
# ret = func('zhouqian')
# print(ret, id(ret)) # ['zhouqian'] 2135732081224
# ret2 = func('太白金星')
# print(ret2, id(ret2))# 按理说是['太白金星'],但是实际上输出['zhouqian', '太白金星'] 2135732081224
# print(func('zhouqian'))
# ['zhouqian'] 2135732081224
# ['zhouqian', '太白金星'] 2135732081224
通过id可知,默认参数是列表的话在内存中是共用同一个地址。只要调用了这个函数,那么就会在同一个地址后面操作这个元素。如果你的默认参数是可变的数据类型,那么无论你调用多少次函数,这个默认参数指向的都是同一个地址。如果你给可变的数据类型传一个值,那么就不会用原来默认的,就用这个传值的。
下面我们用两个python的面试题来讲解默认参数是可变数据类型的坑。
面试题1:
def func(a, alist=[]):
alist.append(a)
return alist
print(func(10, )) # [10]
print(func(20, [])) # [20]
print(func(100, )) # [10,100]
# 上面的类似于下面的代码:
# l1 = []
# l1.append(10)
# print(l1) # [10]
# l2 = []
# l2.append(20)
# print(l2) # [20]
# l1.append(100)
# print(l1) # [10,100]
面试题2:
def func(a, alist=[]):
alist.append(a)
return alist
ret1 = func(10, ) # 这里的值是alist(id 1564531154864)
ret2 = func(20, []) # 这里的值是alist (id 4648456151995)
ret3 = func(100, ) # 这里的值是alist (id 1564531154864)
print(ret1) # [10, 100]
print(ret2) # [20]
print(ret3) # [10, 100]
# 上面的类似于下面的代码:
# l1 = []
# l1.append(10)
# l2 = []
# l2.append(20)
# l1.append(100)
# ret1 = l1
# ret2 = l2
# ret3 = l1
# print(ret1) # [10,100]
# print(ret2) # [20]
# print(ret3) # [10,100]
3.局部作用域的陷阱
# count = 1
# def func():
# count += 1
# print(count)
# # UnboundLocalError: local variable 'count' referenced before assignment
# func()
# 解释:2.局部作用域不能改变全局作用域的变量。当python解释器读取到局部作用域时,发现你对一个变量进行了修改的操作,解释器会认为你在局部作用域已经定义过这个局部变量,他就从局部找这个局部变量,报错了。
# 局部和全局作用域的详细解析
# 1.局部作用域可以获得到全局作用域中使用变量,重新创建变量,操作变量的赋值,可以用来对变量进行操作,改变变量的值。
# 2.局部作用域不能改变全局作用域的变量。当python解释器读取到局部作用域时,发现你对一个变量进行了修改的操作,解释器会认为你在局部作用域已经定义过这个局部变量,他就从局部找这个局部变量,报错了。
# 3.但是全局作用域不可以获得局部作用域,不能操作局部作用域的变量,不能操作局部作用域的变量值。
# count = 1
#
# 在函数中,如果你定义了一个变量,但是在定义这个变量之前对其引用了,那么解释器认为语法问题。
# 你应该使用之前的先定义后引用。
# def func():
# # 先引用后定义。报错
# print(count) # UnboundLocalError: local variable 'count' referenced before assignment
# count = 3
#
# func()
# 解释:在函数中,如果你定义了一个变量,但是在定义这个变量之前对其引用了,那么解释器认为语法问题,你应该使用之前的先定义后引用。
# 以下两个代码是不会报错的。可以正常运行输出结果。
# count = 1
#
#
# def func():
# print(count) # 1
# # count = 3 # 将count=3删除/注释掉就不会报错
#
#
# func()
# count = 1
#
#
# def func():
# count = 3
# print(count) # 3
#
#
# func()
4.补充知识点:global和nonlocal
# global和nonlocal
# 1.在局部作用域声明一个全局变量
# name = 'alex'
# def func():
# name = 'AndreasZhou'
# print(name)
# func()
# print(name)
# 输出的结果为:
# AndreasZhou
# alex
# 解析:全局变量是从全局名称空间和内置名称空间中取值。局部变量是从局部名称作用域、全局名称作用域和内置名称作用域取值。
# 局部名称作用域---》全局名称作用域---》内置名称作用域取值,单向不可逆。
# def func():
# name = 'AndreasZhou'
# print(name)
# func() # AndreasZhou
# print(name) # NameError: name 'name' is not defined
# 输出的结果为:
# AndreasZhou
# NameError: name 'name' is not defined
# name = 'zhouqian'
# def func():
# global name
# name = 'AndreasZhou'
# print(name)
# func()
# print(name)
# 输出的结果为:
# AndreasZhou
# AndreasZhou
# def func():
# global name
# name = '太白金星'
# print(name)
# print(name)
# func()
# 输出的结果为:
# NameError: name 'name' is not defined
# # 2.修改一个全局变量
# count = 1
# def func():
# # print(count) SyntaxError: name 'count' is used prior to global declaration
# global count
# count += 1
# print(count) # 1
# func()
#
# print(count) # 2
# nonlocal
# 1.不能够操作全局变量
# count = 1
# def func():
# nonlocal count # SyntaxError: no binding for nonlocal 'count' found
# count += 1
# func()
# 2.局部作用域:内层函数对外层函数的局部变量进行修改
# def wrapper():
# count = 1
# def inner():
# count+=1 # UnboundLocalError: local variable 'count' referenced before assignment
# inner()
# wrapper()
def wrapper():
count = 1
def inner():
nonlocal count
count += 1
print(count) # 1
inner()
print(count) # 2
wrapper()
python的坑--你知道吗?的更多相关文章
- 杂记:Python 两坑
近日写代码又遇到两个 Python 的坑,觉得值得记录. 递归传参问题 Python 里传参的实现是 assignment,但由于 Python 里都是对象,除了几个基本类型,assignment 基 ...
- Python踩坑之旅其一杀不死的Shell子进程
目录 1.1 踩坑案例 1.2 填坑解法 1.3 坑位分析 1.4 坑后扩展 1.4.1 扩展知识 1.4.1 技术关键字 1.5 填坑总结 1.1 踩坑案例 踩坑的程序是个常驻的Agent类管理进程 ...
- Python 踩坑之旅进程篇其四一次性踩透 uid euid suid gid egid sgid的坑坑洼洼
目录 1.1 踩坑案例 1.2 填坑解法 1.3 坑位分析 1.4 技术关键字 1.5 坑后思考 下期坑位预告 代码示例支持 平台: Centos 6.3 Python: 2.7.14 代码示例: 菜 ...
- [代码修订版] Python 踩坑之旅进程篇其五打不开的文件
目录 1.1 踩坑案例 1.2 填坑和分析 1.2.1 从程序优化入手 1.2.2 从资源软硬限入手 1.4.1 技术关键字 下期坑位预告 代码示例支持 平台: Centos 6.3 Python: ...
- Python 踩坑之旅文件系统篇其一文件夹也是个文件
目录 1.1 案例 1.2 分析 1.3 扩展 1.4 技术关键字 下期预告 代码示例支持 平台: Mac OS Python: 2.7.10 代码示例: - wx: 菜单 - Python踩坑指南代 ...
- python踩坑系列之导入包时下划红线及报错“No module named”问题
python踩坑系列之导入包时下划红线及报错“No module named”问题 使用pycharm编写Python时,自己写了一个包(commontool),在同级另一个路径下(fileshand ...
- [Python]Python入坑小项目推荐- Flask example minitwit
知乎上看到的Python练手项目推荐,链接见:https://www.zhihu.com/question/29372574,不知道是我自己懒得看还是理解力不行,这些项目真的是...太大了呀~~~~ ...
- python跳坑---生成器
贵有恒,何必三更眠五更起,最无益,只怕一日曝十日寒. 好多东西要写下来一是方便自己,二可以分享给大家,我却一拖再拖. 工作的时候看别人代码中间结果,跳了个坑,关于python generator类型: ...
- Python踩坑:类与类对象类型参数传递与使用
前言 对初学者来说,Python确实简单好用,毕竟动态类型语言,不用定义就可以拿来用,类型之间随意转换简直不要太方便,因此Python用来写写小脚本,爬虫程序什么的,没什么问题. 不过,一旦用来开发稍 ...
随机推荐
- PLC可编程控制器的结构和工作原理
PLC的可编程控制器由的功能结构由cpu中央处理器,存储器和输入输出借口三部分组成 CPU Cpu的功能是完成plc所有的的控制和监视, Cpu中央处理去由控制器,寄存器,运算器.通过数据总线,地址总 ...
- Linux的运行等级与目标
在老的 Linux 发行版本中,系统运行分成不同的运行级别(run level),不同的级别所启动的服务搭配有所不同.较新的 Linux 发行版本,比如 CentOS 7+,已经将运行级别替换成另一个 ...
- sql语句中的删除操作
drop: drop table tb; 删除内容和定义,释放空间.简单来说就是把整个表去掉.以后不能再新增数据,除非新增一个表. truncate: truncate table tb; 删除内容. ...
- group by和having注意事项
执行和编写顺序:join->where->group by->having 其中where与having的区别: where用于在group by分组之前过滤掉某些行, group ...
- rpm解决Jenkins安装报错
安装Jenkins出现的问题rpm安装新建路径存放地址mkdir /home/jenkins 下载地址https://pkg.jenkins.io/redhat-stable/jenkins-2.20 ...
- Chisel3 - util - Mux
https://mp.weixin.qq.com/s/TK1mHqvDpG9fbLJyNxJp-Q Mux相关电路生成器. 参考链接: https://github.com/freechips ...
- Flutter 动画鼻祖之CustomPaint
老孟导读:CustomPaint可以称之为动画鼻祖,它可以实现任何酷炫的动画和效果.CustomPaint本身没有动画属性,仅仅是绘制属性,一般情况下,CustomPaint会和动画控制配合使用,达到 ...
- SpringBoot返回html页面
一般Controller返回数据或页面,今天谈一下返回页面的场景. 一.不使用template 1. controller中定义对应的访问路由及返回的页面(使用Controller,不要使用RestC ...
- Nginx 笔记(三)nginx 配置实例 - 反向代理、负载均衡、动静分离
个人博客网:https://wushaopei.github.io/ (你想要这里多有) 一.反向代理 反向代理准备工作: (1)在 liunx 系统安装 tomcat,使用默认端口 8080 ...
- Java实现 LeetCode 667 优美的排列 II(暴力)
667. 优美的排列 II 给定两个整数 n 和 k,你需要实现一个数组,这个数组包含从 1 到 n 的 n 个不同整数,同时满足以下条件: ① 如果这个数组是 [a1, a2, a3, - , an ...