国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

腳本之家,腳本語言編程技術及教程分享平臺!
分類導航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務器之家 - 腳本之家 - Python - 詳細介紹Python函數中的默認參數

詳細介紹Python函數中的默認參數

2020-05-25 09:46Leonardo Giordani Python

這篇文章主要介紹了詳細介紹Python函數中的默認參數,包括默認參數的傳遞和求值等內容,需要的朋友可以參考下

?
1
2
3
4
5
6
import datetime as dt
 
def log_time(message, time=None):
  if time is None:
    time=dt.datetime.now()
  print("{0}: {1}".format(time.isoformat(), message))

最近我在一段Python代碼中發現了一個因為錯誤的使用默認參數而產生的非常惡心的bug。如果您已經知道關于默認參數的全部內容了,只是想嘲笑一下我這可笑的錯誤,請直接跳到本文末尾。哎,這段代碼是我寫的,但是我非常確定那天我被惡魔附體了。你懂的,有時候就是這樣。

本文僅僅是總結一下關于Python函數的標準參數和默認參數的一些基本內容。提醒你注意你的代碼中可能存在的陷阱。如果你剛開始接觸Python,開始寫一些函數,我真心推薦你看一下Python官方手冊中關于函數的內容,鏈接如下:Defining Functions 以及 More on Defining Functions
簡單復習一下函數

Python是一個強大的面向對象語言,它把這種編程范式推向了頂峰。但是,面向對象編程仍然需要依靠函數這一概念,你可以用它來處理數據。Python對于可調用對象有一個更寬泛的概念,即任何對象都可以被調用,調用的意思是對其應用數據。

函數在Python中是可調用對象,并且乍一看,它和其他語言中的函數有著類似的行為。它們獲取一些數據,這些數據被稱為參數,然后處理它們,接著返回結果(如果沒有return語句則是None)

參數被聲明為占位符(在定義函數的時候),用以代表那些當函數調用時被實際傳入的對象。在Python中你不需要聲明參數的類型(例如,像你在C或Java中做的那樣)因為Python哲學依賴于多態。

記住,Python的變量是引用,即實際變量的內存地址。這意味著Python的函數永遠以“傳址”的方式工作(這里使用了一個C/C++術語),當你調用一個函數的時候,并不是復制了一份參數的值來替換占位符,而是把占位符指向了變量本身。這導致了一個非常重要的結果:你可以在函數內部改變這個變量的值。這里有一個很好可視化講解,關于引用機制。

引用在Python扮演著非常重要的角色,它是Python完全多態方式的骨干。關于這個非常重要的主題,請點擊這個鏈接 查看更好的解釋。

為了檢查你是否理解了這門語言的這一基本特性,請跟隨這段簡單的代碼(變量ph代表的是“占位符(placeholder)”)
 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
>>> def print_id(ph):
... print(hex(id(ph)))
...
>>> a = 5
>>> print(hex(id(a)))
0x84ab460
>>> print_id(a)
0x84ab460
>>>
>>> def alter_value(ph):
... ph = ph + 1
... return ph
...
>>> b = alter_value(a)
>>> b
6
>>> a
5
>>> hex(id(a))
'0x84ab460'
>>> hex(id(b))
'0x84ab470'
>>>
>>> def alter_value(ph):
... ph.append(1)
... return ph
...
>>> a = [1,2,3]
>>> b = alter_value(a)
>>> a
[1, 2, 3, 1]
>>> b
[1, 2, 3, 1]
>>> hex(id(a))
'0xb701f72c'
>>> hex(id(b))
'0xb701f72c'
>>>

如果你對這里發生的事情并不感到吃驚,那說明你已經掌握了Python中最為重要的部分之一,你可以放心的跳過下面的解釋了。

print_id()函數顯示,函數內部的占位符同運行時傳入的變量完全一樣(它們的內存地址一致)。

兩個版本的alter_value()意在改變傳入參數的值。正如你所看到的,第一個alter_value() 并沒有像第二個alter_value()一樣成功的改變變量a的值。這是為什么呢?實際上兩者的行為是一樣的,都是嘗試修改傳入的原始變量的值,但是在Python中,有些變量是不可變的(immutable),整數就在此列。另一方面,列表并不是不可變的,所以函數得以完成它的名字所保證的工作。 在這里,你可以找到關于不可變類型的更加詳細的介紹 。

關于Python中的函數,還有一些要說的,但是這些是關于標準的參數的基本知識。
默認參數值

有時候你需要定義一個函數,讓它接受一個參數,而且在這個參數出現或不出現時,函數有不同的行為。如果一門語言不支持這種情況,你就只有兩個選擇:第一種是定義兩個不同的函數,決定每次調用應該選擇調用哪個,第二種是 兩種方法都是可行的,但是都不是最佳的。

Python和其他語言一樣,支持默認參數值,即函數參數可以是調用時指定的,也可以留空,自動接受一個預定義的值。

