Làm thế nào để tìm hiểu xem một đối tượng Python có phải là một chuỗi không?


402

Làm cách nào để kiểm tra xem một đối tượng Python có phải là một chuỗi (thông thường hay Unicode) không?


18
Cái mà Jason muốn nói đến là gõ vịt (nếu nó quẫy như vịt thì có lẽ nó là vịt). Trong Python, bạn thường "để mã của mình hoạt động" trên bất kỳ đối tượng giống như chuỗi nào mà không kiểm tra xem đó là lớp con chuỗi hay chuỗi. Để biết thêm thông tin, hãy xem: docs.python.org/glossary.html#term-duck-typing
Ben Hoyt

4
Đó là những gì tôi thích về SO. Tôi thường hỏi một câu hỏi, nó không được trả lời, mọi người nói với tôi rằng tôi không nên làm điều đó và tại sao, và tôi phát triển như một lập trình viên. =)
vật lý học

24
+1: Chỉ vì một câu trả lời hiếm khi cần thiết, không có nghĩa là câu hỏi không hợp lệ. Mặc dù, tôi nghĩ thật tuyệt khi có một sự thận trọng ở đây, tôi không nghĩ rằng nó đáng để hạ thấp câu hỏi.
Trevor

17
Đây có thể là cách sử dụng hợp pháp nhất của việc kiểm tra kiểu trong Python. Các chuỗi có thể lặp lại, do đó, phân biệt chúng với các danh sách theo bất kỳ cách nào khác là một ý tưởng tồi.
ojrac

3
Chắc chắn có những trường hợp cần phân biệt các chuỗi với các iterables khác. Ví dụ: xem mã nguồn cho PrettyPrinter trong mô-đun pprint.
saxman01

Câu trả lời:



178

Con trăn 2

Để kiểm tra xem một đối tượng ocó phải là kiểu chuỗi của một lớp con của kiểu chuỗi không:

isinstance(o, basestring)

bởi vì cả hai strunicodelà lớp con củabasestring .

Để kiểm tra xem loại ochính xác là str:

type(o) is str

Để kiểm tra xem olà một thể hiện của strhoặc bất kỳ lớp con nào của str:

isinstance(o, str)

Ở trên cũng hoạt động cho các chuỗi Unicode nếu bạn thay thế strbằngunicode .

Tuy nhiên, bạn có thể không cần phải kiểm tra loại rõ ràng. "Gõ vịt" có thể phù hợp với nhu cầu của bạn. Xem http://docs.python.org/glossary.html#term-duck-typing .

Xem thêm Cách thức kinh điển để kiểm tra loại trong python?


biến cục bộ 'str' được tham chiếu trước khi gán
john ktejik

@johnktejik python3 vs python2. Bạn cần kiểm tra basestringtrong py2.
erikbwork

170

Con trăn 3

