自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Python中有趣的Ellipsis對(duì)象

開(kāi)發(fā) 后端
在你輸入了三個(gè)點(diǎn)之后,Python 解釋器非但不會(huì)報(bào)錯(cuò),反而還會(huì)返回給你「Ellipsis」這么一個(gè)信息。那么這個(gè)有趣的東西是什么呢?來(lái)看一下吧。

[[335494]]

 什么是Ellipsis

在 Python 中你可能有時(shí)候會(huì)看到一個(gè)奇怪的用法,就像是這樣: 

  1. >>> ...  
  2. Ellipsis 

在你輸入了三個(gè)點(diǎn)之后,Python 解釋器非但不會(huì)報(bào)錯(cuò),反而還會(huì)返回給你「Ellipsis」這么一個(gè)信息。那么這個(gè)有趣的東西是什么呢?

查閱 Python 官方文檔后可以看到,它是一個(gè)**「內(nèi)置常量」**(Built-in Constant)。經(jīng)常用于對(duì)用戶自定義的容器數(shù)據(jù)類(lèi)型進(jìn)行切片用法的擴(kuò)展。

這也就意味著它可能是會(huì)作為一個(gè)「小眾且另類(lèi)」的語(yǔ)法糖來(lái)使用,但如果你用于 Python 中的容器數(shù)據(jù)類(lèi)型(比如列表)進(jìn)行切片索引時(shí),可能會(huì)引發(fā)錯(cuò)誤: 

  1. >>> nums = list(range(10))  
  2. >>> nums  
  3. [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]  
  4. >>> nums[...]  
  5. Traceback (most recent call last):  
  6.   File "<stdin>", line 1, in <module>  
  7. TypeError: list indices must be integers or slices, not ellipsis 

除此之外,如果你使用的是 Python 2 的解釋器,那么壓根就不支持 Ellipsis 的用法,從一開(kāi)始輸入時(shí)就報(bào)錯(cuò): 

  1. $ python2  
  2. WARNING: Python 2.7 is not recommended.   
  3. This version is included in macOS for compatibility with legacy software.   
  4. Future versions of macOS will not include Python 2.7.   
  5. Instead, it is recommended that you transition to using 'python3' from within Terminal.  
  6. Python 2.7.16 (default, Nov  9 2019, 05:55:08)   
  7. [GCC 4.2.1 Compatible Apple LLVM 11.0.0 (clang-1100.0.32.4) (-macos10.15-objc-s on darwin  
  8. Type "help", "copyright", "credits" or "license" for more information.  
  9. >>> ...  
  10.   File "<stdin>", line 1  
  11.     ...  
  12.     ^  
  13. SyntaxError: invalid syntax 

雖然說(shuō)在列表中使用 Ellipsis 會(huì)報(bào)錯(cuò),但是碰到這種情況你會(huì)發(fā)現(xiàn)解釋器返回給你的是這樣的東西: 

  1. >>> nums = [1,2,3]  
  2. >>> nums  
  3. [1, 2, 3]  
  4. >>> nums[1] = nums  
  5. >>> nums  
  6. [1, [...], 3] 

可以看到,這里我們將 nums 中的第二個(gè)元素替換成自身,就會(huì)形成不斷地遞歸嵌套賦值,而解釋器最后直接給出了頭尾兩個(gè)元素之外,其他全部元素都會(huì)被 ... 所囊括在內(nèi)。

根據(jù) Python 官方的另一處文檔,Ellipsis 本身也不支持任何操作,僅僅只是一個(gè)單例對(duì)象(Singleton)

誰(shuí)能想到,Guido van Rossum 這么一位被人稱為「仁慈的獨(dú)裁者」的 Python 之父采納 Ellipsis 的原因竟然是因?yàn)椋河腥苏J(rèn)為三個(gè)省略號(hào)的寫(xiě)法可愛(ài)。(原文為:「Some folks thought it would be cute to be able to write incomplete code like this」)

應(yīng)用

要說(shuō)這個(gè)看起來(lái)「雞肋」的 Ellipsis 類(lèi)型對(duì)象沒(méi)有用,這個(gè)說(shuō)法似乎也不正確。因?yàn)樗鳛橐环N奇怪的語(yǔ)法糖也被應(yīng)用到了某些地方。

Numpy 中的切片

雖然官方說(shuō) Ellipsis 主要用于用戶自定義容器類(lèi)型的切片操作,但是在我搜索了許久之后發(fā)現(xiàn)用 Ellipsis 來(lái)實(shí)現(xiàn)所謂的切片操作的貌似只有 Numpy。

