Bir Python nesnesinin bir dize olup olmadığını nasıl öğrenebilirim?


402

Python nesnesinin bir dize olup olmadığını nasıl kontrol edebilirim (normal veya Unicode)?


18
Jason'ın bahsettiği şey, ördek yazmaktır (eğer bir ördek gibi quacks ise muhtemelen bir ördek). Python'da, bir dize veya dize alt sınıfı olup olmadığını test etmeden, genellikle kodunuzun herhangi bir dize benzeri nesne üzerinde "çalışmasına izin verin". Daha fazla bilgi için, bkz. Docs.python.org/glossary.html#term-duck-typing
Ben Hoyt

4
SO ile ilgili bunu seviyorum. Genellikle bir soru sordum, cevaplanmadı, insanlar bana bunu yine de yapmamam gerektiğini ve nedenini söylüyorlar ve programcı olarak büyüyorum. =)
physicsmichael

24
+1: Bir cevaba nadiren ihtiyaç duyulması, sorunun geçersiz olduğu anlamına gelmez. Her ne kadar burada dikkat etmek harika bir şey olsa da, soruyu indirgemeyi hak ettiğini düşünmüyorum.
Trevor

17
Bu muhtemelen Python'da tür denetiminin en meşru kullanımıdır. Dizeler yinelenebilir, bu yüzden onları listelerden başka bir şekilde ayırmak kötü bir fikirdir.
ojrac

3
Dizeleri diğer yinelenebilirlerden ayırmanın gerekli olduğu durumlar kesinlikle vardır. Örneğin, pprint modülündeki PrettyPrinter kaynak koduna bakın.
saxman01

Yanıtlar:



178

Python 2

Bir nesnenin odize türünde bir alt sınıfın dize türü olup olmadığını kontrol etmek için :

isinstance(o, basestring)

çünkü her ikisi strve unicodealt sınıflarıdır basestring.

Türünün otam olarak olup olmadığını kontrol etmek için str:

type(o) is str

Aşağıdaki öğelerin obir örneğinin strveya alt sınıfının olup olmadığını denetlemek için str:

isinstance(o, str)

Unicode dizeleri için yukarıda da iş değiştirmek durumunda strolan unicode.

Ancak, hiçbir zaman açık tip denetimi yapmanız gerekmeyebilir. "Ördek yazarak" ihtiyaçlarınızı karşılayabilir. Bkz. Http://docs.python.org/glossary.html#term-duck-typing .

Ayrıca bkz . Python türünü kontrol etmenin standart yolu nedir?


atamadan önce yerel değişken 'str' referansı
john ktejik

@johnktejik python3 vs python2. basestringPy2'de kontrol etmeniz gerekiyor .
erikbwork

170

Python 3

Python 3.x'te tek dize türü basestringgibi artık kullanılamaz str(Python 2.x'lerin semantiği ile unicode).

Python 3.x'teki check sadece:

isinstance(obj_to_test, str)

Bu şu düzeltmeyi resmi bir 2to3dönüşüm aracı: dönüştürme basestringiçin str.


94

Python 2 ve 3

(Çapraz-uyumlu)

Python sürümüne (2.x ve 3.x) bakmaksızın kontrol etmek istiyorsanız, six( PyPI ) ve string_typesözelliğini kullanın:

import six

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

İçinde six(çok hafif tek dosya modülü), sadece yapıyor bu :

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

if PY3:
    string_types = str
else:
    string_types = basestring

Alternatif olarak, adı bile tutmak için future( PyPI ) kullanabilirsiniz :from past.builtins import basestring
David Nemeskey

1
BTW Cheat Sheet , Python sürüm uyumluluğu için mükemmel bir kaynaktır.
David Nemeskey

1
Herhangi bir ithalat kullanmamaya ne dersiniz? Önce deneyin basestringve sonra geri gidin str. Örndef is_string(obj): try: return isinstance(obj, basestring) # python 2 except NameError: return isinstance(obj, str) # python 3
isaacbernat

19

Bu ve daha fazlasını buldum pythonic:

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

Yazım nesneleri singleton olduğundan , nesneyi str türüyle karşılaştırmak için kullanılabilir


4
Bu, kalıtım nedeniyle yazım için önerilen genel test yöntemi değildir: isinstance(obj_to_test, str)açık bir şekilde yazımın test edilmesi amaçlanmıştır ve diğer str olmayan durumlarla aynı prosedürü kullanma avantajına sahiptir.
Eric O Lebigot

14

Birisi açık tip kontrolünden uzak durmak istiyorsa (ve bundan uzak durmak için iyi nedenler varsa), muhtemelen kontrol etmek için dize protokolünün en güvenli kısmı:

str(maybe_string) == maybe_string

Sırasıyla bu liste-of-the dizeleri bir dize çağrı olmaz değil yinelerler bir iterable veya Yineleyici yoluyla olur ve doğru bir tespit stringlike dize olarak.

Tabii ki dezavantajları var. Örneğin, str(maybe_string)ağır bir hesaplama olabilir. Sıkça olduğu gibi , cevap buna bağlıdır .