Trong Python 3.x basestringkhông còn khả dụng nữa, như strlà kiểu chuỗi duy nhất (với ngữ nghĩa của Python 2.x's unicode).

Vì vậy, kiểm tra trong Python 3.x chỉ là:

isinstance(obj_to_test, str)

Điều này tuân theo sửa lỗi của 2to3công cụ chuyển đổi chính thức : chuyển đổi basestringsang str.


94

Con trăn 2 và 3

(tương thích chéo)

Nếu bạn muốn kiểm tra mà không liên quan đến phiên bản Python (2.x so với 3.x), hãy sử dụng six( PyPI ) và string_typesthuộc tính của nó :

import six

if isinstance(obj, six.string_types):
    print('obj is a string!')

Trong six(một mô-đun một tệp rất nhẹ), nó chỉ đơn giản là làm điều này :

import sys
PY3 = sys.version_info[0] == 3

if PY3:
    string_types = str
else:
    string_types = basestring

Ngoài ra, bạn có thể sử dụng future( PyPI ) để thậm chí giữ tên:from past.builtins import basestring
David Nemekey

1
BTW Cheat Sheet là một tài nguyên tuyệt vời để tương thích phiên bản Python.
David Nemekey

1
Điều gì về việc không sử dụng bất kỳ nhập khẩu? Đầu tiên thử basestringvà sau đó rơi trở lại str. Ví dụ:def is_string(obj): try: return isinstance(obj, basestring) # python 2 except NameError: return isinstance(obj, str) # python 3
isaacbernat

19

Tôi tìm thấy điều này nhiều hơn pythonic:

if type(aObject) is str:
    #do your stuff here
    pass

kể từ khi đối tượng loại là singleton, có thể được sử dụng để thực hiện so sánh các đối tượng để loại str


4
Đây không phải là cách thử nghiệm chung được đề xuất cho loại, vì tính kế thừa: isinstance(obj_to_test, str)rõ ràng là để kiểm tra loại và nó có lợi thế là sử dụng cùng một quy trình như đối với các trường hợp khác, không phải là str.
Eric O Lebigot

14

Nếu ai đó muốn tránh xa việc kiểm tra kiểu rõ ràng (và có những lý do chính đáng để tránh xa nó), có lẽ phần an toàn nhất của giao thức chuỗi cần kiểm tra là:

str(maybe_string) == maybe_string

Nó sẽ không lặp qua một iterable hoặc iterator, nó sẽ không gọi một danh sách các chuỗi là một chuỗi và nó phát hiện chính xác một chuỗi như như một chuỗi.

Tất nhiên là có nhược điểm. Ví dụ, str(maybe_string)có thể là một tính toán nặng nề. Như thường lệ, câu trả lời là nó phụ thuộc .

EDIT: Như @Tcll chỉ ra trong các bình luận, câu hỏi thực sự yêu cầu một cách để phát hiện cả chuỗi unicode và bytestrings. Trên Python 2, câu trả lời này sẽ không thành công với một ngoại lệ cho các chuỗi unicode có chứa các ký tự không phải ASCII và trên Python 3, nó sẽ trả về Falsetất cả các chuỗi phụ.


Trong trường hợp các đối tượng khởi tạo với dữ liệu biểu diễn, điều này có thể không hoạt động như mong đợi ... b = b'test'; r = str(b) == bnơi bchứa dữ liệu giống như str(b)nhưng (là một đối tượng byte) không xác thực dưới dạng chuỗi.
Tcll

@Tcll Đúng, câu hỏi thực sự nói "thông thường hoặc Unicode". Tôi đoán tôi đã không đọc nó đúng cách.
clacke

11

Để kiểm tra xem biến của bạn có phải là thứ bạn có thể sử dụng không:

s='Hello World'
if isinstance(s,str):
#do something here,

Đầu ra của isistance sẽ cung cấp cho bạn giá trị boolean True hoặc false để bạn có thể điều chỉnh cho phù hợp. Bạn có thể kiểm tra từ viết tắt dự kiến ​​của giá trị của mình bằng cách sử dụng: type (s) Điều này sẽ trả về cho bạn gõ 'str' để bạn có thể sử dụng nó trong hàm isistance.


5

Tôi có thể đối phó với điều này theo kiểu gõ vịt, như những người khác đề cập. Làm thế nào để tôi biết một chuỗi thực sự là một chuỗi? tốt, rõ ràng bằng cách chuyển đổi nó thành một chuỗi!

def myfunc(word):
    word = unicode(word)
    ...

Nếu đối số đã là một chuỗi hoặc loại unicode, real_word sẽ giữ giá trị của nó không thay đổi. Nếu đối tượng thông qua thực hiện một __unicode__phương thức, được sử dụng để có được biểu diễn unicode của nó. Nếu đối tượng được truyền không thể được sử dụng như một chuỗi, thì unicodenội dung dựng lên một ngoại lệ.


3
isinstance(your_object, basestring)

sẽ đúng nếu đối tượng của bạn thực sự là kiểu chuỗi. 'str' là từ dành riêng.

Tôi xin lỗi, câu trả lời đúng là sử dụng 'basestring' thay vì 'str' để bao gồm cả chuỗi unicode - như đã được lưu ý ở trên bởi một trong những người trả lời khác.


Không hoạt động cho các đối tượng unicode, được yêu cầu rõ ràng trong câu hỏi.
dbn

1

Tối nay tôi gặp phải một tình huống mà tôi nghĩ rằng tôi sẽ phải kiểm tra strloại này, nhưng hóa ra tôi đã không làm thế.

Cách tiếp cận của tôi để giải quyết vấn đề có thể sẽ hoạt động trong nhiều tình huống, vì vậy tôi đưa ra giải pháp dưới đây trong trường hợp những người khác đọc câu hỏi này quan tâm (chỉ Python 3).

# NOTE: fields is an object that COULD be any number of things, including:
# - a single string-like object
# - a string-like object that needs to be converted to a sequence of 
# string-like objects at some separator, sep
# - a sequence of string-like objects
def getfields(*fields, sep=' ', validator=lambda f: True):
    '''Take a field sequence definition and yield from a validated
     field sequence. Accepts a string, a string with separators, 
     or a sequence of strings'''
    if fields:
        try:
            # single unpack in the case of a single argument
            fieldseq, = fields
            try:
                # convert to string sequence if string
                fieldseq = fieldseq.split(sep)
            except AttributeError:
                # not a string; assume other iterable
                pass
        except ValueError:
            # not a single argument and not a string
            fieldseq = fields
        invalid_fields = [field for field in fieldseq if not validator(field)]
        if invalid_fields:
            raise ValueError('One or more field names is invalid:\n'
                             '{!r}'.format(invalid_fields))
    else:
        raise ValueError('No fields were provided')
    try:
        yield from fieldseq
    except TypeError as e:
        raise ValueError('Single field argument must be a string'
                         'or an interable') from e

Một số xét nghiệm:

from . import getfields

def test_getfields_novalidation():
    result = ['a', 'b']
    assert list(getfields('a b')) == result
    assert list(getfields('a,b', sep=',')) == result
    assert list(getfields('a', 'b')) == result
    assert list(getfields(['a', 'b'])) == result

1

Rất đơn giản, hãy sử dụng đoạn mã sau (chúng tôi giả sử đối tượng được đề cập là obj) -

if type(obj) == str:
    print('It is a string')
else:
    print('It is not a string.')

0

Bạn có thể kiểm tra nó bằng cách nối với một chuỗi rỗng:

def is_string(s):
  try:
    s += ''
  except:
    return False
  return True

Chỉnh sửa :

Sửa câu trả lời của tôi sau khi bình luận chỉ ra rằng điều này không thành công với danh sách

def is_string(s):
  return isinstance(s, basestring)

Bạn đã đúng, cảm ơn đã chỉ ra. Tôi đã đưa ra một câu trả lời thay thế.
georgepsarakis

-3

Đối với cách tiếp cận gõ vịt đẹp cho những người thích chuỗi có phần thưởng khi làm việc với cả Python 2.x và 3.x:

def is_string(obj):
    try:
        obj + ''
        return True
    except TypeError:
        return False

Wisefish đã gần gũi với cách gõ vịt trước khi anh chuyển sang isinstancecách tiếp cận, ngoại trừ điều đó +=có ý nghĩa khác cho danh sách hơn là +.


2
Vâng, bạn có hai downvote và không ai cung cấp một bình luận. Tôi đã không đánh giá thấp nhưng tôi không thích giải pháp của bạn vì: * Quá dài dòng. Bạn không cần phải xác định một chức năng để làm điều này. * Đắt. Bắt ngoại lệ là không tốt cho hiệu suất. * Dễ bị lỗi. Đối tượng khác có thể triển khai thêm , xem một chuỗi và đưa ra một loại ngoại lệ khác, không phải là TypeError.
santiagobasulto

Ngoài ra ở đây, bạn đang sử dụng phương pháp gõ vịt, rất đẹp, nhưng cuối cùng lại ném và bắt ngoại lệ chỉ để tìm ra thứ gì đó không đẹp.
Alexey Tigarev

Đây có thể là cách chắc chắn duy nhất để phân biệt giữa một chuỗi giống như chuỗi và một số lần lặp khác của chuỗi. Người ta có thể tìm kiếm các thuộc tính như thế nào isalpha, nhưng ai biết phương pháp nào sẽ an toàn để tìm kiếm?
clacke

Tôi nhận ra rằng __str__phương pháp cộng với sự bình đẳng thực sự có thể là phương pháp chứng minh ngu ngốc. Nhưng ngay cả điều đó không phải là không có sự cẩn thận.
clacke

Các ngoại lệ @santiagobasulto có giá rẻ bằng Python. Nếu bạn mong đợi lỗi 1% thời gian, trycó thể nhanh hơn. Nếu bạn mong đợi nó 99% thời gian, có thể không. Sự khác biệt hiệu suất là tối thiểu, tốt hơn hết là thành ngữ trừ khi bạn cấu hình mã của mình và xác định nó là thực sự chậm.
Nick T

-4
if type(varA) == str or type(varB) == str:
    print 'string involved'

từ EDX - khóa học trực tuyến MITx: 6,00.1x Giới thiệu về Khoa học và Lập trình Máy tính bằng Python


6
Đây có lẽ là cách tồi tệ nhất có thể để kiểm tra. Nó không chỉ loại trừ các đối tượng unicode, thậm chí còn loại trừ các lớp con của str!
tám
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.