日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

python基础函数图_Python基础:函数

發布時間:2024/10/12 python 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python基础函数图_Python基础:函数 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、概述

函數(function)是一個可調用的(callable)對象,它獲取一些(0個或多個)參數,然后執行一段代碼,最后返回一個值給調用者。

在Python中,函數是第一級對象(first-class),因此它具有與其他Python對象完全相同的基本行為特征,如可以被傳遞、可以作為右值進行賦值、可以作為另一個函數的參數或返回值等等。

二、聲明、定義和調用

與C/C++不同的是,Python中的函數不單獨區分 聲明 和 定義,這兩者同時發生在def語句被執行時,因此統一稱為 定義。

def funcname([parameters]):

與其他高級語言類似,Python中的函數必須在定義后才能 調用(即先定義,后調用);同時,在函數定義中允許存在 前向引用(即在函數A的定義中引用了函數B,但函數B在函數A之后才定義)。

# 先定義,后調用

>>> funcA()

Traceback (most recent call last):

File "", line 1, in

NameError: name 'funcA' is not defined

>>> def funcA():

... print 'ok'

...

>>> funcA()

ok

# 前向引用

>>> def funcA():

... print 'in funcA()'

... funcB()

...

>>> def funcB():

... print 'in funcB()'

...

>>> funcA()

in funcA()

in funcB()

# 前向引用(也必須遵守“先定義,后調用”的原則)

>>> def funcA():

... print 'in funcA()'

... funcB()

...

>>> funcA()

in funcA()

Traceback (most recent call last):

File "", line 1, in

File "", line 3, in funcA

NameError: global name 'funcB' is not defined

三、參數

以下討論中,實參 是指調用函數時由調用者傳入的參數,形參 是指函數定義中在內部使用的參數(類似于C/C++中的參數概念)。

1、參數傳遞

Python中對函數參數的傳遞采用 傳引用 的方式,即實參和形參都是引用,它們指向同一個對象實體(換言之,即形參是實參的淺拷貝)。

例如有以下函數:

>>> def changer(a, b): # 函數定義

... a = 2 # 改變形參a

... b[0] = 'spam' # 改變形參b

...

>>> X = 1 # 實參X指向一個整數(不可變對象)

>>> L = [1, 2] # 實參L指向一個列表(可變對象)

>>> changer(X, L) # 函數調用

>>> X # 對形參a的修改,不影響實參X

1

>>> L # 對形參b的修改,影響了實參L

['spam', 2]

上述示例中,函數changer的實參和形參的傳遞關系如下:

綜上可知:

如果參數引用的對象本身是 不可變的,如數值、字符串、元組,則在函數中對形參的修改 不會影響 實參

如果參數引用的對象本身是 可變的,如列表、字典,則在函數中對形參的修改 會影響 實參

2、實參類型

調用函數時,可以指定兩種類型的參數:位置參數(positional argument)和關鍵字參數(keyword argument)(參考 argument)。

1)位置參數

位置參數 又稱為非關鍵字參數(non-keyword argument),這種參數的指定方式有兩種:直接以值的形式 和 以 * 開頭的可迭代對象 (iterable)。

例如,在以下對complex()函數的調用中,3和5都是位置參數:

>>> complex(3, 5)

(3+5j)

>>> complex(*(3, 5))

(3+5j)

2)關鍵字參數

關鍵字參數 的指定方式也有兩種:以 name=value 的形式 和 以 ** 開頭的字典。

例如,在以下對complex()函數的調用中,3和5都是關鍵字參數:

>>> complex(real=3, imag=5)

(3+5j)

>>> complex(**{'real': 3, 'imag': 5})

(3+5j)

3)混合使用

如果在調用函數時,要混合使用位置參數和關鍵字參數,則位置參數必須位于關鍵字參數之前。

例如,在以下對complex()函數的調用中,3是位置參數,5是關鍵字參數:

>>> complex(3, imag=5)

(3+5j)

3、形參綁定

在函數定義中,可以指定四種類型的參數:常規參數、默認參數、變長元組參數和變長字典參數。這四種形參類型的區別與 形參綁定 強相關。

形參綁定 是指:調用函數時,Python對實參與形參進行一一匹配的過程(進而完成參數傳遞)。在這個綁定過程中,每種形參能夠接受的實參類型是不同的,具體對應關系如下:

