1. 程式人生 > >Python基礎4 函數

Python基礎4 函數

gen 語法 修改 需要 易維 ffffff blog 溢出 python

函數基本語法及特性

函數是什麽?

定義:

函數是指將一組語句的集合通過一個名字(函數名)封裝起來,要想執行這個函數,只需調用其函數名即可。

特性:

減少重復代碼

使程序變的可擴展

使程序變的易維護

def sayhi():    # 函數名
    print(Hi, Im Jack!)

sayhi()    # 調用函數

函數也可以帶參數

def test(x, y):
    print(x, y)

test(1,2)


函數參數與局部變量

形參:

變量只有在被調用時才分配內存單元,在調用結束時,即刻釋放所分配的內存單元。因此,形參只在函數內部有效。函數調用結束返回主調用函數後則不能再使用該形參變量。

實參:

可以是常量、變量、表達式、函數等,無論實參是何種類型的量,在進行函數調用時,它們都必須有確定的值,以便把這些值傳送給形參。因此應預先用賦值,輸入等辦法使參數獲得確定值。

def test(x, y):     # x, y為形式參數       
    print(x + y)    

test(1, 2)    # 1, 2為實際參數

默認參數:

def test(x, y, z=3):    # z為默認參數
    print(x + y + z)    

test(1, 2)      # 在函數調用時,可以不給z傳值,如果不傳則該參數的值為3

關鍵字參數:

正常情況下,給函數傳參數要按順序,不想按順序就可以用關鍵參數,只需指定參數名即可,但記住一個要求就是,關鍵參數必須放在位置參數之後。

def test(x, y, z):
    print(x + y + z)

test(1, z=3, y=10)    # 這裏調用test函數時,先將位置參數1賦值給x再將z、y以關鍵字參數形式傳入函數中

非固定參數:

若你的函數在定義時不確定用戶想傳入多少個參數,就可以使用非固定參數,*args 會把多傳入的參數變成一個元組形式。

def test(x, y, *args):
    print(x, y, *args, x, y, args)

test(1, 2, 3, 4)

>>> x, y, *args 1 2 (3, 4)

還可以有一個**kwargs,*kwargs 會把多傳入的參數變成一個dict形式。

def test(x, y, *args, **kwargs):
    print(x, y, *args, **kwargs, x, y, args, kwargs)

test(1, 2, 3, 4, a=5, b=6, c=7)

>>>x, y, *args, **kwargs 1 2 (3, 4) {c: 7, a: 5, b: 6}

局部變量

name = Jack

def test(name):
    name = Tom
    print(My name is , name)

test(name)

函數會從自身查name變量去調用

全局變量與局部變量

在子程序中定義的變量稱為局部變量,在程序的一開始定義的變量稱為全局變量。 全局變量作用域是整個程序,局部變量作用域是定義該變量的子程序。 當全局變量與局部變量同名時: 在定義局部變量的子程序內,局部變量起作用;在其它地方全局變量起作用。

返回值

要想獲取函數的執行結果,就可以用return語句把結果返回

註意:

函數在執行過程中只要遇到return語句,就會停止執行並返回結果,也可以理解為 return 語句代表著函數的結束

如果未在函數中指定return,那這個函數的返回值為None


嵌套函數

name = Tom


def change_name1():
    name = Tom1
    def change_name2():
        name = Tom2
        print(name)
    change_name2()
    print(name)

change_name1()
print(name)


遞歸

遞歸特性:

必須有一個明確的結束條件

每次進入更深一層遞歸時,問題規模相比上次遞歸都應有所減少

遞歸效率不高,遞歸層次過多會導致棧溢出(在計算機中,函數調用是通過棧(stack)這種數據結構實現的,每當進入一個函數調用,棧就會加一層棧幀,每當函數返回,棧就會減一層棧幀。由於棧的大小不是無限的,所以,遞歸調用的次數過多,會導致棧溢出)

def calc(n):
    print(n)
    if int(n/2) == 0:
        return n
    print(----)
    return calc(int(n/2))

calc(10)


匿名函數

匿名函數就是不需要顯式的指定函數

def calc(n):
    return n*n
print(calc(10))


# 匿名函數
calc = lambda n: n*n
print(calc(10))


高階函數

變量可以指向函數,函數的參數能接收變量,那麽一個函數就可以接收另一個函數作為參數,這種函數就稱之為高階函數。

def add(x, y, f):
    return f(x) + f(y)

res = add(-3, 4, abs)
print(res)


叠代器、生成器、裝飾器

叠代器

凡是可作用與for循環的對象都是可叠代對象
凡是可作用於next()函數的對象都是叠代器類型,表示一個惰性計算的序列
集合數據類型是可叠代對象,但不是叠代器,可通過iter()函數獲得一個叠代器對象
Python的for循環本質上是通過不斷調用next()函數實現的

import time
 
def consumer(name):
    print ("%s 準備吃包子啦!" % name)
    while True:
        baozi = yield
        print ("包子[%s]來了,被[%s]吃了" % (baozi,name))
 
def producer():
    c1 = consumer("Jack")
    c2 = consumer("Tom")
    c1.__next__()
    c2.__next__()
    for i in range(1,11):
        time.sleep(1)
        print ("做好1個包子,分成兩份!")
        c1.send(i)
        c2.send(i)
producer()

生成器

#列表生成式
list1 = [i*2 for i in range(1,11)]
list = (x*2 for x in range(1,1000000))

#函數生成器
def fib(max):
    n,a,b = 0,0,1
    while n < max:
        #print (b)
        yield b
        a,b = b,a+b
        n = n + 1
    #return異常的時候打印消息
    return "done"
 
g = fib(10)
while True:
    try:
        x = next(g)
        print ("g:",x)
    except StopIteration as e:
        print ("Generator return value:",e.value)
        break

裝飾器

本身是函數,(裝飾其他函數)就是為其他函數添加附加功能

原則:

不能修改被裝飾的函數的源代碼

不能修改被裝飾的函數的調用方式

實現裝飾器知識儲備:

函數即“變量”

高階函數

嵌套函數

高階函數+嵌套函數=》裝飾器

def logging(func):
    def warpper(*args,**kwargs):
        func(*args,**kwargs)
        print("logging...")
    return warpper
 
@logging
def test1(name,age):
    print("func in %s,%s" % (name,age))
 
@logging
def test2(name,age):
    print("func in %s,%s" % (name,age))

Python基礎4 函數