Python函數高級應用

變量作用域

1)全局變量

  • 標識符的作用域是定義爲其聲明在程序裏的可應用範圍,也就是變量的可見性
  • 在一個模塊中最高級別的變量有全局作用域
  • 全局變量的一個特徵是除非被刪除掉,否則它們的存活到腳本運行結束,且對於所有的函數,他們的值都是可以被訪問的
>>> a = 10
>>> def func1():
...   print(a)
...
>>> func1()
10
# 在函數內定義的變量是局部變量,只能在函數內使用
>>> def func2():
...   b = 100
...   print(b)
...
>>> func2()
100
>>> print(b)   # Error,全局沒有b這個名字
# 如果函數內和全局有相同的名字,函數內的名字將會遮蓋住全局的名字
>>> def func3():
...   a = 'hello world'
...   print(a)
...
>>> func3()
hello world
>>> print(a)   # 全局變量a的值仍然是10
10
# 如果需要在函數內(局部)改變全局的值,可以使用global關鍵字
>>> def func4():
...   global a
...   a = 1000
...   print(a)
...
>>> print(a)
10
>>> func4()
1000
>>> print(a)
1000

2)局部變量

  • 局部變量只時暫時地存在,僅僅只依賴於定義它們的函數現階段是否處於活動
  • 當一個函數調用出現時,其局部變量就進入聲明它們的作用域。在那一刻,一個新的局部變量名爲那個對象創建了
  • 一旦函數完成,框架被釋放,變量將會離開作用域
  • 如果函數內有局部變量的name與全局變量相同,那麼在引用時,優先局部變量

函數式編程

1)偏函數

  • 偏函數的概念是將函數式編程的概念和默認參數以及可變參數結合在一起
  • 一個帶有多個參數的函數,如果其中某些參數基本上固定的,那麼就可以通過偏函數爲這些參數賦默認值
>>> def add(a,b,c,d,e):
...     print(a+b+c+d+e)
... 
>>> add(1,2,3,4,5)
15
>>> add(1,2,3,4,6)
16
>>> add(1,2,3,4,7)
17
>>> import functools
>>> add2 = functools.partial(add,1,2,3,4) #改造的函數,位置參數1,位置參數2,位置參數3,位置參數4
>>> add2(5)   #此時abcd均有值,所以5爲e的值
15
>>> add2(6)
16
>>> add2(7)
17
>>> 
>>> int('10101100',base=2)  #base=2表示被轉換的數字爲2進制數
172
>>> int2 = functools.partial(int,base=2) #使用偏函數改造,將base=2設爲默認
>>> int2('10101100')
172
#簡單的gui圖形程序
import tkinter
from functools import partial
root = tkinter.Tk()    #創建頂層窗口
lb1 = tkinter.Label(root, text="hello world!", font = "Aria 16 bold")#創建標籤
b1 = tkinter.Button(root, bg='blue', fg='white', text="Button 1")#創建按鈕
mybutton = partial(tkinter.Button, root, bg='blue', fg='white')
#調用新的函數時,給出改變的參數即可
b2 = mybutton(text='Button 2')
b3 = tkinter.Button(root, bg='red', fg='red', text='QUIT', command=root.quit)    #創建按鈕,綁定了root.quit命令
lb1.pack()    #填充到界面
b1.pack()
b2.pack()
b3.pack()
root.mainloop()    #運行這個GUI應用

2)遞歸函數

  • 如果函數包含了對其自身的調用,該函數就是遞歸的
  • 在操作系統中,查看某一目錄內所有文件、修改權限等都是遞歸的應用
# 階乘函數,例:5!=5*4*3*2*1   5!=5*4!   ...
def func(x):
    if x == 1:
        return 1
    return x * func(x - 1)

if __name__ == '__main__':
    print(func(5))
# 指定序列對象進行快速排序
from random import randint

def qsort(seq):
    '接受一個序列對象,返回排序結果'
    if len(seq) < 2:
        return seq

    # 假設第1項是中間值
    middle = seq[0]
    smaller = []
    larger = []
    # 遍歷後續項,比middle小的放到samller,比middle大的放到larger
    for data in seq[1:]:
        if data < middle:
            smaller.append(data)
        else:
            larger.append(data)

    # 把3項數據拼接
    return qsort(smaller) + [middle] + qsort(larger)

if __name__ == '__main__':
    nums = [randint(1, 100) for i in range(10)]
    print(nums)
    result = qsort(nums)
    print(result)

生成器

  • 生成器表達式:和列表解析有一樣的語法格式
>>> ['192.168.1.%s' % i for i in range(1, 255)] #列表解析
>>> ips = ('192.168.1.%s' % i for i in range(1, 255)) #生成器
>>> print(ips)
<generator object <genexpr> at 0x7f007b5b82b0>
>>> for ip in ips:
...   print(ip)
  • 生成器函數:本質上還是函數
    • 生成器函數可以通過yield關鍵字返回很多中間值
>>> def mygen():
...   yield 100
...   a = 10 + 20
...   yield a
...   yield 'Hello World'
...
>>> mg = mygen()   # 創建一個生成器對象
>>> next(mg)       # 從生成器對象中取值
100
>>> next(mg)
30
>>> next(mg)
'Hello World'
>>> next(mg)       # 生成器對象無值可取的時候,返回StopIteration異常
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

>>> mg = mygen()
>>> for data in mg:
...   print(data)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章