形參類型實參類型(位置參數)實參類型(關鍵字參數)

常規參數

默認參數

變長元組參數

×

變長字典參數

×

下面結合實參與形參的綁定過程,分別介紹形參的這四種類型:

1)常規參數

常規參數 是必須指定的形參。根據實參類型的不同,綁定規則如下:

如果實參是“位置參數”,則按照 參數位置 來嚴格匹配實參和形參,實參和形參的個數必須相等、順序必須一致。

如果實參是“關鍵字參數”,則按照 參數名稱 來嚴格匹配實參和形參,實參和形參的個數必須相等、名稱必須一致(順序不重要)。

參考以下示例:

# 函數定義

>>> def func(a, b):

... print type(a), a

... print type(b), b

...

# 函數調用(實參是“位置參數”)

>>> func() # 個數必須相等

Traceback (most recent call last):

File "", line 1, in

TypeError: func() takes exactly 2 arguments (0 given)

>>> func(1)

Traceback (most recent call last):

File "", line 1, in

TypeError: func() takes exactly 2 arguments (1 given)

>>> func(1, 2, 3)

Traceback (most recent call last):

File "", line 1, in

TypeError: func() takes exactly 2 arguments (3 given)

>>> func(1, 2) # 順序一致時:a等于1,b等于2

1

2

>>> func(2, 1) # 順序相反時:a等于2,b等于1

2

1

# 函數調用(實參是“關鍵字參數”)

>>> func(a=1, b=2) # 順序一致時:a等于1,b等于2

1

2

>>> func(b=2, a=1) # 順序相反時:a等于1,b等于2

1

2

>>> func(c=1, d=2) # 名稱必須一致

Traceback (most recent call last):

File "", line 1, in

TypeError: func() got an unexpected keyword argument 'c'

2)默認參數

在函數定義中,默認參數 被指定了默認值,因此在調用函數時:

如果不指定對應的實參,則形參使用其默認值

如果指定了對應的實參,則形參使用實際指定的參數值

指定實參時,默認參數的綁定規則與“常規參數”相同

參考以下示例:

# 函數定義

>>> def func(a=1):

... print type(a), a

...

# 函數調用

>>> func() # 使用默認值

1

>>> func(2) # 實參是“位置參數”

2

>>> func(a=2) # 實參是“關鍵字參數”

2

對于默認參數,還有一點值得注意的是:默認參數只在函數定義(即執行def語句)時被求值一次,以后每次調用函數時都使用以前的值(參考 function definitions)。由此可知,當默認參數的默認值是一個可變對象的時候,如果函數內部對默認參數有修改,就會影響到下一次調用函數時的默認值(一般情況下,這可能不是你想要的行為)。簡單示例如下:

# 函數定義

>>> def func(a=[]):

... print a

... a.append(0)

...

# 函數調用

>>> func()

[]

>>> func()

[0]

>>> func()

[0, 0]

為了避免上述問題,可以采用以下方式:

# 函數定義

>>> def func(a=None):

... if a is None:

... a = []

... print a

... a.append(0)

...

# 函數調用

>>> func()

[]

>>> func()

[]

3)變長元組參數

在“常規參數”和“默認參數”綁定完成后(如果有的話),如果還有額外(0個或多個)的“位置參數”,則 變長元組參數 將會把這些多余的“位置參數”以 元組 的形式搜集到一起。示例如下:

# 函數定義

>>> def func(*args):

... print type(args), args

...

# 函數調用

>>> func() # 允許沒有“位置參數”

()

>>> func(1, 2) # 實參是“位置參數”

(1, 2)

>>> func(*(1, 2)) # 實參是“位置參數”

(1, 2)

>>> func(a=1, b=2) # 不接受實參是“關鍵字參數”的情況

Traceback (most recent call last):

File "", line 1, in

TypeError: func() got an unexpected keyword argument 'a'

4)變長字典參數

在“常規參數”和“默認參數”綁定完成后(如果有的話),如果還有額外(0個或多個)的“關鍵字參數”,則 變長字典參數 將會把這些多余的“關鍵字參數”以 字典 的形式搜集到一起。示例如下:

# 函數定義

>>> def func(**kwargs):

... print type(kwargs), kwargs

...

# 函數調用

>>> func() # 允許沒有“關鍵字參數”

{}