使用 Python 做數(shù)據(jù)分析、挖掘或機(jī)器學(xué)習(xí)相關(guān)的朋友一定對(duì) Numpy 高性能的科學(xué)計(jì)算庫(kù)并不陌生。在 Numpy 中我們真正的使用 Ellipsis 來(lái)進(jìn)行切片索引: 

  1. >>> import numpy as np  
  2. >>> arr = np.arange(9).reshape((3,3))  
  3. >>> arr 
  4.  array([[0, 1, 2],  
  5.        [3, 4, 5],  
  6.        [6, 7, 8]]) 

需要注意的是,Ellipsis 主要是對(duì)二維以上的數(shù)組才起作用: 

  1. >>> arr[...,1:2]  
  2. array([[1],  
  3.        [4],  
  4.        [7]])  
  5. >>> arr[2, ...]  
  6. array([6, 7, 8]) 

從結(jié)果中我們看到,Ellipsis 三個(gè)省略號(hào)的寫(xiě)法其實(shí)就等價(jià)于 arr[:, 1:2] 冒號(hào)的寫(xiě)法。但是在使用過(guò)程中 Ellipsis 只能出現(xiàn)一次: 

  1. >>> ndarr = np.arange(24).reshape((2,3,4))  
  2. >>> ndarr  
  3. array([[[ 0,  1,  2,  3],  
  4.         [ 4,  5,  6,  7],  
  5.         [ 8,  9, 10, 11]],  
  6.        [[12, 13, 14, 15],  
  7.         [16, 17, 18, 19],  
  8.         [20, 21, 22, 23]]])  
  9. >>> ndarr[:, :, :]  
  10. array([[[ 0,  1,  2,  3],  
  11.         [ 4,  5,  6,  7],  
  12.         [ 8,  9, 10, 11]],  
  13.        [[12, 13, 14, 15],  
  14.         [16, 17, 18, 19],  
  15.         [20, 21, 22, 23]]])  
  16. >>> ndarr[..., ..., ...]  
  17. Traceback (most recent call last):  
  18.   File "<stdin>", line 1, in <module>  
  19. IndexError: an index can only have a single ellipsis ('...') 

Ellipsis 在 Numpy 中出現(xiàn)的意義在于,當(dāng)你的數(shù)組是高維的數(shù)組時(shí),那么可以直接使用它來(lái)作為選取其他維度的等價(jià)寫(xiě)法,以下例子來(lái)源于 Numpy 官方文檔: 

  1. >>> z = np.arange(81).reshape(3,3,3,3)  
  2. >>> z[1,...,2] # 等價(jià)于 z[1, :,:, 2]  
  3. array([[29, 32, 35],  
  4.        [38, 41, 44],  
  5.        [47, 50, 53]]) 

Type Hint 類(lèi)型注解

自從 PEP 484 之后,Python 解釋器開(kāi)始支持類(lèi)型注解。所謂的類(lèi)型注解無(wú)非就是在 Python 實(shí)際代碼中能像注釋那樣對(duì)當(dāng)中的一些參數(shù)或返回值添加類(lèi)型注釋,就像是這樣: 

  1. def add(x: int, y: int) -> int:  
  2.     return x + y 

如果你是有使用過(guò) Java 或者 Go 這類(lèi)對(duì)類(lèi)型注解要求較為嚴(yán)格的編譯型語(yǔ)言,那么相信對(duì)此并不陌生,無(wú)論是變量還是方法,都要寫(xiě)上對(duì)應(yīng)的類(lèi)型以防編譯報(bào)錯(cuò);但即便沒(méi)有接觸過(guò)這類(lèi)編譯型語(yǔ)言也不要緊,將其理解為注釋即可,這樣的注釋是能被編輯器或 IDE 所支持,在你要查看函數(shù)定義或文檔時(shí)會(huì)給予提示。

但是 Type Hint 僅僅只是一種「協(xié)定」,告訴別人你的方法里參數(shù)是如何、最后返回的是什么僅此而已,無(wú)論是加與不加都不會(huì)影響最終代碼的效果,影響的僅僅只是代碼的可讀性罷了。

如果你的方法有多個(gè)返回值,我們不可能對(duì)每個(gè)返回值的類(lèi)型都寫(xiě)上注解,因此這時(shí) Ellipsis 對(duì)象就派上了用場(chǎng)。根據(jù)官方文檔給出的說(shuō)明,我們完全可以像這樣來(lái)進(jìn)行類(lèi)型注解: 

  1. from typing import Tuple  
  2. def get_many_value(  
  3.     a:int, b:int, c:int,   
  4.     d:int, e:int, f:int  
  5. ) -> Tuple[int, ...]:  
  6.     return [a+b, c+d, e+f] 

這樣的寫(xiě)法本質(zhì)上就是 *args 的作用,表示同類(lèi)型的可變長(zhǎng)度元組。如果你將 Tuple 換成是 List,那么解釋器會(huì)報(bào)錯(cuò),因?yàn)?*args 在方法中的表現(xiàn)就是元組,那么作為注解的 Ellipsis 也應(yīng)如此。這可能也就說(shuō)明為什么在 Tuple 注解中不報(bào)錯(cuò)了。

