Làm thế nào để kiểm tra nếu một đối tượng là một danh sách hoặc tuple (nhưng không phải là chuỗi)?


443

Đây là những gì tôi thường làm để xác định rằng đầu vào là list/ tuple- nhưng không phải là a str. Bởi vì nhiều lần tôi tình cờ phát hiện ra các lỗi trong đó một hàm vượt qua một strđối tượng do nhầm lẫn và hàm mục tiêu không for x in lstcho rằng đó lstthực sự là một listhoặc tuple.

assert isinstance(lst, (list, tuple))

Câu hỏi của tôi là: có cách nào tốt hơn để đạt được điều này?


9
loại (lst) là danh sách?
jackalope

1
không phải là isinstance (khóa, six.opes_types)
wyx

Câu trả lời:


332

Chỉ trong python 2 (không phải python 3):

assert not isinstance(lst, basestring)

Thực sự là những gì bạn muốn, nếu không, bạn sẽ bỏ lỡ rất nhiều thứ hoạt động như danh sách, nhưng không phải là lớp con của listhoặc tuple.


91
Vâng, đây là câu trả lời chính xác. Trong Python 3, basestringđã biến mất và bạn chỉ cần kiểm tra isinstance(lst, str).
steveha

5
Có rất nhiều thứ bạn có thể lặp như danh sách, ví dụ: setbiểu thức trình tạo, trình lặp. Có những thứ kỳ lạ như mmap, những thứ ít kỳ lạ hơn giống như arrayhoạt động giống như danh sách, và có lẽ tôi đã quên rất nhiều.
Nick Craig-Wood

50
Điều đáng chú ý là điều này không đảm bảo có thể lstlặp lại được, trong khi bản gốc đã làm (ví dụ: một int sẽ vượt qua kiểm tra này)
Peter Gibson

11
@PeterGibson - Một sự kết hợp của cả hai sẽ cung cấp một kiểm tra hợp lệ, hạn chế hơn và đảm bảo 1) lst là lặp lại, 2) lst không phải là một chuỗi. assert isinstance(lst, (list, tuple)) and assert not isinstance(lst, basestring)
strongMA

4
Chà, giải pháp này chỉ kiểm tra các loại dẫn xuất chuỗi, nhưng còn số nguyên, nhân đôi hoặc bất kỳ loại không lặp nào khác thì sao?
Eneko Alonso

171

Hãy nhớ rằng trong Python chúng tôi muốn sử dụng "gõ vịt". Vì vậy, bất cứ điều gì hoạt động như một danh sách có thể được coi là một danh sách. Vì vậy, đừng kiểm tra loại danh sách, hãy xem nó có hoạt động như một danh sách không.

Nhưng các chuỗi cũng hoạt động như một danh sách và thường đó không phải là điều chúng ta muốn. Có những lúc nó thậm chí là một vấn đề! Vì vậy, kiểm tra rõ ràng cho một chuỗi, nhưng sau đó sử dụng gõ vịt.

Đây là một chức năng tôi viết cho vui. Đây là phiên bản đặc biệt repr()in bất kỳ chuỗi nào trong ngoặc vuông ('<', '>').

def srepr(arg):
    if isinstance(arg, basestring): # Python 3: isinstance(arg, str)
        return repr(arg)
    try:
        return '<' + ", ".join(srepr(x) for x in arg) + '>'
    except TypeError: # catch when for loop fails
        return repr(arg) # not a sequence so just return repr

Đây là sạch sẽ và thanh lịch, tổng thể. Nhưng những gì isinstance()kiểm tra làm ở đó? Đó là một loại hack. Nhưng nó là điều cần thiết.

Hàm này tự gọi đệ quy trên bất cứ thứ gì hoạt động như một danh sách. Nếu chúng ta không xử lý chuỗi đặc biệt, thì nó sẽ được coi như một danh sách và chia ra một ký tự một lần. Nhưng sau đó, cuộc gọi đệ quy sẽ cố gắng coi mỗi nhân vật là một danh sách - và nó sẽ hoạt động! Ngay cả một chuỗi ký tự cũng hoạt động như một danh sách! Hàm sẽ tiếp tục gọi chính nó một cách đệ quy cho đến khi stack stack.