>>> func(a=1, b=2) # 實參是“關鍵字參數”

{'a': 1, 'b': 2}

>>> func(**{'a': 1, 'b': 2}) # 實參是“關鍵字參數”

{'a': 1, 'b': 2}

>>> func(1, 2) # 不接受實參是“位置參數”的情況

Traceback (most recent call last):

File "", line 1, in

TypeError: func() takes exactly 0 arguments (2 given)

5)混合使用

如果在函數定義中,要混合使用上述四種類型的形參,則這幾種形參類型的排列順序必須從左到右依次為:常規參數,默認參數,變長元組參數,變長字典參數。

以下為混合使用幾種形參的典型示例:

# 函數定義

>>> def func(a, b=0, *args, **kwargs):

... print type(a), a

... print type(b), b

... print type(args), args

... print type(kwargs), kwargs

...

# 函數調用

>>> func(1)

1

0

()

{}

>>> func(1, 2)

1

2

()

{}

>>> func(1, 2, 3)

1

2

(3,)

{}

>>> func(1, 2, 3, c=4)

1

2

(3,)

{'c': 4}

四、返回值

在Python中,一個函數總會返回一個值(除非發生異常),這個值可以是任何Python對象。根據具體函數的不同,返回值有以下幾種情況:

函數中的return語句實際返回的Python對象

無return

None

return

None

return a

對象a

return a, b, c

元組(a, b, c)

簡單示例如下:

>>> def f1(): pass

...

>>> def f2(): return

...

>>> def f3(): return 1

...

>>> def f4(): return 1, 2, 3

...

>>> f1(), f2(), f3(), f4()

(None, None, 1, (1, 2, 3))

五、名字空間與作用域

以下討論中,會根據下面的 示意圖 來進行具體示例分析:

1、基本概念

在Python程序中,一切對象都是借助 名字 來操作的(即名字引用對象)。名字空間(namespace)是名字到對象的映射。

在一個程序文本中,通常存在多個不同的 代碼塊(code block),例如模塊、函數體、類定義等,每個代碼塊都對應一個獨立的名字空間。名字空間中的名字只能在一個代碼范圍內可見,這個代碼范圍稱為 作用域(scope)。

對于上述概念的準確而詳細的描述,請參考 Naming and binding。

2、名字空間

一個代碼塊對應一個名字空間,具體到示意圖中的情況:

func局部名字空間:即func函數的代碼塊對應的名字空間,包含變量名e,函數參數名x、y、z

func_inner局部名字空間:即func_inner函數的代碼塊(除開func部分)對應的名字空間,包含變量名c,函數名func,函數參數名x、y

func_outer局部名字空間:即func_outer函數的代碼塊(除開func_inner部分)對應的名字空間,包含變量名b,函數名func_inner,函數參數x

全局名字空間:即模塊文件的代碼塊(除開func_outer部分)對應的名字空間,包含變量名a,函數名func_outer,變量名d(在func函數中以global方式定義),以及Python為模塊預置的一些名字(例如__name__、__builtins__等)

內建名字空間:包含內建模塊__builtin__中的所有名字,例如print(實際由全局名字空間中的__builtins__指定:在__main__模塊中,__builtins__就是內建的__builtin__模塊;在導入模塊中,__builtins__是字典__builtin__.__dict__的別名)

查看名字空間的一個簡單方法是:使用dir函數。例如,查看示意圖中各代碼塊對應名字空間的示例如下:

#!/usr/bin/env python

# -*- coding: utf-8 -*-

a = 1

def func_outer(x):

b = 2

def func_inner(y):

c = 3

def func(z):

global d

d = 4

e = x + y + z

print "func's namespace:"

print dir()

func(0)

print "func_inner's namespace:"

print dir()

func_inner(0)

print "func_outer's namespace:"

print dir()

if __name__ == '__main__':

func_outer(0)

print 'global namespace:'

print dir()

print 'built-in namespace:'

print dir(__builtins__)

運行結果:

$ python shownamespace.py

func's namespace:

['e', 'x', 'y', 'z']

func_inner's namespace:

['c', 'func', 'x', 'y']

func_outer's namespace:

['b', 'func_inner', 'x']

global namespace:

