python是个坑_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()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值