Cách kiểm tra xem biến có phải là chuỗi có khả năng tương thích python 2 và 3 không


171

Tôi biết rằng tôi có thể sử dụng: isinstance(x, str)trong python-3.x nhưng tôi cần kiểm tra xem có gì đó là một chuỗi trong python-2.x không. Sẽ isinstance(x, str)hoạt động như mong đợi trong python-2.x? Hoặc tôi sẽ cần phải kiểm tra phiên bản và sử dụng isinstance(x, basestr)?

Cụ thể, trong python-2.x:

>>>isinstance(u"test", str)
False

và python-3.x không có u"foo"


2
Cú pháp u "" cho các chữ Unicode được giới thiệu lại trong Python 3.3
jfs

Lạ Tôi nhận được `` `>>> isinstance (u" test ", basestring) Đúng` `` trên Python 2.7.16
Darakian

Câu trả lời:


209

Nếu bạn đang viết mã tương thích 2.x-và-3.x, có lẽ bạn sẽ muốn sử dụng sáu :

from six import string_types
isinstance(s, string_types)

Xin lỗi tôi hơi nhầm lẫn về kết quả sau đây. >>> isinstance(u"foo", string_types) True >>> isinstance(u"foo".encode("utf-8"), string_types) True Tôi đã mong đợi isinstance (u "foo", string_types) trả về false.
Chandler.Huang

1
@ Chandler.Huang câu hỏi này là về việc xác định strunicodetrên Python 2 hoặc strtrên Python 3. Nếu bạn không muốn unicodeđếm trên Python 2, chỉ cần sử dụng str.
ecatmur

@ecatmur woops, cảm ơn! đã xóa nó, vì vậy không ai bị nhầm lẫn
runDOSrun

4
bạn cũng có thể sử dụng nó từ futuregói thay vì six:from future.utils import string_types
SuperGeo

113

Cách tiếp cận ngắn gọn nhất mà tôi tìm thấy mà không cần dựa vào các gói như sáu, là:

try:
  basestring
except NameError:
  basestring = str

sau đó, giả sử bạn đã kiểm tra các chuỗi trong Python 2 theo cách chung nhất,

isinstance(s, basestring)

bây giờ cũng sẽ làm việc cho Python 3+.


10
Đối với py3, basestring = (str, bytes)từrequests/compat.py
Woo

Đẹp, nhưng tại sao? Sẽ thật tuyệt nếu Python3 tương thích ngược ở đây. Các giải pháp trên hoạt động. Sẽ còn tốt hơn nữa, nếu không cần nó.
guettli

2
Để đáp ứng cả hỗ trợ py2 & 3 và mypy, tôi đã kết thúc vớiif not hasattr(__builtins__, "basestring"): basestring = (str, bytes)
Dave Lee

35

Điều gì về điều này, hoạt động trong tất cả các trường hợp?

isinstance(x, ("".__class__, u"".__class__))

@keepenweb: Không và có - một cách tiện lợi "chỉ tác động khi cần thiết" tôi nghĩ.
Pha loãng

1
Lý do tại sao tôi thích câu trả lời này là vì nó thân thiện với việc di chuyển từ python2 đến 3.
Tiagojdferreira

4
Tôi cũng đã sử dụng tùy chọn này, gói nó trong một hàm trợ giúp, vì vậy nó chỉ xuất hiện một lần và có một vị trí trong chuỗi tài liệu để ghi có Fil.
Carl Smith

2
Neat, và tôi đã sử dụng nó cho đến khi tôi nhận ra rằng tôi cũng có from __future__ import unicode_literalshoạt động. Bây giờ tôi sẽ đi với:isinstance(val, (str, u"".__class__))
Graham Klyne

18

Đây là câu trả lời của @Lev Levitsky, được viết lại một chút.

try:
    isinstance("", basestring)
    def isstr(s):
        return isinstance(s, basestring)
except NameError:
    def isstr(s):
        return isinstance(s, str)

Các try/ exceptkiểm tra được thực hiện một lần, và sau đó định nghĩa một hàm mà luôn luôn làm việc và càng nhanh càng tốt.

EDIT: Thật ra, chúng tôi thậm chí không cần gọi isinstance(); chúng ta chỉ cần đánh giá basestringvà xem nếu chúng ta có được NameError:

try:
    basestring  # attempt to evaluate basestring
    def isstr(s):
        return isinstance(s, basestring)
except NameError:
    def isstr(s):
        return isinstance(s, str)