Các hàm như thế này, phụ thuộc vào từng cuộc gọi đệ quy phá vỡ công việc cần thực hiện, phải thực hiện các chuỗi trường hợp đặc biệt - bởi vì bạn không thể phá vỡ một chuỗi dưới mức của chuỗi một ký tự và thậm chí là một chuỗi chuỗi -character hoạt động như một danh sách.

Lưu ý: try/ exceptlà cách sạch nhất để thể hiện ý định của chúng tôi. Nhưng nếu mã này bằng cách nào đó rất quan trọng về thời gian, chúng tôi có thể muốn thay thế nó bằng một loại thử nghiệm nào đó để xem liệu đó argcó phải là một chuỗi hay không. Thay vì kiểm tra loại, có lẽ chúng ta nên kiểm tra các hành vi. Nếu nó có một .strip()phương thức, thì đó là một chuỗi, vì vậy đừng coi đó là một chuỗi; mặt khác, nếu nó có thể lập chỉ mục hoặc lặp lại, đó là một chuỗi:

def is_sequence(arg):
    return (not hasattr(arg, "strip") and
            hasattr(arg, "__getitem__") or
            hasattr(arg, "__iter__"))

def srepr(arg):
    if is_sequence(arg):
        return '<' + ", ".join(srepr(x) for x in arg) + '>'
    return repr(arg)

EDIT: Ban đầu tôi đã viết ở trên với một kiểm tra __getslice__()nhưng tôi nhận thấy rằng trong collectionstài liệu mô-đun, phương pháp thú vị là __getitem__(); Điều này có ý nghĩa, đó là cách bạn lập chỉ mục một đối tượng. Điều đó có vẻ cơ bản hơn __getslice__()vì vậy tôi đã thay đổi ở trên.


2
@stantonk, cảm ơn bạn đã nói như vậy, nhưng tôi nghĩ rằng đã có một câu trả lời được chấp nhận khi tôi viết bài này và tôi không thực sự mong đợi câu trả lời được chấp nhận sẽ được thay đổi.
steveha

@steveha: sreprlà một ý tưởng rất thú vị. Nhưng tôi giữ một ý kiến ​​khác với bạn về việc nó có cần phải đặc biệt hay không str. Vâng, strcho đến nay là lặp đi lặp lại rõ ràng và phổ biến nhất sẽ gây ra một đệ quy vô hạn trong srepr. Nhưng tôi có thể dễ dàng tưởng tượng các iterables do người dùng định nghĩa hoạt động theo cùng một cách (có hoặc không có lý do chính đáng). Thay vì trường hợp đặc biệt str, chúng ta nên thừa nhận rằng phương pháp này có thể đi vào đệ quy vô hạn và đồng ý với một số cách xử lý. Tôi sẽ gửi đề nghị của tôi trong một câu trả lời.
tối đa

1
Tôi nghĩ rằng đây chắc chắn là con đường đúng. Tuy nhiên, để xử lý trường hợp đặc biệt (của chuỗi trong kịch bản này), tôi nghĩ rằng chúng ta tốt hơn nên đặt câu hỏi "làm thế nào một con người sẽ nói sự khác biệt?" Ví dụ, hãy xem xét một đối số chức năng có thể là một danh sách các địa chỉ email hoặc một địa chỉ email duy nhất (hãy nhớ rằng một chuỗi chỉ đơn giản là một danh sách các ký tự). Đưa biến này cho một con người. Làm thế nào có thể nói đó là gì? Cách dễ nhất tôi có thể nghĩ đến là xem có bao nhiêu nhân vật trong mỗi mục của danh sách. Nếu nó lớn hơn 1, đối số chắc chắn không thể là danh sách các ký tự.
Josh

