目錄
- 函數的結構和參數
- 函數的取值順序 加載順序 作用域
- 函數名的應用
- 構造函數和析構函數
- 重寫和重載的區別?
- 什么是接口?
- lambda表達式格式以及應用場景?
- *arg和**kwarg作用
- Python垃圾回收機制?
- 列舉常見的內置函數
- 列表推導式與生成器推導式
- def func(a,b=[]) 這種寫法有什什么坑?
- 如何在函數中設置一個全局變量
- 簡述 生成器、迭代器、可迭代對象 以及應用場景?
- 裝飾器
- 用Python實現一個二分查找的函數。
- 談談你對閉包的理解?
- 是否使用過functools中的函數?其作用是什么?
- 異常處理寫法以及如何主動跑出異常(應用場景)
- yield和yield from關鍵字
函數的結構和參數
定義一個函數
def len_num(a):
return len(a)
b=len_num([123,1,2])#函數名加括號就調用了
print(b)
# 結構:
#def 關鍵字,定義函數。
#len_num 函數名:與變量設置相同,具有可描述性。
#函數體 :縮進。函數中盡量不要出現print
# return后面是返回值(len(a)) 在函數中遇到return直接結束函數。
# return 將數據返回給函數的執行者,調用者 len_num()。
# return 返回單個元素 是返回原有數據類型的形式返回
# return 返回多個元素 是以元組的形式返回給函數的執行者。
形參的最終順序為:
**位置參數,
*args,
默認參數,
僅限關鍵字參數,
**kwargs
實參角度:
1. 位置參數 按照順序,一一對應
2. 關鍵字參數, 一一對應
3. 混合參數:位置參數一定要在關鍵字參數的前面。
1.萬能參數: *args, 約定俗稱:args,
函數定義時,*代表聚合。 他將所有的位置參數聚合成一個元組,賦值給了 args。
2.**kwargs 僅限關鍵字參數
1.函數的定義時: ** 將所有的關鍵字參數聚合到一個字典中,將這個字典賦值給了kwargs.
1.*在函數的調用時,*代表打散。
**{'name': '太白'}打散為name='太白'
*[1,2,3]打散為1,2,3
2.函數外:處理剩余元素
a,b,*c = [1,2,3,4,5]
函數的取值順序 加載順序 作用域
# 內置名稱空間:python源碼給你提供的一些內置的函數,print input
python分為三個空間:
1.內置名稱空間(builtins.py)
2.全局名稱空間(當前py文件)
3.局部名稱空間(函數,函數執行時才開辟)
加載順序:
內置名稱空間 ---> 全局名稱空間 ----> 局部名稱空間(函數執行時)
取值順序(就近原則) 單向不可逆
從局部找時 局部名稱空間 ---> 全局名稱空間 ---> 內置名稱名稱空間
兩個作用域:
1.全局作用域 :內置名稱空間 全局名稱空間
2.局部作用域:局部名稱空間(函數等)
注意
1.局部作用域可以引用全局作用域的變量
2.局部作用域不能改變全局變量。 可以使用,不能改變
3.注意 python中不可以先引用 后定義
函數名的應用
1.函數名是一個特殊的變量。
2.函數名指向的是函數的內存地址,加上()就執行這個函數。
3. 函數名可以作為容器類類型的元素。
4. 函數名可以作為函數的實參。
5. 函數名可以作為函數的返回值。
構造函數和析構函數
構造函數,用於創建對象的函數。
析構函數,用於銷毀對象的函數。
class Foo(object):
def __new__(self,*args,**kwargs): # 構造函數
pass
def __del__(self,*args,**kwargs): # 析構函數
pass
obj = Foo()
del obj
重寫和重載的區別?
class Foo(object):
def f1(self,int a1):
return 123
def f1(self,string a1):
pass
重載,函數名相同而參數類型/個數/返回值不同。
class Foo(object):
def f1(self):
print(123)
class Bar(Foo):
def f1(self):
print(666)
重寫,在子類中對父類中的方法進行重寫。
什么是接口?
定義一個接口對繼承類進行約束,接口里有什么方法,繼承類就必須有什么方法,接口中不能任何功能代碼
強制約束
抽象類,可以說是類和接口的混合體,既可以定義常規方法,也可以約束子類的方法(抽象方法)
lambda表達式格式以及應用場景?
匿名函數:為了解決那些功能很簡單的需求而設計的一句話函數 與內置函數結合
函數名 = lambda 參數 :返回值
1.參數可以有多個,用逗號隔開
2.匿名函數不管邏輯多復雜,只能寫一行,且邏輯執行結束后的內容就是返回值
3.返回值和正常的函數一樣可以是任意數據類型
lambda 表達式
temp = lambda x,y:x+y
print(temp(4,10)) # 14
可替代:
def foo(x,y):
return x+y
print(foo(4,10)) # 14
和內置函數結合
1.min max()可以加功能
2.reversed() 將一個序列翻轉
3.sorted排序函數 可以加key
4.map對元素進行映射
5.filter篩選過濾 返回迭代器
*arg和**kwarg作用
*args代表位置參數,它會接收任意多個參數並把這些參數作為元祖傳遞給函數。
**kwargs代表的關鍵字參數,返回的是字典,位置參數一定要放在關鍵字前面
Python垃圾回收機制?
1.引用計數
引用計數法有很明顯的優點:
對象有確定的生命周期
易於實現
原始的引用計數法也有明顯的缺點:
維護引用計數消耗資源,維護引用計數的次數和引用賦值成正比,而不像mark and sweep等基本與回收的內存數量有關。
無法解決循環引用的問題。A和B相互引用而再沒有外部引用A與B中的任何一個,它們的引用計數都為1,但顯然應該被回收。
為了解決這兩個致命弱點,Python又引入了以下兩種GC機制。
2.標記清除
標記-清除”法是為了解決循環引用問題。可以包含其他對象引用的容器對象
3.分代回收
Python默認定義了三代對象集合,索引數越大,對象存活時間越長
列舉常見的內置函數
1.abs() print(abs(a)) #輸出3
返回數字的絕對值
2.all() 此函數用於判斷給定的可迭代參數 iterable 中的所有元素是否都不為 0、都不為False 或者iterable都 為空,如果是返回 True,否則返回 False。
3.any() 函數用於判斷給定的可迭代參數 iterable 是否全部為空對象,如果都為空、都為0、或者都為false,則返回 False,如果不都為空、不都為0、不都為false,則返回 True。
3.print()
print函數是你學Python接觸到的第一個函數,它將對象輸出到標准輸出流,可將任意多個對象打印出來
4.isinstance()
可以用 isinstance 函數判斷某個對象是否屬於某個類的實例,函數的定義
range()
range函數是個工廠方法,用於構造一個從[start, stop) (不包含stop)之間的連續的不可變的整數序列對象,這個序列功能上和列表非常類似,函數定義:
enumerate()
用於枚舉可迭代對象,同時還可以得到每次元素的下表索引值,函數定義:
len()
zip()
sep 設定分隔符。
print(1, 2, 3, sep='|')
end去除默認換行
print(1, 2, end=' ')
abs() 獲取絕對值
print(abs(-10))
sum() 數字相加求和
# sum() 數字相加求和 會for循環里面元素 必須里面都是由int組成 注意列表 sum(iterable,)
print(sum([1, 2, 3, 4], 100))
min max()可以加功能
# min 可以加功能 key 與匿名函數結合
# min 可以加功能
# print(min([22, 11, 45, 2]))
# l1 = [(73, 'alex'), (35, '武大'), (18, '太白')]
# print(min(l1,key=lambda x: x[0]))
# print(min(l1,key=lambda x: x[0])[0])
# 第一步 循環遍歷l1 將里面的元素以形參的方式傳給匿名函數得到返回值
# 第2步 利用內置函數比較返回值 得到想要的結果,在將傳進去的元素返回
reversed() 將一個序列翻轉
# reversed() 將一個序列翻轉, 返回翻轉序列的迭代器 reversed 示例:
# l = reversed('123') # l 獲取到的是一個生成器 注意字符串轉list會分隔
# print(list(l))
sorted排序函數 可以加key
# lst = [{'id': 1, 'name': 'alex', 'age': 18},
# {'id': 2, 'name': 'wusir', 'age': 17},
# {'id': 3, 'name': 'taibai', 'age': 16}, ]
# # 按照年齡對學生信息進行排序
# print(sorted(lst, key=lambda e: e['age']))
l = ['班級24','班級15','班級3','班級5','班級25']#,按照數字的順序從大到小排序,不改變原列表,請以最少代碼量實現。(3分)
print(sorted(l, key=lambda e: int(e[2:]),reverse=False))
map對元素進行映射
# map(function,iterable) 可以對可迭代對象中的每一個元素進行映射,分別取執行function
# 計算列表中每個元素的平方,返回新列表
# lst = [1,2,3,4,5]
# def func(s):
# return s*s
# mp = map(func,lst)
# print(mp)#對象
# print(list(mp))
# # 改寫成lambda
# print(list(map(lambda s:s*s,lst)))
zip() 拉鏈方法
# zip() 拉鏈方法。函數用於將可迭代的對象作為參數,將對象中對應的元素打包成一個個元組,
# 然后返回由這些元祖組成的內容,如果各個迭代器的元素個數不一致,則按照長度最短的返回
# lst1 = [1,2,3]
# lst2 = ['a','b','c','d']
# lst3 = (11,12,13,14,15)
# for i in zip(lst1,lst2,lst3):
# print(i)
filter篩選過濾 返回迭代器
filter篩選過濾 返回迭代器
ls = filter(lambda e:e['age'] > 16,lst)
列表推導式與生成器推導式
print([ i % 2 for i in range(10) ]) # [0, 1, 0, 1, 0, 1, 0, 1, 0, 1]
print([ i for i in range(10) ]) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print([ 10 % 2]) # [0]
# %是個運算符。
print(( i % 2 for i in range(10) ))
# <generator object <genexpr> at 0x00000000020CEEB8> 生成器
# 在Python中,有一種自定義迭代器的方式,稱為生成器(Generator)。
# 定義生成器的兩種方式:
# 1.創建一個generator,只要把一個列表生成式的[]改成(),就創建了一個generator:
# generator保存的是算法,每次調用next(),就計算出下一個元素的值,直到計算到最后一個元素,
沒有更多的元素時,拋出StopIteration的錯誤。
# 2.定義generator的另一種方法。如果一個函數定義中包含yield關鍵字,那么這個函數就不再是一個普通函數,
而是一個generator
def func(a,b=[]) 這種寫法有什什么坑?
def func(a,b = []):
b.append(1)
print(a,b)
func(a=2)
func(2)
func(2)
'''
2 [1]
2 [1, 1]
2 [1, 1, 1]
函數的默認參數是一個list 當第一次執行的時候實例化了一個list
第二次執行還是用第一次執行的時候實例化的地址存儲
所以三次執行的結果就是 [1, 1, 1] 想每次執行只輸出[1] ,默認參數應該設置為None
如何在函數中設置一個全局變量
x = 2
def func():
global x
x = 1
return x
func()
print(x) # 1
簡述 生成器、迭代器、可迭代對象 以及應用場景?
可迭代對象
1.可以進行循環更新的一個實實在在值。
2.如何判斷一個對象是否是可迭代對象: 利用內置函數:dir()可以查看對象內部方法
3.有__iter__方法的對象,都是可迭代對象。
4.str,list set tup 逗是可迭代對象
print('__iter__' in dir(str))#True
ps dir()函數可以獲取對象所有方法
迭代器
1.可更新迭代的工具
2.在python中,內部含有'__iter__'方法並且含有'__next__'方法的對象就是迭代器。
3.迭代器可以迭代取值。利用next()進行取值(節省內存)或者轉為list 元祖等等取值
4.一個next()取一個值 且會記錄位置 迭代器一條路走到底,不走回頭路。
5.取完了再next()會報錯(StopIteration) 我們可以用try處理 萬能異常(Exception)
可迭代對象轉化成迭代器
利用內置函數iter()
l1=[1,2,3]
obj = iter(l1)
object.__iter__()
1.可迭代對象是一個操作方法比較多,比較直觀,存儲數據相對少(幾百萬個對象,8G內存是可以承受的)的一個數據集。
2.當你側重於對於數據可以靈活處理,並且內存空間足夠,將數據集設置為可迭代對象是明確的選擇。
3.是一個非常節省內存,可以記錄取值位置,可以直接通過循環+next方法取值,但是不直觀,操作方法比較單一的數據集。
4.當你的數據量過大,大到足以撐爆你的內存或者你以節省內存為首選因素時,將數據集設置為迭代器是一個不錯的選擇。
生成器
1.將return換為yield就是生成器函數
2.只要函數中出現了yield那么他就不是函數,它是生成器函數。
3.不結束函數,對應着給 next 返回值(多個值通過元組的形式返回)。 會記錄位置
4.生成器是一個返回迭代器的函數,只能用於迭代操作,更簡單點理解生成器就是一個迭代器。
裝飾器
裝飾器:
能夠在不修改原函數代碼的基礎上,在執行前后進行定制操作,閉包函數的一種應用 不修改被修飾函數的代碼
場景:
- flask路由系統
- flask before_request
- csrf
- django內置認證
- django緩存
# 手寫裝飾器;
import functools
def wrapper(func):
@functools.wraps(func) #不改變原函數屬性
def inner(*args, **kwargs):
#執行函數前
return func(*args, **kwargs)
#執行函數后
return inner
1. 執行wapper函數,並將被裝飾的函數當做參數。 wapper(index)
2. 將第一步的返回值,重新賦值給 新index = wapper(老index)
@wrapper #index=wrapper(index)
def index(x):
return x+100
用Python實現一個二分查找的函數。
二分查找算法:簡單的說,就是將一個列表先排序好,比如按照從小到大的順序排列好,當給定一個數據,比如3,查找3在列表中的位置時,可以先找到列表中間的數li[middle]和3進行比較,當它比3小時,那么3一定是在列表的右邊,反之,則3在列表的左邊,比如它比3小,則下次就可以只比較[middle+1, end]的數,繼續使用二分法,將它一分為二,直到找到3這個數返回或者列表全部遍歷完成(3不在列表中)
優點:效率高,時間復雜度為O(logN);
缺點:數據要是有序的,順序存儲。
li = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
def search(someone, li):
l = -1
h = len(li)
while l + 1 != h:
m = int((l + h) / 2)
if li[m] < someone:
l = m
else:
h = m
p = h
if p >= len(li) or li[p] != someone:
print("元素不存在")
else:
str = "元素索引為%d" % p
print(str)
search(3, li) # 元素索引為2
談談你對閉包的理解?
ef foo():
m=3
n=5
def bar():
a=4
return m+n+a
return bar
>>>bar = foo()
>>>bar()
種內部函數可以使用外部函數變量的行為,就叫閉包。或者有自由變量
是否使用過functools中的函數?其作用是什么?
用於修復裝飾器 flask源碼里面有用到
import functools
def deco(func):
@functools.wraps(func) # 加在最內層函數正上方
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
@deco
def index():
'''哈哈哈哈'''
x = 10
print('from index')
print(index.__name__)
print(index.__doc__)
# 加@functools.wraps
# index
# 哈哈哈哈
# 不加@functools.wraps
# wrapper
# None
異常處理寫法以及如何主動跑出異常(應用場景)
# 觸發異常
def temp_convert(var):
try:
return int(var)
except ValueError as Argument:
print ("參數沒有包含數字%s"%Argument)
# 調用函數
temp_convert("xyz")
# 以10為基數的int()的無效文字:“xyz”
----------------------------------------------------------------------------
# raise語法
#raise [Exception [, args [, traceback]]]
# 語句中 Exception 是異常的類型,args 是自已提供的異常參數。
class Networkerror(RuntimeError):
def __init__(self, arg):
self.args = arg
try:
raise Networkerror("Bad hostname")
except Networkerror as e:
print(e.args)
yield和yield from關鍵字
yield 返回一個
yield from 返回一堆
1.yield from 將一個可迭代對象的每一個元素返回給next
2.yield from 節省代碼,提升效率(代替了for循環)