['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'a', 'd', 'func_outer']

built-in namespace:

['ArithmeticError', 'AssertionError', ..., 'xrange', 'zip']

3、作用域

Python中的作用域可以分為四種:局部作用域(Local scope)、外圍作用域(Enclosing scope)、全局作用域(Global scope)、內建作用域(Built-in scope)。

例如,對于示意圖中的函數func而言:

局部作用域 是指func函數對應的代碼范圍(包含在def語句或lambda表達式內部)

外圍作用域 是指func_outer函數對應的代碼范圍(包括內嵌的函數funct_inner,以及二次內嵌的函數func)

全局作用域 是指整個模塊文件對應的代碼范圍

內建作用域 是指任何的Python代碼范圍

上述幾種名字空間與這四種作用域的關系是:

func局部名字空間中的名字只在局部作用域可見

func_inner局部名字空間和func_outer局部名字空間中的名字只在外圍作用域可見

全局名字空間中的名字只在全局作用域可見

內建名字空間中的名字只在內建作用域可見

4、總原則

關于名字與作用域,主要記住以下兩點:

名字引用 遵循 LEGB 的查找規則:首先查找局部作用域(L),接著查找外圍作用域(E),然后查找全局作用域(G),最后查找內建作用域(B);否則查找失敗

名字賦值 默認新建一個局部作用域中的名字;如果與LEGB路徑上的其他作用域中的名字相同,則在LEGB查找時將屏蔽其他作用域中的相同名字;如果聲明為global,則將新建(或是覆蓋,如果已存在)一個全局作用域中的名字

六、高級

1、裝飾器

裝飾器(decorator)是一個函數,它對另一個函數進行包裝處理,進而擴展被包裝函數的功能。盡管名稱相同,但Python中的裝飾器并不是設計模式中的裝飾器模式的Python實現(可以參考 Decorators)。

@wrapper[(arg)]

def funcname([parameters]):

裝飾器可以不帶參數,例如以下兩種函數定義是等價的:

# 裝飾器版本

@f

def func(): pass

# 普通版本

def func(): pass

func = f(func)

裝飾器也可以帶參數,例如以下兩種函數定義是等價的:

# 裝飾器版本

@f(arg)

def func(): pass

# 普通版本

def func(): pass

func = f(arg)(func)

當然,還可以多個裝飾器嵌套使用,例如以下兩種函數定義是等價的:

# 裝飾器版本

@f1(arg)

@f2

def func(): pass

# 普通版本

def func(): pass

func = f1(arg)(f2(func))

以上都是函數定義中的裝飾器語法,下面給出一個裝飾器實現的簡單示例:

>>> def wrapper(func):

... def wrappedFunc():

... print 'before func'

... func()

... print 'after func'

... return wrappedFunc

...

>>> @wrapper

... def func():

... print 'in func'

...

>>> func()

before func

in func

after func

2、生成器

生成器(generator)是一個帶有yield語句的函數,與普通函數不同的是,它返回一個支持迭代器(iterator)協議的對象。

以下是一個生成器的簡單示例:

# 平方生成器

>>> def squares(N):

... for i in range(N):

... yield i ** 2

...

# 返回一個生成器對象,該對象支持迭代器協議

>>> x = squares(2)

>>> x

>>> x.next()

0

>>> x.next()

1

>>> x.next()

Traceback (most recent call last):

File "", line 1, in

StopIteration

# for循環自動調用next(),并處理StopIteration異常

>>> for i in squares(2):

... print i

...

0

1

如果要嚴格區分的話,在上述示例中,squares 是生成器函數,而 x 才是生成器(對象)??梢越柚?inspect模塊 來體會二者的區別(參考 Python yield使用淺析):

>>> import inspect

>>> inspect.isgeneratorfunction(squares), inspect.isgeneratorfunction(x)

(True, False)

>>> inspect.isgenerator(squares), inspect.isgenerator(x)

(False, True)

關于生成器,需要注意以下幾點:

yield語句會產生一個值,作為next()調用的返回值

yield語句會中斷函數處理,并記住當前的執行狀態(中斷位置和變量值等),以便后續原狀態恢復執行

如果恢復執行后,已經沒有yield語句可執行,則拋出StopIteration異常(以示迭代結束)

生成器中一般沒有return語句,如果執行中遇到了return語句,則直接拋出StopIteration異常

總結

以上是生活随笔為你收集整理的python基础函数图_Python基础:函数的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。