1
Tôi đã nghĩ về điều này một chút, và thảo luận với một vài người khác, và tôi nghĩ srepr()nó vẫn ổn. Chúng ta cần một hàm đệ quy để xử lý những thứ như một danh sách được lồng trong một danh sách khác; nhưng đối với các chuỗi, chúng tôi muốn có chúng được in như "foo"<'f', 'o', 'o'>. Vì vậy, một kiểm tra rõ ràng cho một chuỗi có ý nghĩa tốt ở đây. Ngoài ra, thực sự không có bất kỳ ví dụ nào khác về các loại dữ liệu trong đó việc lặp lại luôn trả về một lần lặp và đệ quy sẽ luôn gây ra lỗi tràn ngăn xếp, vì vậy chúng tôi không cần một thuộc tính đặc biệt để kiểm tra điều này ("Tính thực tế đánh bại độ tinh khiết").
steveha

1
Điều này không hoạt động trong Python 3, bởi vì các chuỗi có một __iter__()phương thức trong Python 3, nhưng không phải trong Python 2. Bạn đang thiếu dấu ngoặc đơn is_sequence(), nên đọc:return (not hasattr(arg, "strip") and (hasattr(arg, "__getitem__") or hasattr(arg, "__iter__")))
MiniQuark

124
H = "Hello"

if type(H) is list or type(H) is tuple:
    ## Do Something.
else
    ## Do Something.

11
Ngoại trừ nó không sử dụng thành ngữ Python gõ vịt như các nhà bình luận khác đã chỉ ra (mặc dù nó trả lời trực tiếp và sạch sẽ câu hỏi).
Soren Bjornstad

7
Câu trả lời này ít được chấp nhận hơn các câu hỏi khác vì nó không cho phép gõ vịt và cũng không thành công trong trường hợp đơn giản là phân lớp (một ví dụ điển hình là lớp có tên).
Philippe Gauthier

11
"Không cho phép gõ vịt" không làm cho câu trả lời ít được chấp nhận hơn, đặc biệt là câu trả lời này thực sự trả lời câu hỏi.
Petri

4
Tôi đã đưa ra câu trả lời này, nhưng if isinstance( H, (list, tuple) ): ...ngắn hơn và rõ ràng hơn.
shahar_m

2
Cú pháp thay thế:if type(H) in [list, tuple]:
Štefan Schindler

77

Đối với Python 3:

import collections.abc

if isinstance(obj, collections.abc.Sequence) and not isinstance(obj, str):
    print("obj is a sequence (list, tuple, etc) but not a string")

Đã thay đổi trong phiên bản 3.3: Đã chuyển Bộ sưu tập Các lớp cơ sở trừu tượng sang mô đun bộ sưu tập.abc. Để tương thích ngược, chúng cũng sẽ tiếp tục hiển thị trong mô-đun này cho đến phiên bản 3.8 nơi nó sẽ ngừng hoạt động.

Đối với Python 2:

import collections

if isinstance(obj, collections.Sequence) and not isinstance(obj, basestring):
    print "obj is a sequence (list, tuple, etc) but not a string or unicode"

5
Ồ Điều này hoạt động thực sự độc đáo, và cô đọng hơn nhiều so với bất kỳ câu trả lời đúng nào khác. Tôi không biết rằng các loại tích hợp thừa hưởng từ collections.Sequencenhưng tôi đã thử nghiệm nó và tôi thấy rằng chúng làm được. Cũng vậy xrange. Thậm chí tốt hơn, thử nghiệm này loại trừ dict, trong đó có cả __getitem____iter__.
Neil Mayhew

Bất cứ ý tưởng tại sao kết quả của inspect.getmro(list)không bao gồm Sequencemặc dù? Làm thế nào chúng ta phải tìm ra những gì chúng ta có thể làm với isinstancekhi getmrokhông hiển thị mọi thứ?
Steve Jorgensen

Thứ tự độ phân giải phương thức @SteveJorgensen định nghĩa đường dẫn tìm kiếm lớp được Python sử dụng để tìm kiếm phương thức phù hợp để sử dụng trong các lớp. Sequencelà một lớp trừu tượng.
suzanshakya

