一個菜雞的掙扎
就總結(jié)下
and 如果有大佬不小心看到了發(fā)現(xiàn)了錯誤,就歡迎指正
6.1懶惰是一種美德
通過創(chuàng)建函數(shù)調(diào)用之可以減少代碼量
6.2 抽象和結(jié)構(gòu)
抽象是程序能夠被人理解的關(guān)鍵所在(無論對編寫程序還是閱讀來說,這都至關(guān)重要)
函數(shù)封裝了人不需要關(guān)心的實現(xiàn)細(xì)節(jié),從而更容易被使用和理解
6.3 自定義函數(shù)
6.3.1 給函數(shù)編寫文檔
在def后面添加字符串,相當(dāng)于給整個函數(shù)添加注釋,以確保被人理解
_doc _是函數(shù)的一個屬性,可用它來訪問函數(shù)的文檔字符串
我自己的練習(xí):
def lalala(x):
"""就瞎寫的"""
print(x)
print(lalala.__doc__)
結(jié)果:

這里書上說用單引號,但是pycharm中會有提示,要讓用連續(xù)的三個雙引號
help()函數(shù)可訪問有關(guān)函數(shù)的信息,其中會包含函數(shù)的文檔字符串
In [1]: help(round)
Help on built-in function round in module builtins:
round(...)
round(number[, ndigits]) -> number
Round a number to a given precision in decimal digits (default 0 digits).
This returns an int when called with one argument, otherwise the
same type as the number. ndigits may be negative.
6.3.2 其實并不是函數(shù)的函數(shù)
就是有的函數(shù)沒有return 或者return后面沒有指定值,這么做將會返回None
6.4 參數(shù)魔法
6.4.1 值從哪里來 略
6.4.2 我能修改參數(shù)嗎
可變參數(shù)可以,不可變參數(shù)不可以
如果不想讓可變參數(shù)的值在調(diào)用函數(shù)后發(fā)生變化,可以向函數(shù)中傳遞切片或者用copy()傳遞副本(如果有copy()的話)
自己的練習(xí):
def change(n):
n[0] = 'a'
x = [1, 2, 3]
change(x)
print(x)
結(jié)果;

change(x[:])
print(x)
結(jié)果:

change(x.copy())
print(x)
結(jié)果:

如果想讓不可變參數(shù)發(fā)生變化,可以使之重新指向返回的值,或者干脆把它放在列表中
6.4.3 關(guān)鍵字參數(shù)和默認(rèn)值
這個部分之前看過了,少總結(jié)下
像這種用名稱指定的參數(shù)稱為關(guān)鍵字參數(shù),主要優(yōu)點是有助于澄清各個參數(shù)的作用。
關(guān)鍵字參數(shù)在傳入時的順序與定義時的不一樣也沒關(guān)系,反正有關(guān)鍵字程序不會認(rèn)錯
可以為關(guān)鍵字參數(shù)設(shè)置默認(rèn)值,如果在調(diào)用該參數(shù)沒有傳入,就使用默認(rèn)值
位置參數(shù)不可定義在關(guān)鍵字參數(shù)后面!
關(guān)鍵字好像只能是字符串,我的試驗:
def test(*a, **b):
print(a, b)
b = {1: 'a', 2:'b'}
test(1, **b)
然后會報錯:

6.4.4 收集參數(shù)
帶星號的參數(shù)會收集多余的值,放在元組中
一個星號不會收集關(guān)鍵字參數(shù)!若想收集,可帶兩個星號,這樣會得到字典而非數(shù)組
位置參數(shù)最好不要放在星號參數(shù)后面,雖然指定名稱也可以調(diào)用
6.4.5 分配參數(shù)
類似于序列解包,可大致理解為與收集參數(shù)相反的操作
6.5 作用域
- vars()函數(shù) ,返回作用域中看不見的字典,最好不要使用它修改字典中的值,因為其結(jié)果是不確定的
- 在函數(shù)中讀取全局變量而非訪問它,一般不會造成任何問題,但這樣通常會不小心寫出Bug
- 如果局部變量與全局變量重名,必要時可使用globals()['變量名']來訪問它,globals()類似于vars(),也返回一個字典
- 在函數(shù)中定義變量時,可在前面加入global 來聲明它是全局變量
- 作用域嵌套,可在函數(shù)中再定義函數(shù),并用return返回這個函數(shù)
在函數(shù)中訪問全局變量:
# 在函數(shù)中訪問全局變量
y = '全局'
def test(x):
print(x+y)
test('局部')
結(jié)果:

PS:做作業(yè)時發(fā)現(xiàn)np.array不用gobal關(guān)聯(lián)也會變化,于是猜測,可變變量似乎不用關(guān)聯(lián)也會變化
如果局部變量與全局變量重名:
# 如果局部變量與全局變量重名
y = '全局'
def test(y):
print(y+globals()['y'])
test('局部')
結(jié)果同上
重新關(guān)聯(lián)全局變量:
# 重新關(guān)聯(lián)全局變量
y = '全局'
def test():
global y
y = '我變了'
test()
print(y)
結(jié)果:

關(guān)于作用域嵌套:
In [2]: def first(x):
...: def second(y):
...: return y**x
...: return second
...: fun = first(2)
...: fun(2)
Out[2]: 4
6.6 遞歸
這個就不說了
函數(shù)式編程
- 主要說了map,filter,reduce,lambda
- 在較新的python版本中,可以用列表推導(dǎo)代替map和filter
- map:對列表中所有元素執(zhí)行函數(shù)
In [3]: list(map(str,range(10)))
Out[3]: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
In [4]: # 與下面等價
In [5]: [str(i) for i in range(10)]
Out[5]: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
- filter: 對序列中元素執(zhí)行函數(shù),若為結(jié)果真,把它添加到最終要返回的列表中
In [6]: def fun(x):
...: return x.isalnum()
...: list(filter(fun,['fdas','fdsa3','1*&']))
Out[6]: ['fdas', 'fdsa3']
# 與[x for x in [....] if x.isalnum] 等價
- reduce: 這個還是看例子
In [1]: from functools import reduce
In [2]: reduce(lambda x,y: x+y, [1,2,3,4,5,6,7,8,9])
Out[2]: 45
lambda的作用很明顯了
補充:
通常,不能給外部作用域內(nèi)的變量賦值,但如果一定要這樣做,可使用關(guān)鍵字nonlocal。這個關(guān)鍵字的用法與global很像,讓你能夠給外部作用域(非全局作用域)內(nèi)的變量賦值。
總結(jié)
抽象、函數(shù)定義、函數(shù)傳參、作用域、函數(shù)式編程(主要是函數(shù)式編程工具,用以代替定義函數(shù))
完了,希望不是在做無用功