DÜZENLEME: As @Tcll işaret yorumlarda, soru aslında unicode dizeleri ve bytestrings hem algılamak için bir yol sorar. Python 2'de bu cevap ASCII olmayan karakterler içeren unicode dizeleri için bir istisna ile başarısız olur ve Python 3'te Falsetüm bytestringler için geri döner.


Sunum verileriyle başlayan nesneler söz konusu olduğunda, bu beklendiği gibi çalışmayabilir ... b = b'test'; r = str(b) == bburada baynı verileri tutar, str(b)ancak (bayt nesnesi olarak) bir dize olarak doğrulanmaz.
Tcll

@Tcll Doğru, soru aslında "normal veya Unicode" diyor. Sanırım düzgün okumadım.
clacke

11

Değişkeninizin bir şey olup olmadığını kontrol etmek için:

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

Direnç çıkışı size boolean True veya False değeri verecektir, böylece buna göre ayarlama yapabilirsiniz. Başlangıçta aşağıdakileri kullanarak değerinizin beklenen kısaltmasını kontrol edebilirsiniz: type (s) Bu, isistance işlevinde kullanabilmeniz için 'str' türünü döndürür.


5

Bunu, diğerlerinin de belirttiği gibi, ördek yazım tarzında ele alabilirim. Bir dizenin gerçekten bir dize olduğunu nasıl bilebilirim? iyi, açıkça bir dizeye dönüştürerek !

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

Arg zaten bir dize veya unicode tipiyse, real_word değerini değiştirmeden tutar. Aktarılan nesne bir __unicode__yöntem uygularsa , bu onun unicode temsilini almak için kullanılır. Geçirilen nesne dize olarak kullanılamazsa, unicodeyerleşik bir istisna oluşturur.


3
isinstance(your_object, basestring)

nesneniz gerçekten bir dize türüyse True olur. 'str' ayrılmış kelimedir.

özür dilerim, doğru cevap, diğer yanıtlayıcılardan biri tarafından yukarıda belirtildiği gibi, unicode dizeleri de içermesi için 'str' yerine 'basestring' kullanmaktır.


Soruda açıkça istenen unicode nesneler için çalışmaz.
dbn

1

Bu akşam , tipe karşı kontrol etmek zorunda kalacağımı düşündüğüm bir durumla karşılaştım str, ama öyle olmadı.

Sorunu çözme yaklaşımım muhtemelen birçok durumda işe yarayacaktır, bu yüzden bu soruyu okuyan diğerlerinin ilgilenmesi durumunda aşağıda sunuyorum (sadece 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

Bazı testler:

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

Basit, aşağıdaki kodu kullanın (obj olarak belirtilen nesnenin var olduğunu varsayıyoruz)

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

0

Boş bir dize ile birleştirerek test edebilirsiniz:

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

Düzenle :

Bunun listelerde başarısız olduğunu belirten yorumlardan sonra cevabımı düzeltiyorum

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

Haklısın, işaret ettiğin için teşekkürler. Alternatif bir cevap verdim.
georgepsarakis

-3

Hem Python 2.x hem de 3.x ile çalışma bonusu olan dize beğenileri için hoş bir ördek yazma yaklaşımı için:

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

bilge balıklarisinstance yaklaşıma geçmeden önce ördek yazmaya yakındı , ancak +=listeler için olduğundan farklı bir anlamı +var.


2
Peki, iki vahşetin var ve kimse yorum yapmadı. Ben düşürmedim ama çözümünüzü sevmiyorum çünkü: * Çok ayrıntılı. Bunu yapmak için bir işlev tanımlamanız gerekmez. * Pahalı. İstisnaları yakalamak performans için iyi değildir. * Eğilimli hata. Diğer nesne uygulayabilir eklenti , bir dize görmek ve TypeError değil istisna başka tür yükseltmek.
santiagobasulto

Ayrıca burada güzel olan ördek yazma yaklaşımını kullanıyorsunuz, ancak güzel olmayan bir şey bulmak için istisna atmak ve yakalamak.
Alexey Tigarev

Bu, bir dize benzeri ve diğer bir dizi dize arasında ayrım yapmanın tek kesin yolu olabilir. Bu gibi özellikler isalphaaranabilir, ancak hangi yöntemlerin güvenli bir şekilde aranacağını kim bilebilir?
clacke

Ben fark olduğunu __str__yöntem artı eşitlik aslında hamlede biri olabilir. Ama bu bile uyarılar olmadan değil.
clacke

@santiagobasulto istisnalar Python'da ucuzdur. Hatanın% try1'ini beklerseniz , daha hızlı olabilir. Eğer zamanın% 99'unu bekliyorsanız, belki değil. Performans farkı minimum olduğundan, kodunuzun profilini ve gerçekte yavaş olduğunu tanımlamadığınız sürece deyimsel olmak daha iyidir.
Nick T

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

EDX - online course MITx: 6.00.1x Python Kullanarak Bilgisayar Bilimi ve Programlamaya Giriş


6
Muhtemelen kontrol etmenin en kötü yolu budur. Sadece unicode nesneleri hariç tutmakla kalmaz, aynı zamanda alt sınıflarını da hariç tutar str!
augurar
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.