python的坑--你知道嗎?

python的坑--你知道嗎?

1.列表的坑

坑的地方是:由於列表用pop以後,後面的索引都會自動減一php

# 列表的坑之一
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
# 男

上面的代碼是運行正常的,彷彿默認參數並無什麼坑。可是咱們用下面的例子就知道了。默認參數的陷阱只針對默認參數是可變的數據類型java

# 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

下面咱們用兩個python的面試題來說解默認參數是可變數據類型的坑。c++

面試題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:c#

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()
相關文章
相關標籤/搜索