一個關于默認值的非常簡單(也很沒用)的例子如下:
 

?
1
2
3
def log(message=None):
  if message:
    print("LOG: {0}".format(message))

這個函數可以帶一個參數運行(可以是None)

?
1
2
3
4
>>> log("File closed")
LOG: File closed
>>> log(None)
>>>

 

但是同樣也可以不帶參數運行,這種情況下它會接受一個函數原型中設置的默認值(本例中是None)
 

?
1
2
>>> log()
>>>

你可以在標準庫中找到更多有趣的例子,比如在open()函數中(請查看官方文檔
 

?
1
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)

函數原型可以證明,例如 f = open('/etc/hosts')這樣的調用,通過傳入默認值隱藏了很多參數 (mode, buffering, encoding, 等),并且使這個函數的典型應用案例變得非常簡單易用。

正如你在內建的open()函數中看到的那樣,我們可以在函數中使用標準或者默認參數,但是兩者在函數中出現的次序是固定的:首先調用標準參數,然后調用默認參數。
 

?
1
2
def a_rich_function(a, b, c, d=None, e=0):
  pass

原因是顯而易見的:如果我們可以在標準參數前面放置一個默認參數,語言就無法理解,默認參數是否已經被初始化。例如,考慮下面這個函數定義
 

?
1
2
def a_rich_function(a, b, d=None, c, e=0):
  pass

當調用函數a_rich_function(1, 2, 4, 5)時,我們傳入了什么參數? 是d=4, c=5 還是c=4, e=5?因為d有一個默認的值。因此這種順序的定義是被禁止的,如果你這樣做,Python會拋出一個SyntaxError
 

?
1
2
3
4
5
6
>>> def a_rich_function(a, b, d=None, c, e=0):
... pass
...
 File "<stdin>", line 1
SyntaxError: non-default argument follows default argument
>>>

默認參數求值

默認參數可以通過普通值或是函數調用結果來提高,但是后者這種技術需要一個特別的警示

一個普通的值是硬編碼的,因此除了編譯時,其他時候是不需要求值的,但是函數調用期望在運行時執行求值。所以我們可以這樣寫
 

?
1
2
3
4
import datetime as dt
 
def log_time(message, time=dt.datetime.now()):
  print("{0}: {1}".format(time.isoformat(), message))

每次我們調用log_time()時都期望它能夠正確提供當前時間。悲劇的是并沒有成功:默認參數在定義時求值(比如說當你首次導入模塊時),調用的結果如下
 

?
1
2
3
4
5
6
>>> log_time("message 1")
2015-02-10T21:20:32.998647: message 1
>>> log_time("message 2")
2015-02-10T21:20:32.998647: message 2
>>> log_time("message 3")
2015-02-10T21:20:32.998647: message 3

如果把默認值賦給一個類的實例,結果會更加奇怪,你可以在Hitchhiker's Guide to Python!中讀到相關內容。根據。。通常的解決方法是把默認參數替換為None,并且在函數內部檢查參數值。
 
結論

默認參數能夠極大的簡化API,你需要關注它唯一的“失敗點”,即求值的時機。令人驚奇的是,Python最基本的內容之一,函數的參數和引用,是最大的錯誤源之一,有時候對于有經驗的程序員也一樣。我建議抽時間學習一下引用和多態。
相關閱讀:

  •     OOP concepts in Python 2.x – Part 2
  •     Python 3 OOP Part 1 – Objects and types
  •     Digging up Django class-based views – 2
  •     Python Generators – From Iterators to Cooperative Multitasking – 2
  •     OOP concepts in Python 2.x – Part 1

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 国产综合久久久 | 国产成人精品免费 | 色毛片 | 玖玖玖视频 | 午夜视频在线 | 91精品综合久久久久久五月天 | 国产在线视频一区二区 | 国产高清av在线播放 | 国产欧美日韩一级大片 | 午夜精品一区二区三区在线视频 | 久久久精品网站 | 欧美 日韩 综合 | 精品国产一区三区 | 日韩成人一区 | 五月天一区二区 | 久久久久久高清 | 精品视频二区 | 天天插天天狠 | 久久综合成人精品亚洲另类欧美 | 色九九 | a毛片国产 | 精品久久99| 欧美日韩在线免费 | 一性一交一色生活片 | 欧美一级久久久 | 精品美女久久久 | www.99re | 欧美激情区| 视频一区二区三区中文字幕 | 特黄特黄aaaa级毛片免费看 | 山岸逢花在线观看无删减 | 国产男女做爰免费网站 | 国产一区在线不卡 | 麻豆国产一区二区三区 | 欧美日韩在线电影 | 日韩一区二区中文 | 毛片特级| 99国产精品99久久久久久 | 国产精品成人一区二区三区夜夜夜 | 久久66| 91视频大全 |