วิธีการตรวจสอบว่าตัวแปรเป็นสตริงที่มีความเข้ากันได้หลาม 2 และ 3


171

ฉันรู้ว่าฉันสามารถใช้: isinstance(x, str)ใน python-3.x แต่ฉันต้องตรวจสอบว่ามีสตริงใน python-2.x หรือไม่ จะisinstance(x, str)ทำงานได้ตามที่คาดหวังใน python-2.x หรือไม่ หรือฉันจะต้องตรวจสอบเวอร์ชั่นและใช้isinstance(x, basestr)?

โดยเฉพาะใน python-2.x:

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

และ python-3.x ไม่มี u"foo"


2
ไวยากรณ์ของ u "" สำหรับตัวอักษร Unicode จะได้รับการแนะนำใหม่ใน Python 3.3
jfs

แปลก ฉันได้รับ `` `>>> isinstance (คุณ" การทดสอบ ", basestring) จริง` `` บน Python 2.7.16
Darakian

คำตอบ:


209

หากคุณกำลังเขียนโค้ดที่เข้ากันได้ 2.x-and-3.x คุณอาจต้องการใช้หก :

from six import string_types
isinstance(s, string_types)

ขออภัยฉันสับสนเล็กน้อยเกี่ยวกับผลลัพธ์ต่อไปนี้ >>> isinstance(u"foo", string_types) True >>> isinstance(u"foo".encode("utf-8"), string_types) True ฉันคาดหวังว่า isinstance (u "foo", string_types) จะคืนค่าเท็จ
Chandler.Huang

1
@ Chandler.Huang คำถามนี้เป็นเรื่องเกี่ยวกับการระบุstrและunicodeในหลาม 2 หรือstrในหลาม 3. หากคุณไม่ต้องการunicodeที่จะนับในหลาม 2 strใช้เพียง
ecatmur

@ecatmur woops ขอบคุณ! ลบออกดังนั้นไม่มีใครสับสน
runDOSrun

4
คุณสามารถใช้มันจากfutureแพ็คเกจแทนsix:from future.utils import string_types
SuperGeo

113

แนวทางที่สั้นที่สุดที่ฉันค้นพบโดยไม่ต้องพึ่งพาแพ็คเกจเหมือนหกคือ:

try:
  basestring
except NameError:
  basestring = str

จากนั้นสมมติว่าคุณได้ตรวจสอบสตริงใน Python 2 ในลักษณะทั่วไปที่สุด

isinstance(s, basestring)

จะใช้งานได้กับ Python 3+ ด้วย


10
สำหรับ py3 basestring = (str, bytes)จากrequests/compat.py
Tanky Woo

ดี แต่ทำไม มันจะดีถ้า Python3 สามารถใช้งานร่วมกับระบบย้อนหลังได้ที่นี่ วิธีแก้ปัญหาข้างต้นใช้ได้ผล จะดีกว่านี้ถ้าไม่มีความจำเป็น
guettli

2
เพื่อตอบสนองทั้งการสนับสนุน py2 & 3 และ mypy ฉันจึงลงเอยด้วยif not hasattr(__builtins__, "basestring"): basestring = (str, bytes)
เดฟลี

35

เกี่ยวกับเรื่องนี้ทำงานได้ในทุกกรณี?

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

@ holdenweb: ไม่และใช่ - ดี "ส่งผลกระทบเฉพาะที่จำเป็น" แฮ็คฉันคิดว่า
Dilettant

1
เหตุผลที่ฉันชอบคำตอบนี้ก็คือมันเป็นมิตรกับการย้ายจาก python2 เป็น 3
Tiagojdferreira

4
ฉันยังไปกับตัวเลือกนี้โดยห่อในฟังก์ชันผู้ช่วยดังนั้นจะปรากฏเพียงครั้งเดียวและมีสถานที่ใน docstring ถึงเครดิต Fil
Carl Smith

2
เรียบร้อยและฉันใช้มันด้วยตัวเองจนกระทั่งฉันรู้ว่าฉันยังมีfrom __future__ import unicode_literalsส่วนร่วมด้วย ตอนนี้ฉันจะไปกับ:isinstance(val, (str, u"".__class__))
เกรแฮม Klyne

18

นี่คือคำตอบของ @Lev Levitsky เขียนใหม่อีกครั้ง

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

การทดสอบtry/ exceptจะทำครั้งเดียวแล้วกำหนดฟังก์ชั่นที่ใช้งานได้เสมอและเร็วที่สุด

แก้ไข: ที่จริงแล้วเราไม่จำเป็นต้องแม้กระทั่งโทรisinstance(); เราแค่ต้องประเมินbasestringและดูว่าเราได้รับNameError:

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

ผมคิดว่ามันเป็นเรื่องง่ายที่จะปฏิบัติตามที่มีการเรียกร้องให้isinstance()แต่