FastAPI 中的必選參數(shù)

目前正流行開(kāi)來(lái)的高性能 Web 框架 FastAPI 中,也應(yīng)用了 Ellipsis。它用以表示參數(shù)是必填項(xiàng),這在 Swagger 頁(yè)面更能直觀體現(xiàn)。 

  1. # pip install fastapi  
  2. # pip install uvicorn  
  3. from fastapi import FastAPI, Query  
  4. app = FastAPI()  
  5. @app.get('/greetWithOutEllipsis')  
  6. async def greet(name: str = None):  
  7.     if name:  
  8.         return {"info": f"Welcome! {name}"}  
  9.     return {"info": f"Welcome to FastAPI!"}  
  10. @app.get('/greetWithEllipsis')  
  11. async def greet(name: str = Query(..., min_length=2)):  
  12.     if name:  
  13.         return {"info": f"Welcome! {name}"}  
  14.     return {"info": f"Welcome to FastAPI!"}  
  15. if __name__ == "__main__":  
  16.     import uvicorn  
  17.     uvicorn.run(app, port = 5000

啟動(dòng)服務(wù)之后,在瀏覽器中輸入 http://127.0.0.1:5000/docs 便能進(jìn)入到服務(wù)的 Swagger 頁(yè)面中,在上述例子中如果 name 參數(shù)并非是個(gè)必要的參數(shù)時(shí),在 Swagger 頁(yè)面中不會(huì)看到任何標(biāo)識(shí),即便我們不帶上 name 參數(shù)也能進(jìn)行請(qǐng)求: 

非必要參數(shù)

但當(dāng)我們加上了一個(gè) Query() 方法,并將其 Ellipsis 對(duì)象丟到當(dāng)中時(shí),不僅會(huì)給參數(shù)加上 required 的標(biāo)識(shí),同時(shí)還對(duì)傳入的字符串長(zhǎng)度進(jìn)行了限制。

必要參數(shù)

除了參數(shù)之外,在 FastAPI 中你還可以在請(qǐng)求體、路徑、字段等多個(gè)地方使用 Ellipsis 對(duì)象。

「?jìng)巍?pass 寫(xiě)法

Ellipsis 有時(shí)候還可以作為 pass 的一種「?jìng)巍箤?xiě)法,比如這樣: 

  1. def greet():  
  2.     ... #等價(jià)于 pass 

這其實(shí)就和 # 注釋符號(hào)與六個(gè)引號(hào)的長(zhǎng)字符串注釋類(lèi)似。但實(shí)際上僅僅只是一種取巧的方法,實(shí)際上我們可以將 ... 替換成任何值或?qū)ο?,?None、1、True 等,因?yàn)樵诜椒ㄖ胁](méi)有顯示聲明返回的對(duì)象,所以無(wú)論我們寫(xiě)什么最后的效果都是一樣的。

但使用 Ellipsis 對(duì)象來(lái)作為 pass 關(guān)鍵字的替代品從「視覺(jué)」上來(lái)說(shuō)或許還有點(diǎn)「意猶未盡」的意思。

當(dāng)然如果在你和同事協(xié)作時(shí),隨手寫(xiě)下這樣一個(gè)省略號(hào),沒(méi)準(zhǔn)隱含著你對(duì)同事 Coding 的無(wú)奈,或者是對(duì)禿頭的憂愁(逃) 

 

責(zé)任編輯:龐桂玉 來(lái)源: Python中文社區(qū)
相關(guān)推薦

2010-03-12 10:30:18

Python語(yǔ)言

2023-08-13 16:32:12

JavaScript

2021-03-15 08:15:42

ES2021語(yǔ)言開(kāi)發(fā)

2009-10-23 14:22:59

Windows 7微軟隱藏功能

2016-12-20 11:35:52

編程語(yǔ)言開(kāi)源項(xiàng)目

2014-12-09 12:35:11

人工智能機(jī)器學(xué)習(xí)開(kāi)源項(xiàng)目

2010-05-14 10:55:04

java對(duì)象序列化

2017-08-08 16:04:30

Python圖片處理文章提取器

2022-10-10 23:19:02

Python腳本語(yǔ)言工具庫(kù)

2009-04-30 16:21:37

VB.NET通用對(duì)象列表

2022-12-28 08:59:11

2020-03-29 20:27:51

Python函數(shù)開(kāi)發(fā)

2022-01-23 14:08:52

PythonPygame

2025-03-19 09:55:17

2024-10-25 08:30:55

NumPyPandasMatplotlib

2023-03-13 08:47:06

CSS數(shù)學(xué)函數(shù)

2022-08-29 14:56:56

Python腳本代碼

2014-09-19 11:17:48

面試題

2010-07-17 01:03:13

CMD Telnet

2023-07-14 22:36:42

Node.jsStorage
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)