6
一段時間以來,Python已經有Abstract Base Classes(建議orignally在PEP 3119中),尤其是對於容器類型,可以更輕鬆地編寫在整個自定義類型。例如,如何使用Python 3的標準庫測試不像字符串的序列
from collections.abc import Sequence, Set
if isinstance(x, Sequence):
# Handle lists, tuples, or custom objects that behave like lists
elif isinstance(x, Set):
# Handle anything that behaves like a set
一個多數民衆贊成我絆倒了幾次「陷阱」的是str
,bytes
和bytearray
都被認爲是Sequence
S,除了更爲明顯名單狀物體:
from collections.abc import ByteString, Sequence
s = 'hello'
b = b'hello'
ba = bytearray(b'hello')
lst = [0, 1, 2]
t = (0, 1, 2)
islistlike = lambda x: isinstance(x, Sequence)
list(map(islistlike, [s, b, ba, lst, t])) # -> [True, True, True, True, True]
這當然有意義:通常這三種類型的行爲就像列表或字符元組(或字節)。但是,這似乎是一個相當常見的用例,請問這個對象是x
既是列表式的又不是字符串式的?解決方法是直截了當:
islistlike = lambda x: isinstance(x, Sequence) and not isinstance(x, (str, ByteString))
list(map(islistlike, [s, b, ba, lst, t])) # -> [False, False, False, True, True]
但這似乎這將是一個足夠常見的模式,我不知道如果我錯過在標準庫的東西。
- 是否有Python的標準庫中的任何
abc
這樣islistlike = lambda x: isinstance(x, abc)
會像上面的最後一個例子? - 圍繞
Sequence
vs字符串像容器有什麼設計討論嗎? (我還沒有找到標準庫的文檔或PEP 3119在與此相關的任何東西)
1.據我所知。 2.正如你注意到的那樣,*「string-like containers」* *是單個字符串/字節的序列('ByteString'繼承'Sequence',even),所以*「vs」*並不真正使感。在許多情況下,一個字符串被認爲是一個函數或方法的一個完全有效的參數,所以你必須在不是這種情況時纔是明確的。 – jonrsharpe
@jonrsharpe感謝您的評論!我認爲「* vs *」可能是合適的,取決於具體情況。通常,我將字符串(字節等)看作單個原子數據點,我想知道,我是在處理類似字符串項目的列表狀容器,還是我正在處理單個字符串類型項目。這裏出現的一個地方是使用遞歸函數來扁平化一個嵌套的字典,例如 - 在您想要在項目類型上分派的遞歸函數內。 – DGrady