isinstance("", basestring)คือสิ่งที่ฉันหมายถึงโดย "เรียก" อย่างไรก็ตาม +1
Lev Levitsky

1
Python เป็นภาษาที่มีพลวัตมากและฉันไม่คิดว่ามันจะดูไม่ดีเลยที่จะมีการทดสอบเช่นนี้ นี่เป็นเทคนิคที่มีประโยชน์สำหรับการค้นหาสิ่งต่าง ๆ ในครั้งเดียวและตามนั้นการตั้งค่าฟังก์ชั่นที่จะถูกต้องเสมอ ขอบคุณสำหรับ +1
steveha

5
ฉันจะเขียนมันเป็น:try: string_types = basestring except NameError: string_types = str
jfs

12

futureห้องสมุดเพิ่ม (หลาม 2) ชื่อที่เข้ากันได้เพื่อให้คุณสามารถเขียนต่อหลาม 3 คุณสามารถทำสิ่งต่อไปนี้ง่ายๆ

from builtins import str
isinstance(x, str) 

หากต้องการติดตั้งเพียงดำเนินการpip install futureเพียงแค่ดำเนินการ

ในฐานะที่เป็นข้อแม้ก็เพียง แต่สนับสนุนpython>=2.6,>=3.3แต่มันเป็นเรื่องที่ทันสมัยมากขึ้นกว่าsixที่เป็นเพียงการแนะนำถ้าใช้python 2.5


8

อาจใช้วิธีแก้ปัญหาเช่น

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

ขออภัยที่จะผิดพลาดคุณ แต่isinstance(u'hello', basestr)ให้SyntaxError: invalid syntaxฉันด้วย Python 3.2.3 ภายใต้ Window 7 .. ความคิดใด ๆ ว่าทำไมถึงเป็นเช่นนั้น? ดูเหมือนจะไม่ชอบu- ฉันได้รับข้อผิดพลาดนี้ด้วยstrและbasestr
Levon

1
@Levon ไม่มีปัญหา :) นั่นเป็นเพราะPython3 ไม่มีไวยากรณ์เช่นนั้นstrใน Python3 นั้นเป็นไปตามนิยามของ Unicode ดังนั้นจึงไม่มีbasestringประเภทดังนั้นNameErrorที่ติดอยู่ในตัวอย่างของฉัน
Lev Levitsky

มันมีไวยากรณ์ที่เป็น noop ในขณะนี้ ใน 3.3
Randall Hunt

2
ฉันขอแนะนำให้ทำtry/ exceptทดสอบครั้งเดียวและจากผลของการทดสอบครั้งเดียวนั้นคุณกำหนดisstr()อย่างถูกต้อง isstr()ไม่มีความจำเป็นที่จะต้องเสียค่าใช้จ่ายของข้อยกเว้นสำหรับการเรียกร้องให้ทุกคนเป็น
steveha

@Ranman ที่ถูกต้องเกี่ยวกับงูหลาม 3.3 นี่คือเชื่อมโยงไปยังห้าวหาญ
Lev Levitsky

7

คุณสามารถรับคลาสของวัตถุโดยการโทรobject.__class__ดังนั้นเพื่อตรวจสอบว่าวัตถุเป็นประเภทสตริงเริ่มต้น:

    isinstance(object,"".__class__)

และคุณสามารถวางต่อไปนี้ในด้านบนของรหัสของคุณเพื่อให้สตริงที่ล้อมรอบด้วยคำพูดอยู่ใน Unicode ในหลาม 2:

    from __future__ import unicode_literals

ฉันแก้ปัญหานี้ไม่น้อย ฉันพบว่ามันจะมีประโยชน์ในการกำหนด str = "" .__ class__ ซึ่งตอนนี้อนุญาตให้เขียน isinstance (object, str) ได้ตามปกติและยังช่วยให้มั่นใจได้ว่า str (วัตถุ) จะส่งคืนสตริง unicode ใน Python 2 และ Python 3
amicitas

นี้จะไม่ทำงานเมื่อวิเคราะห์ XML: some_element.textเป็น 'STR' แต่เปรียบเทียบกับ 'Unicode' จะล้มเหลว
หลุมฝังศพ

ใช้งานไม่ได้กับสตริง unicode ใน python 2: isinstance (u'XXX ',' '.__ class__) == False
Fil

0

คุณสามารถลองสิ่งนี้ได้ที่จุดเริ่มต้นของรหัสของคุณ:

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

และในภายหลังในรหัส:

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

0

ระวัง! ในหลาม 2 strและbytesเป็นหลักเหมือนกัน สิ่งนี้อาจทำให้เกิดข้อบกพร่องหากคุณพยายามแยกแยะระหว่างสอง

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

-4

ประเภท (สตริง) == str

ผลตอบแทนจริงถ้ามันเป็นสตริงและเท็จถ้าไม่


1
ไม่เป็นความจริงสำหรับ Python 2 ซึ่งstringเป็นสตริง Unicode
lxop
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.