2010-10-04 73 views
6

我想基於它可能是類似地圖的對象或類似序列的對象的事實對參數執行操作。我知道沒有任何策略對於類型檢查是100%可靠的,但我正在尋找一個可靠的解決方案。如何區分序列和映射

基於此answer,我知道如何確定某物是否是一個序列,並且在檢查該物體是否爲地圖後,我可以執行此檢查。

def ismap(arg): 
    # How to implement this? 

def isseq(arg): 
    return hasattr(arg,"__iter__") 

def operation(arg): 
    if ismap(arg): 
     # Do something with a dict-like object 
    elif isseq(arg): 
     # Do something with a sequence-like object 
    else: 
     # Do something else 

因爲一個序列可以看作一個映射,其中鍵是整數,我應該試着找到一個不是整數的鍵?或者,也許我可以看看字符串表示?要麼...?

UPDATE

我選擇SilentGhost的答案,因爲它看起來像最「正確」的,但我需要的,這裏是我結束了實施解決方案:

if hasattr(arg, 'keys') and hasattr(arg, '__getitem__'): 
    # Do something with a map 
elif hasattr(arg, '__iter__'): 
    # Do something with a sequence/iterable 
else: 
    # Do something else 

從本質上講,我不想依賴ABC,因爲有許多自定義類的行爲與序列和字典類似,但仍不能擴展python集合ABCs(請參閱@Manoj註釋)。我認爲鑰匙屬性(由刪除他/她答案的人提到)足以檢查映射。

擴展序列和映射ABC的類也可以使用該解決方案。

+0

爲什麼不嘗試一些像序列或地圖狀,並基於錯誤,您可以決定如何把它作爲。 – PyRulez 2013-10-26 23:44:20

回答

10
>>> from collections import Mapping, Sequence 
>>> isinstance('ac', Sequence) 
True 
>>> isinstance('ac', Mapping) 
False 
>>> isinstance({3:42}, Mapping) 
True 
>>> isinstance({3:42}, Sequence) 
False 

collections abstract base classes (ABCs)

+3

自定義類怎麼樣?對於例如Django的'QuerySet'?它表現得像一個序列,但是'isinstance(a_queryset,Sequence)'返回'False'。 – 2010-10-04 11:12:05

+1

@Manoj:他們可能需要修復繼承?它在什麼意義上「表現得像一個序列」? – SilentGhost 2010-10-04 11:15:07

+1

@SilentGhost:嗯。你是對的。我想如果設計師期望這樣的操作,設計師就必須開始繼承適當的類型。 – 2010-10-04 11:17:56

1

序列具有一個__add__方法,該方法實現+運算符。地圖沒有這種方法,因爲添加到地圖需要一個鍵和一個值,而+運算符只有一個右邊。

所以,你可以嘗試:

def ismap(arg): 
    return isseq(arg) and not hasattr(arg, "__add__")