3
Trong Python3, bạn có thể thay thế isinstance (obj, basestring) bằng isinstance (obj, str) và điều đó sẽ hoạt động.
Adrian Keister

2
trong Python 3 bạn cần và không phải là isinstance (obj, byte) ... nếu bạn muốn có một danh sách các thứ, và không chỉ liệt kê các byte ...
Erik Aronesty

35

Python với hương vị PHP:

def is_array(var):
    return isinstance(var, (list, tuple))

6
Python là một ngôn ngữ gõ vịt, vì vậy bạn thực sự nên kiểm tra xem var có thuộc tính không __getitem__. Ngoài ra tên là sai lệch, vì cũng có mô-đun mảng. Và var cũng có thể là một numpy.ndarray hoặc bất kỳ loại nào khác, có __getitem__. Xem stackoverflow.com/a/1835259/470560 để có câu trả lời đúng.
peterhil

9
@peterhil strcũng có __getitem__do đó kiểm tra của bạn không loại trừstr
erikbwork

9
Một dict cũng vậy. Kiểm tra __getitem__là lời khuyên tồi ở đây.
Petri

10

Nói chung, thực tế là một hàm lặp trên một đối tượng hoạt động trên các chuỗi cũng như các bộ dữ liệu và danh sách là nhiều tính năng hơn lỗi. Bạn chắc chắn có thể sử dụng isinstancehoặc gõ vịt để kiểm tra một đối số, nhưng tại sao bạn nên?

Nghe có vẻ giống như một câu hỏi tu từ, nhưng không phải vậy. Câu trả lời cho "tại sao tôi nên kiểm tra loại đối số?" có lẽ sẽ đề xuất một giải pháp cho vấn đề thực sự chứ không phải vấn đề nhận thức. Tại sao nó là một lỗi khi một chuỗi được truyền cho hàm? Ngoài ra: nếu đó là một lỗi khi một chuỗi được truyền cho hàm này, thì đó cũng là một lỗi nếu một số lần lặp không phải danh sách / tuple khác được truyền cho nó? Tại sao, hoặc tại sao không?

Tôi nghĩ rằng câu trả lời phổ biến nhất cho câu hỏi có thể là các nhà phát triển viết ra f("abc")đang mong đợi chức năng này hoạt động như thể họ đã viết f(["abc"]). Có lẽ có những trường hợp có ý nghĩa hơn để bảo vệ các nhà phát triển khỏi chính họ hơn là hỗ trợ trường hợp sử dụng lặp lại qua các ký tự trong một chuỗi. Nhưng tôi nghĩ lâu và khó về nó trước.


16
"Nhưng tôi sẽ nghĩ lâu và chăm chỉ về nó trước." Tôi sẽ không. Nếu hàm được coi là hàm list-y, thì có, nó nên xử lý chúng giống nhau (nghĩa là đưa ra một danh sách, nhổ nó ra phía sau, những thứ như vậy). Tuy nhiên, nếu đó là một hàm trong đó một trong các đối số có thể là một chuỗi hoặc một danh sách các chuỗi (là một nhu cầu khá phổ biến) thì buộc nhà phát triển sử dụng hàm đó phải luôn nhập tham số của chúng bên trong một mảng có vẻ hơi nhiều . Ngoài ra, hãy suy nghĩ về cách bạn xử lý, giả sử, nhập liệu JSON. Bạn chắc chắn muốn xử lý một danh sách các đối tượng khác với một chuỗi.
Jordan Reiter

8

Hãy thử điều này để dễ đọc và thực hành tốt nhất:

Python2

import types
if isinstance(lst, types.ListType) or isinstance(lst, types.TupleType):
    # Do something

Python3

import typing
if isinstance(lst, typing.List) or isinstance(lst, typing.Tuple):
    # Do something

Hy vọng nó giúp.


Python 3.6.5:AttributeError: module 'types' has no attribute 'ListType'
Juha Untinen

