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的坑--你知道吗?的更多相关文章

  1. 杂记:Python 两坑

    近日写代码又遇到两个 Python 的坑,觉得值得记录. 递归传参问题 Python 里传参的实现是 assignment,但由于 Python 里都是对象,除了几个基本类型,assignment 基 ...

  2. Python踩坑之旅其一杀不死的Shell子进程

    目录 1.1 踩坑案例 1.2 填坑解法 1.3 坑位分析 1.4 坑后扩展 1.4.1 扩展知识 1.4.1 技术关键字 1.5 填坑总结 1.1 踩坑案例 踩坑的程序是个常驻的Agent类管理进程 ...

  3. Python 踩坑之旅进程篇其四一次性踩透 uid euid suid gid egid sgid的坑坑洼洼

    目录 1.1 踩坑案例 1.2 填坑解法 1.3 坑位分析 1.4 技术关键字 1.5 坑后思考 下期坑位预告 代码示例支持 平台: Centos 6.3 Python: 2.7.14 代码示例: 菜 ...

  4. [代码修订版] Python 踩坑之旅进程篇其五打不开的文件

    目录 1.1 踩坑案例 1.2 填坑和分析 1.2.1 从程序优化入手 1.2.2 从资源软硬限入手 1.4.1 技术关键字 下期坑位预告 代码示例支持 平台: Centos 6.3 Python: ...

  5. Python 踩坑之旅文件系统篇其一文件夹也是个文件

    目录 1.1 案例 1.2 分析 1.3 扩展 1.4 技术关键字 下期预告 代码示例支持 平台: Mac OS Python: 2.7.10 代码示例: - wx: 菜单 - Python踩坑指南代 ...

  6. python踩坑系列之导入包时下划红线及报错“No module named”问题

    python踩坑系列之导入包时下划红线及报错“No module named”问题 使用pycharm编写Python时,自己写了一个包(commontool),在同级另一个路径下(fileshand ...

  7. [Python]Python入坑小项目推荐- Flask example minitwit

    知乎上看到的Python练手项目推荐,链接见:https://www.zhihu.com/question/29372574,不知道是我自己懒得看还是理解力不行,这些项目真的是...太大了呀~~~~ ...

  8. python跳坑---生成器

    贵有恒,何必三更眠五更起,最无益,只怕一日曝十日寒. 好多东西要写下来一是方便自己,二可以分享给大家,我却一拖再拖. 工作的时候看别人代码中间结果,跳了个坑,关于python generator类型: ...

  9. Python踩坑:类与类对象类型参数传递与使用

    前言 对初学者来说,Python确实简单好用,毕竟动态类型语言,不用定义就可以拿来用,类型之间随意转换简直不要太方便,因此Python用来写写小脚本,爬虫程序什么的,没什么问题. 不过,一旦用来开发稍 ...

随机推荐

  1. iOS开发判断手机号及其运营商

    根据三大运营商出现的号段(号段来自百度百科) 判断是否是手机号 + (BOOL)isMobile:(NSString *)str { NSString *MOBILE = @"^1(3[0- ...

  2. 微软Azure IoT驱动数字化变革线上分享会(6月4号)

    微软Azure IoT驱动数字化变革线上分享会(6月4号)   微软作为全球范围内IoT领域的领军者,以微软智能云Azure为基础和核心,推动包括物联网.机器学习.微服务.人工智能等在内的新技术的发展 ...

  3. 解决pip._vendor.urllib3.exceptions.ReadTimeoutError: HTTPSConnectionPool(host='files.pythonhosted.org', port=443): Read timed out.问题

    国内的其他镜像源清华大学 https://pypi.tuna.tsinghua.edu.cn/simple/阿里云 http://mirrors.aliyun.com/pypi/simple/中国科技 ...

  4. 如何短时间内快速通过Java面试

    当然是刷题啊 1-10期[10期]Redis 面试常见问答[09期]说说hashCode() 和 equals() 之间的关系?[08期]说说Object类下面有几种方法呢?[07期]Redis中是如 ...

  5. 50个SQL语句(MySQL版) 问题十三

    --------------------------表结构-------------------------- student(StuId,StuName,StuAge,StuSex) 学生表 tea ...

  6. 分享按钮(QQ,微信,微博等)移入动画效果

    ps:最近写的很多博客都是在以前在项目里写过的,之所以现在写出来,最大的目的就是希望自己以后用到的时候比较容易找,而且现在再写一遍,有助于加深印象! 很简单的效果,说先实现方式: 1.图标来自 阿里巴 ...

  7. Java实现 LeetCode 812 最大三角形面积 (暴力)

    812. 最大三角形面积 给定包含多个点的集合,从其中取三个点组成三角形,返回能组成的最大三角形的面积. 示例: 输入: points = [[0,0],[0,1],[1,0],[0,2],[2,0] ...

  8. Java实现 LeetCode 810 黑板异或游戏 (分析)

    810. 黑板异或游戏 一个黑板上写着一个非负整数数组 nums[i] .小红和小明轮流从黑板上擦掉一个数字,小红先手.如果擦除一个数字后,剩余的所有数字按位异或运算得出的结果等于 0 的话,当前玩家 ...

  9. Java实现 LeetCode 765 情侣牵手(并查集 || 暴力)

    765. 情侣牵手 N 对情侣坐在连续排列的 2N 个座位上,想要牵到对方的手. 计算最少交换座位的次数,以便每对情侣可以并肩坐在一起. 一次交换可选择任意两人,让他们站起来交换座位. 人和座位用 0 ...

  10. Java实现 LeetCode 430 扁平化多级双向链表

    430. 扁平化多级双向链表 您将获得一个双向链表,除了下一个和前一个指针之外,它还有一个子指针,可能指向单独的双向链表.这些子列表可能有一个或多个自己的子项,依此类推,生成多级数据结构,如下面的示例 ...