Tôi nghĩ rằng nó dễ dàng hơn để làm theo với cuộc gọi đến isinstance(), mặc dù.


isinstance("", basestring)là những gì tôi có nghĩa là "gọi". Dù sao, +1.
Lev Levitsky

1
Python là một ngôn ngữ rất năng động và tôi không nghĩ nó có vẻ tệ khi thử nghiệm như thế. Đây là một kỹ thuật hữu ích để tìm ra một cái gì đó một lần, và dựa vào đó, thiết lập một chức năng sẽ luôn luôn chính xác. Cảm ơn +1.
steveha

5
Tôi sẽ viết nó như sau:try: string_types = basestring except NameError: string_types = str
jfs

12

Các futurethư viện bổ sung (để Python 2) tên tương thích , vì vậy bạn có thể tiếp tục viết Python 3 . Bạn có thể đơn giản làm như sau:

from builtins import str
isinstance(x, str) 

Để cài đặt nó , chỉ cần thực hiện pip install future.

Là một cảnh báo , nó chỉ hỗ trợ python>=2.6, >=3.3nhưng nó hiện đại hơn six, chỉ được khuyến khích nếu sử dụngpython 2.5


8

Có thể sử dụng một cách giải quyết như

def isstr(s):
    try:
        return isinstance(s, basestring)
    except NameError:
        return isinstance(s, str)

Xin lỗi để làm phiền bạn nhưng isinstance(u'hello', basestr)mang lại SyntaxError: invalid syntaxcho tôi với Python 3.2.3 trong Window 7 .. bạn có biết tại sao điều này sẽ xảy ra không? Nó dường như không thích u- Tôi gặp lỗi này strbasestr
Levon

1
@Levon Không có vấn đề gì :) Đó là vì Python3 không có cú pháp đó , như strtrong Python3 là theo định nghĩa Unicode. Theo đó, không có basestringloại nào , do đó cái NameErrorđó bị bắt trong đoạn trích của tôi.
Lev Levitsky

Nó không có cú pháp như bây giờ. trong 3,3
Randall Hunt

2
Tôi sẽ đề nghị thực hiện try/ exceptkiểm tra một lần duy nhất và dựa trên kết quả của bài kiểm tra đó, bạn xác định isstr()chính xác. Không cần phải chịu chi phí ngoại lệ cho mỗi cuộc gọi đến isstr().
steveha

@Ranman nói đúng về Python 3.3, đây là một liên kết đến PEP .
Lev Levitsky

7

Bạn có thể lấy lớp của một đối tượng bằng cách gọi object.__class__, vì vậy để kiểm tra xem đối tượng có phải là loại chuỗi mặc định hay không:

    isinstance(object,"".__class__)

Và bạn có thể đặt đoạn mã sau vào đầu Mã của bạn để các chuỗi được bao quanh bởi dấu ngoặc kép ở dạng unicode trong python 2:

    from __future__ import unicode_literals

Tôi giải pháp này khá một chút. Tôi thấy nó có thể hữu ích khi định nghĩa str = "" .__ class__, giờ đây cho phép viết isinstance (object, str) bình thường và cũng đảm bảo rằng str (object) sẽ trả về một chuỗi unicode trong cả Python 2 và Python 3.
amellyas

Điều này không hoạt động khi phân tích cú pháp XML: some_element.textlà một 'str' nhưng việc so sánh với 'unicode' sẽ thất bại
vault

Không hoạt động với chuỗi unicode trên python 2: isinstance (u'XXX ',' '.__ class__) == Sai
Fil

0

Bạn có thể thử điều này ở đầu mã của bạn:

from __future__ import print_function
import sys
if sys.version[0] == "2":
    py3 = False
else:
    py3 = True
if py3: 
    basstring = str
else:
    basstring = basestring

và sau này trong mã:

anystring = "test"
# anystring = 1
if isinstance(anystring, basstring):
    print("This is a string")
else:
    print("No string")

0

Hãy cẩn thận! Trong python 2, strbytesvề cơ bản là giống nhau. Điều này có thể gây ra lỗi nếu bạn đang cố gắng phân biệt giữa hai.

>>> size = 5    
>>> byte_arr = bytes(size)
>>> isinstance(byte_arr, bytes)
True
>>> isinstance(byte_arr, str)
True

-4

loại (chuỗi) == str

trả về true nếu đó là một chuỗi và false nếu không


1
Không đúng với Python 2, trong đó stringcó một chuỗi unicode
lxop
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.