1
Trong Python 3, đó là: from typing import List-> isinstance([1, 2, 3], List= Trueisinstance("asd", List)= False
Juha Untinen

5

Đối strtượng không có __iter__thuộc tính

>>> hasattr('', '__iter__')
False 

để bạn có thể kiểm tra

assert hasattr(x, '__iter__')

và điều này cũng sẽ nâng cao một tốt đẹp AssertionError cho bất kỳ đối tượng không lặp lại nào khác.

Chỉnh sửa: Như Tim đề cập trong các bình luận, điều này sẽ chỉ hoạt động trong python 2.x, không phải 3.x


8
Cẩn thận: Trong Python 3 hasattr('','__iter__')trả về True. Và tất nhiên điều đó có ý nghĩa vì bạn có thể lặp qua một chuỗi.
Tim Pietzcker

1
Có thật không? Tôi không biết điều đó. Tôi luôn nghĩ rằng đây là một giải pháp tao nhã cho vấn đề này, ồ tốt.
Moe

1
Thử nghiệm này không hoạt động trên pyodbc.Row. Nó không có iter __ () nhưng ít nhiều nó hoạt động giống như một danh sách (thậm chí nó còn định nghĩa "__setitem "). Bạn có thể lặp lại các yếu tố của nó tốt. Hàm len () hoạt động và bạn có thể lập chỉ mục các phần tử của nó. Tôi đang vật lộn để tìm ra sự kết hợp đúng bắt tất cả các loại danh sách, nhưng loại trừ các chuỗi. Tôi nghĩ rằng tôi sẽ giải quyết một kiểm tra về " getitem " và " len " trong khi loại trừ rõ ràng cơ sở.
haridsv

5

Điều này không nhằm trực tiếp trả lời OP, nhưng tôi muốn chia sẻ một số ý tưởng liên quan.

Tôi đã rất quan tâm đến câu trả lời @steveha ở trên, dường như đưa ra một ví dụ về việc gõ vịt dường như bị phá vỡ. Tuy nhiên, trên suy nghĩ thứ hai, ví dụ của ông cho thấy rằng gõ vịt rất khó tuân thủ, nhưng nó không cho thấy rằng nó strxứng đáng được xử lý đặc biệt.

strXét sreprcho cùng , một loại không (ví dụ: loại do người dùng xác định duy trì một số cấu trúc đệ quy phức tạp) có thể khiến hàm @steveha gây ra đệ quy vô hạn. Mặc dù điều này được thừa nhận là khá khó xảy ra, chúng tôi không thể bỏ qua khả năng này. Do đó, chứ không phải là chuyên vỏ strtrong srepr, chúng ta nên làm rõ những gì chúng tôi muốn sreprlàm khi một kết quả đệ quy vô hạn.

Có vẻ như một cách tiếp cận hợp lý là chỉ đơn giản là phá vỡ đệ quy trong sreprthời điểm này list(arg) == [arg]. Trên thực tế, điều này sẽ giải quyết hoàn toàn vấn đề với str, mà không có bất kỳ isinstance.

Tuy nhiên, một cấu trúc đệ quy thực sự phức tạp có thể gây ra một vòng lặp vô hạn, nơi list(arg) == [arg]không bao giờ xảy ra. Do đó, mặc dù kiểm tra trên là hữu ích, nhưng nó không đủ. Chúng ta cần một cái gì đó như một giới hạn cứng về độ sâu đệ quy.

Quan điểm của tôi là nếu bạn có kế hoạch xử lý các loại đối số tùy ý, việc xử lý strthông qua gõ vịt là rất xa, dễ dàng hơn nhiều so với xử lý các loại chung hơn mà bạn có thể (về mặt lý thuyết) gặp phải. Vì vậy, nếu bạn cảm thấy cần loại trừ các strthể hiện, thay vào đó, bạn nên yêu cầu đối số là một thể hiện của một trong số ít loại mà bạn chỉ định rõ ràng.


1
Hmm, tôi thích cách bạn nghĩ. Tôi nghĩ rằng bạn không thể tranh luận rằng mã của tôi là thực tế: có chính xác một trường hợp phổ biến str, đó là mã trường hợp đặc biệt xử lý. Nhưng có lẽ nên có một thuộc tính tiêu chuẩn mới mà mã có thể kiểm tra, .__atomic__giả sử, đó là tín hiệu cho thấy một cái gì đó không thể bị phá vỡ thêm nữa. Có lẽ đã quá muộn để thêm một hàm dựng sẵn khác atomic()vào Python, nhưng có lẽ chúng ta có thể thêm from collections import atomichoặc một cái gì đó.
steveha

5

Tôi tìm thấy một hàm như vậy có tên is_ resultence trong tenorflow .

def is_sequence(seq):
  """Returns a true if its input is a collections.Sequence (except strings).
  Args:
    seq: an input sequence.
  Returns:
    True if the sequence is a not a string and is a collections.Sequence.
  """
  return (isinstance(seq, collections.Sequence)
and not isinstance(seq, six.string_types))

Và tôi đã xác minh rằng nó đáp ứng nhu cầu của bạn.


2

Tôi làm điều này trong tủ thử nghiệm của tôi.

def assertIsIterable(self, item):
    #add types here you don't want to mistake as iterables
    if isinstance(item, basestring): 
        raise AssertionError("type %s is not iterable" % type(item))

    #Fake an iteration.
    try:
        for x in item:
            break;
    except TypeError:
        raise AssertionError("type %s is not iterable" % type(item))

Chưa được kiểm tra về máy phát điện, tôi nghĩ bạn bị bỏ lại ở 'năng suất' tiếp theo nếu được đưa vào máy phát điện, điều này có thể làm hỏng mọi thứ ở hạ lưu. Nhưng sau đó, một lần nữa, đây là một 'bất hạnh'


2

Theo cách "gõ vịt", làm thế nào về

try:
    lst = lst + []
except TypeError:
    #it's not a list

hoặc là

try:
    lst = lst + ()
except TypeError:
    #it's not a tuple

tương ứng. Điều này tránh isinstance/hasattr công cụ introspection.

Bạn cũng có thể kiểm tra ngược lại:

try:
    lst = lst + ''
except TypeError:
    #it's not (base)string

Tất cả các biến thể không thực sự thay đổi nội dung của biến, nhưng ngụ ý việc gán lại. Tôi không chắc liệu điều này có thể là không mong muốn trong một số trường hợp.

Thật thú vị, với nhiệm vụ "tại chỗ" sẽ +=không TypeErrorđược nêu ra trong mọi trường hợp nếu lstlà một danh sách (không phải là một tuple ). Đó là lý do tại sao bài tập được thực hiện theo cách này. Có lẽ ai đó có thể làm sáng tỏ tại sao lại như vậy.


1

cách đơn giản nhất ... sử dụng anyisinstance

>>> console_routers = 'x'
>>> any([isinstance(console_routers, list), isinstance(console_routers, tuple)])
False
>>>
>>> console_routers = ('x',)
>>> any([isinstance(console_routers, list), isinstance(console_routers, tuple)])
True
>>> console_routers = list('x',)
>>> any([isinstance(console_routers, list), isinstance(console_routers, tuple)])
True

1

Một phiên bản khác của gõ vịt để giúp phân biệt các đối tượng giống như chuỗi với các đối tượng giống như chuỗi khác.

Biểu diễn chuỗi của các đối tượng giống như chuỗi là chính chuỗi, vì vậy bạn có thể kiểm tra xem bạn có nhận được một đối tượng bằng nhau từ hàm strtạo không:

# If a string was passed, convert it to a single-element sequence
if var == str(var):
    my_list = [var]

# All other iterables
else: 
    my_list = list(var)

Điều này sẽ làm việc cho tất cả các đối tượng tương thích với strvà cho tất cả các loại đối tượng lặp lại.


0

Python 3 có cái này:

from typing import List

def isit(value):
    return isinstance(value, List)

isit([1, 2, 3])  # True
isit("test")  # False
isit({"Hello": "Mars"})  # False
isit((1, 2))  # False

Vì vậy, để kiểm tra cả Danh sách và Tuples, đó sẽ là:

from typing import List, Tuple

def isit(value):
    return isinstance(value, List) or isinstance(value, Tuple)

0
assert (type(lst) == list) | (type(lst) == tuple), "Not a valid lst type, cannot be string"

2
Đây có phải là một cách ổn để làm điều này?
ersh

1
Chào mừng đến với SO. Một lời giải thích tại sao mã này trả lời câu hỏi sẽ hữu ích.
Nick

Tất nhiên, tôi sử dụng các phương thức tương tự như thế này vì đường ống được coi là một hoặc do đó bạn đang khẳng định rằng loại đó phải là một danh sách hoặc loại tuple xuất ra lỗi thông báo tùy chỉnh để xử lý lỗi. Tôi tin rằng nó trả lời câu hỏi, nhưng tôi tò mò như thể đó là một cách hiệu quả để làm điều này vì tôi vẫn đang cố gắng để có được cách viết mã được tối ưu hóa nhất. Tuy nhiên, tôi không chắc chắn nếu mã này bỏ lỡ những thứ có thể hoạt động như danh sách / bộ dữ liệu nhưng không phải là lớp con của một trong hai, như cách câu trả lời được chấp nhận giải quyết khả năng đó. Cảm ơn!
ersh

-1

Chỉ cần làm điều này

if type(lst) in (list, tuple):
    # Do stuff

5
isinstance (lst, (list, tuple))
Davi Lima

@DaviLima OK, đó là một cách khác. Nhưng loại () được khuyến nghị cho các loại được xây dựng và đẳng cấp cho các Lớp.
ATOzTOA

-1

trong trăn> 3,6

import collections
isinstance(set(),collections.abc.Container)
True
isinstance([],collections.abc.Container)
True
isinstance({},collections.abc.Container)
True
isinstance((),collections.abc.Container)
True
isinstance(str,collections.abc.Container)
False

2
Trong lần kiểm tra cuối, bạn sử dụng một loại str, không phải là một chuỗi. Hãy thử isinstance('my_string', collections.abc.Container)và bạn sẽ thấy rằng nó sẽ trở lại True. Điều này là do abc.Containercung cấp __contains__phương thức và tất nhiên các chuỗi có nó.
Georgy

-6

Tôi có xu hướng làm điều này (nếu tôi thực sự, thực sự phải làm):

for i in some_var:
   if type(i) == type(list()):
       #do something with a list
   elif type(i) == type(tuple()):
       #do something with a tuple
   elif type(i) == type(str()):
       #here's your string

5
Bạn gần như không bao giờ nên làm điều này. Điều gì xảy ra nếu tôi some_varlà một thể hiện của một lớp là một lớp con của list()? Mã của bạn sẽ không biết phải làm gì với nó, mặc dù nó sẽ hoạt động hoàn hảo theo mã "làm điều gì đó với danh sách". Và bạn hiếm khi cần quan tâm đến sự khác biệt giữa danh sách và bộ dữ liệu. Xin lỗi, -1.
steveha

1
Không cần phải viết type(tuple())- tuplesẽ làm. Tương tự cho danh sách. Ngoài ra, cả hai strunicodemở rộng basestring, đó là loại chuỗi thực, vì vậy bạn muốn kiểm tra thay thế.
đối xử tốt với các mod của bạn vào

@DrBloodmoney: Downvote tình cờ. Vui lòng (tầm thường) chỉnh sửa câu trả lời của bạn để cho phép tôi xóa downvote.
SabreWolfy

Đối với tôi, sự bình đẳng dường như không phải là một sự so sánh có ý nghĩa. Tôi muốn kiểm tra danh tính thay thế : type(i) is list. Ngoài ra, type(list())chỉ là listchính nó ... Cuối cùng, điều này không hoạt động một cách duyên dáng với các lớp con. Nếu itrên thực tế và OrderedDict, hoặc một loại tên được đặt tên nào đó, mã này sẽ coi là một chuỗi.
bukzor
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.