1. 程式人生 > >python3函數

python3函數

print 執行函數 內存 訪問權限 如果 標識 num ref 重新定義

一、python3函數

函數是組織好的,可重復使用的,用來實現單一,或相關聯功能的代碼段。

函數能提高應用的模塊性,和代碼的重復利用率。可以自己創建函數,這被叫做用戶自定義函數。

1、定義函數規則

  • 函數代碼塊以 def 關鍵詞開頭,後接函數標識符名稱和圓括號 ()
  • 任何傳入參數和自變量必須放在圓括號中間,圓括號之間可以用於定義參數。
  • 函數的第一行語句可以選擇性地使用文檔字符串—用於存放函數說明。
  • 函數內容以冒號起始,並且縮進。
  • return [表達式] 結束函數,選擇性地返回一個值給調用方。不帶表達式的return相當於返回 None。

2、語法

python定義函數使用def關鍵字,格式如下:

def 函數名(參數列表):

  函數體

>>> def hello():      #定義簡單函數
...   print(hello world)
... 
>>> hello()   #執行函數
hello world
>>> def yourname(name):   #傳參函數
...   print(your are name is:,name)
... 
>>> yourname(qi)    #執行傳參函數
your are name is: qi

>>> def
multiplication(x,y): #傳參運算函數 ... return x*y ... >>> multiplication(8,9) 72

3、函數調用

定義一個函數:給函數一個名稱,並指定了函數裏包含的參數和代碼塊結構。這個函數的基本結構完成以後。

可以通過另一個函數調用執行,也可以直接從python命令提示符執行

