Değişkenin python 2 ve 3 uyumluluğu ile dize olup olmadığı nasıl kontrol edilir


171

Kullanabileceğimi biliyorum: isinstance(x, str)python-3.x ama bir şey de python-2.x bir dize olup olmadığını kontrol etmek gerekir. Will isinstance(x, str)piton-2.x beklendiği gibi çalışmayabilir? Yoksa sürümü kontrol edip kullanmam gerekecek isinstance(x, basestr)mi?

Özellikle, python-2.x içinde:

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

ve python-3.x içermiyor u"foo"


2
u "" Unicode değişmezlerinin sözdizimi Python 3.3
jfs

Garip. Python 2.7.16
Darakian

Yanıtlar:


209

2.x ve 3.x uyumlu kod yazıyorsanız, muhtemelen altı kod kullanmak istersiniz :

from six import string_types
isinstance(s, string_types)

Üzgünüm, aşağıdaki sonuç hakkında biraz kafam karıştı. >>> isinstance(u"foo", string_types) True >>> isinstance(u"foo".encode("utf-8"), string_types) True Ben isinstance (u "foo", string_types) yanlış döndürme bekliyordum.
Chandler.Huang

1
@ Chandler.Huang Bu soru, Python 2 veya Python 3'ü tanımlamak strve hakkında unicode. Python 2'ye strgüvenmek istemiyorsanız unicode, sadece kullanın str.
ecatmur

@ecatmur woops, teşekkürler! silindi, böylece kimse karışmaz
runDOSrun

4
ayrıca futurebunun yerine paketten de kullanabilirsiniz six:from future.utils import string_types
SuperGeo

113

Altı gibi paketlere dayanmadan bulduğum en kısa yaklaşım:

try:
  basestring
except NameError:
  basestring = str

Python 2'de dizeleri en genel şekilde kontrol ettiğinizi varsayarsak,

isinstance(s, basestring)

şimdi Python 3+ için de çalışacak.


10
PY3 için basestring = (str, bytes)gelenrequests/compat.py
Tanky Woo

Güzel, ama neden? Python3'ün burada geriye dönük uyumlu olması iyi olurdu. Yukarıdaki çözümler çalışır. Eğer gerek olmazsa, daha iyi olurdu.
guettli

2
Hem py2 hem de 3 desteği ve mypy'yi tatmin etmek için bitirdimif not hasattr(__builtins__, "basestring"): basestring = (str, bytes)
Dave Lee

35

Buna ne dersin, her durumda işe yarıyor mu?

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

@holdenweb: Hayır ve evet - şık bir "sadece gerektiğinde etkiler" kesmek sanırım.
Seyreltici

1
Bu yanıtı beğenmemizin nedeni, python2'den 3'e geçişle dost olması.
Tiagojdferreira

4
Ayrıca bu seçenekle yardımcı bir işleve sarıldım, bu yüzden sadece bir kez görünüyor ve doktrinde Fil'e kredi vermek için bir yer var.
Carl Smith

2
Düzenli ve from __future__ import unicode_literalsaktif olduğumu fark edene kadar kendim kullanıyordum . Şimdi gidiyorum:isinstance(val, (str, u"".__class__))
Graham Klyne

18

Bu @Lev Levitsky'nin cevabı, biraz yeniden yazılmış.

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

try/ exceptTest kez yapılır ve sonra hep çalışır ve mümkün olduğu kadar hızlı bir fonksiyon tanımlar.

EDIT: Aslında, aramamıza bile gerek yok isinstance(); Biz sadece değerlendirmek gerekir basestringve biz verip vermediğine bakın NameError:

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

isinstance()Yine de çağrıyı takip etmenin daha kolay olduğunu düşünüyorum .


isinstance("", basestring)"arayarak" demek istedim. Her neyse, +1.
Lev Levitsky

1
Python çok dinamik bir dildir ve böyle bir teste sahip olmanın hiç de kötü görünmediğini düşünüyorum. Bu, bir şeyi bir kerede anlamak ve buna dayanarak, her zaman doğru olacak bir işlev kurmak için yararlı bir tekniktir. +1 için teşekkürler.
steveha

5
Ben şöyle yazardım:try: string_types = basestring except NameError: string_types = str
jfs

12

futureKütüphane (Python 2'ye) ekler uyumlu isimlerin sen böylece, Python 3 yazmaya devam . Aşağıdakileri basit bir şekilde yapabilirsiniz:

from builtins import str
isinstance(x, str) 

Kurmak için , sadece çalıştırın pip install future.

Bir uyarı olarak , sadece destekliyor python>=2.6, >=3.3ancak daha modern six, sadece kullanıldığında önerilirpython 2.5


8

Belki şöyle bir geçici çözüm kullanın

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

Sizi isinstance(u'hello', basestr)rahatsız ettiğim için üzgünüm ama SyntaxError: invalid syntaxPython 3.2.3 ile Windows 7 altında bana verim veriyor. Bu gibi görünmüyor u- Bu hatayla alıyorum strvebasestr
Levon

1
@Levon Sorun :) çünkü yıllardan bu Python3 o sözdizimi yok gibi strtanım Unicode gereğidir Python3 içinde. Buna göre, hiçbir basestringtürü yoktur , bu yüzden NameErrorsnippet'imde yakalanır.
Lev Levitsky

Şu anda bir sözdizimine sahip. in 3.3
Randall Hunt

2
try/ exceptTesti tek bir kez yapmanızı öneririm ve bu tek testin sonuçlarına göre isstr()doğru bir şekilde tanımlarsınız . Her çağrı için bir istisna yükü oluşturmaya gerek yoktur isstr().
steveha

@Ranman Python 3.3 hakkında doğru , PEP için bir bağlantı .
Lev Levitsky

7

object.__class__Nesnenin varsayılan dize türü olup olmadığını kontrol etmek için bir nesnenin sınıfını çağırarak alabilirsiniz :

    isinstance(object,"".__class__)

Ve kodunuzun üst kısmına aşağıdakileri yerleştirebilirsiniz, böylece tırnak işaretleri içine alınmış dizeler python 2'de unicode olur:

    from __future__ import unicode_literals

Ben bu çözümü biraz. Ben şimdi isinstance (nesne, str) normal olarak yazılmasını sağlar ve aynı zamanda str (nesne) hem Python 2 hem de Python 3 bir unicode dize döndürmesini sağlar str = "" .__ class__ tanımlamak yararlı olabilir bulundu.
amicitas

XML ayrıştırılırken bu işe yaramaz: some_element.textbir 'str' dir ancak 'unicode' ile karşılaştırma başarısız olur
tonoz

Python 2'de unicode dize ile çalışmaz: isinstance (u'XXX ',' '.__ class__) == Yanlış
Fil

0

Bunu kodunuzun başında deneyebilirsiniz:

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

ve daha sonra kodda:

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

0

Dikkatli ol! Python 2'de strve bytesaslında aynı. Bu ikisi arasında ayrım yapmaya çalışıyorsanız bir hataya neden olabilir.

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

-4

type (string) == str

bir dize olursa true değerini, değilse false değerini döndürür


1
stringUnicode dizge olan Python 2 için doğru değil
lxop
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.