>>> def times(date):
...   打印當前時間
...   print(date);
...   return time.strftime("%Y-%m-%d %H:%M:%S
", time.localtime()) ... >>> import time >>> times(當前時間是) 當前時間是 2017-09-30 23:23:27

4、參數傳遞

在 python 中,類型屬於對象,變量是沒有類型。

可更改(mutable)與不可更改(immutable)對象

在 python 中,strings, tuples, 和 numbers 是不可更改的對象,而 list,dict 等則是可以修改的對象。

  • 不可變類型:變量賦值 a=5 後再賦值 a=10,這裏實際是新生成一個 int 值對象 10,再讓 a 指向它,而 5 被丟棄,不是改變a的值,相當於新生成了a。

  • 可變類型:變量賦值 la=[1,2,3,4] 後再賦值 la[2]=5 則是將 list la 的第三個元素值更改,本身la沒有動,只是其內部的一部分值被修改了。

python 函數的參數傳遞:

  • 不可變類型:類似 c++ 的值傳遞,如 整數、字符串、元組。如fun(a),傳遞的只是a的值,沒有影響a對象本身。比如在 fun(a)內部修改 a 的值,只是修改另一個復制的對象,不會影響 a 本身。

  • 可變類型:類似 c++ 的引用傳遞,如 列表,字典。如 fun(la),則是將 la 真正的傳過去,修改後fun外部的la也會受影響

python 中一切都是對象,嚴格意義我們不能說值傳遞還是引用傳遞,我們應該說傳不可變對象和傳可變對象。不可變實例:

>>> def changeint(x):   #定義函數傳參賦值
...   x = 100
... 
>>> i1 = 200
>>> changeint(i1)   #當將定義的變量賦值給函數調用後,原變量還是不變,只是把i1變量的值復制給了x,它們同時指向這個對象。
>>> print(i1)
200

傳可變對象實例:

可變對象在函數裏修改了參數,那麽在調用這個函數的函數裏,原始的參數也被改變了。

>>> def changelist(l1,v):   #定義列表插入函數
...   l1.insert(2,v)
...   return l1
... 
>>> list1 = [1,2,3,4]    #列表
>>> changelist(list1,python)   #應用外面的列表,即會影響外面列表的內容
[1, 2, python, 3, 4]
>>> print(list1)    #列表內容被改變
[1, 2, python, 3, 4]

5、參數類型

必須參數:在一個函數指定需要參數時,在執行函數是必須指定參數,否則會報錯

關鍵字參數:使用關鍵字傳遞參數時,參數順序可以隨意,解釋器會根據參數名來匹配參數傳遞

默認參數:調用函數時,如果沒有傳遞參數,則會使用默認參數。

不定長參數:如傳遞列表,元祖,字典時,參數的個數不定長,可以使用(*)代表不定長,

>>> def foo(user):        #必須參數
...   print(user,去旅遊)    
... 
>>> foo(張三)
張三 去旅遊
>>> foor()    #如不傳遞參數執行函數會報錯
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name foor is not defined
>>> def foo(user,action):
...   print(action,去了,user)   #通過關鍵字傳遞參數給函數實體調用,不用不按順序
... 
>>> foo(李四,上班)
上班 去了 李四

>>> def foo(user,action=北京):   #定義默認參數是必須在最後定義
...   print(user,來自,action)
... 
>>> foo(zhangsan,shanghai)   #如指定則輸出指定值
zhangsan 來自 shanghai
>>> foo(shangsan)   #如指定一個參數則輸出默認值
shangsan 來自 北京

>>> def foo(user,where=北京,action=旅遊):  #定義默認參數
...   print(user,,where,action)
... 
>>> foo(zhangsan,shanghai,gongzuo)  #指定參數輸出
zhangsan 去 shanghai gongzuo
>>> foo(lisi)   #如只指定一個參數則使用默認參數
lisi 去 北京 旅遊
>>> foo(lisi,action=工作)  #在有多個默認參數時,需指定參數名傳參
lisi 去 北京 工作
>>> foo(lisi,where=上海,action=學習)
lisi 去 上海 學習

>>> def show(*args):  #不定長傳參
...   for i in args:
...     print(i)
... 
>>> show(zhangsan,lisi,wangwu)
zhangsan
lisi
wangwu
>>> l1 = [1,2,3,4]
>>> show(l1)
[1, 2, 3, 4]
>>> show(*l1)  #在列表傳參是必須使用*來不定長傳參
1
2
3
4

>>> def show(**kargs):    #兩參數不定長傳參,也就是字典傳參
...   for i in kargs.items():
...     print(i)
... 
>>> show(name=zhangsan,age=9999)
(age, 9999)
(name, zhangsan)
>>> dict = {k1:123,k2:456,k3:678}
>>> show(dict)     #在傳參字典時會將字典當一個參數傳入會報錯
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: show() takes 0 positional arguments but 1 was given
>>> show(**dict)   #必須使用(**)將參數分隔傳參
(k1, 123)
(k2, 456)
(k3, 678)

6、return語句

return [表達式] 語句用於退出函數,選擇性地向調用方返回一個表達式。不帶參數值的return語句返回None。

>>> def foo():
...   1+1
...   return
... 
>>> print(foo())  #默認返回None
None
>>> def foo():
...   1+1
...   return 0    #指定返回值
... 
>>> print(foo())
0
>>> def foo():
...   return 1+1
... 
>>> print(foo())
2
>>> def foo():
...   print(1+1)
...   return 1+2
... 
>>> print(foo())
2
3

7、變量作用域

Python 中,程序的變量並不是在哪個位置都可以訪問的,訪問權限決定於這個變量是在哪裏賦值的。

變量的作用域決定了在哪一部分程序可以訪問哪個特定的變量名稱。Python的作用域一共有4種,分別是:

  • L (Local) 局部作用域
  • E (Enclosing) 閉包函數外的函數中
  • G (Global) 全局作用域
  • B (Built-in) 內建作用域

以 L –> E –> G –>B 的規則查找,即:在局部找不到,便會去局部外的局部找(例如閉包),再找不到就會去全局找,再者去內建中找。

>>> m = girl    #全局作用域變量
>>> def func(): 
...   m = boy    #局部作用域變量
...   return m
... 
>>> func()     #優先使用局部作用域變量
boy
>>> print(m)   #但不改變全局作用域的變量
girl

>>> def foo():
...   num = x + 100    #變量x沒有定義會報錯
...   return num
... 
>>> foo()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in foo
NameError: name x is not defined
>>> x = 11   #定義一個全局變量
>>> foo()   #則函數會調用全局變量
111

>>> num = 100
>>> def func():
...   num = 200
...   x = num + 100
...   return x
... 
>>> func()
300

>>> n = 10   #全局
>>> def foo():
...   global n   #使用global定義局部變量為全局變量,並會覆蓋前面的變量值
...   n = 100
...   return n
... 
>>> foo()
100
>>> print(n)   #全局變量值會改變
100

>>> def foo():  #定義一個嵌套函數
...   num = 5
...   def bar():    #嵌套使用閉包作用域變量
...     print(num)
...   bar()
...   print(num)
... 
>>> foo()
5
5

>>> def foo():
...   num1 = 20
...   def bar():
...     z = 30
...     print(num1)
...   bar()
...   print(z)
... 
>>> foo()
20
Traceback (most recent call last):    #而當嵌套內閉包作用域在未定義時引用就會報錯
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 7, in foo
NameError: name z is not defined

>>> def foo():
...   m = 111
...   def bar():
...     n = 222
...     print(m+n)    #在bar()函數中的m就是一個既不屬於全局域又不屬於局部域的閉包變量,它存活在一個函數的名稱空間和作用域,即嵌套作用域
...   bar()
...   print(m)
... 
>>> foo()
333
111

def foo():
   num2 = 400
   def bar():
    print(num2)
    num2 = 333
    print(num2)
   bar()
foo()

Traceback (most recent call last):  #錯誤原因為num2為不可變類型,此處不能重新定義
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 7, in foo
  File "<stdin>", line 4, in bar
UnboundLocalError: local variable num2 referenced before assignment

def foo():
   num2 = [400]  
   def bar():
    print(num2[0])
    num2[0] = 333   #如果定義為列表則不會報錯了
    print(num2[0])
   bar()
foo()
400
333

二、匿名函數

python 使用 lambda 來創建匿名函數。

所謂匿名,意即不再使用 def 語句這樣標準的形式定義一個函數。

  • lambda 只是一個表達式,函數體比 def 簡單很多。
  • lambda的主體是一個表達式,而不是一個代碼塊。僅僅能在lambda表達式中封裝有限的邏輯進去。
  • lambda 函數擁有自己的命名空間,且不能訪問自己參數列表之外或全局命名空間裏的參數。
  • 雖然lambda函數看起來只能寫一行,卻不等同於C或C++的內聯函數,後者的目的是調用小函數時不占用棧內存從而增加運行效率。

1、語法

lambda函數的語法只包含一個語句

lambda [arg1 [,arg2....argn]]:expression

>>> funct1 = lambda x,y:x+y     #生成一個匿名函數
>>> print(funct1(10,43))    
53
>>> funct2 = lambda x:x**3
>>> print(funct2(2))
8
>>> funct3 = lambda x,y=3,z=4:x+y+z   #參數可以設置默認值
>>> print(funct3(3))
10
>>> print(funct3(3,4,5))
12
>>> print(funct3(3,y=9))   #註意多參數傳值時需指定參數名
16
>>> print(funct3(3,z=8,y=9))
20
>>> list(map(lambda x:x**3,[1,2,3,4,5]))  #使map生成序列
[1, 8, 27, 64, 125]
>>> list(map(lambda x,y:x+y,[11,22,33,44],[1,2,3,4])) #多個參數傳值,如不匹配則以最少為準
[12, 24, 36, 48]
>>> list(map((lambda x:x+5),range(10))) #使用叠代器
[5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
>>> l1 = [(lambda x:x+5),(lambda x:x**2),(lambda x:x/2)] #生成可變列表
>>> print(l1[0](5),l1[1](3),l1[2](10))
10 9 5.0
>>> dict1 = {k1:(lambda x:x**2),k2:(lambda x:x**3),k3:(lambda x:x**4)}
>>> print(dict1[k1](2),dict1[k2](2),dict1[k3](2))  #生成可變字典
4 8 16

python3函數