__Str__ ve __repr__ arasındaki fark nedir?


Yanıtlar:


2723

Alex iyi özetledi ama şaşırtıcı bir şekilde çok kısa ve özdü.

İlk olarak, Alex'in gönderisindeki ana noktaları tekrarlayayım :

  • Varsayılan uygulama işe yaramaz (hangisi olmayacağını düşünmek zor, ama evet)
  • __repr__ hedef açık olmak
  • __str__ amaç okunabilir olmak
  • Kapsayıcı __str__içerdiği nesneleri kullanıyor__repr__

Varsayılan uygulama işe yaramaz

Bu çoğunlukla bir sürprizdir çünkü Python'un varsayılanları oldukça yararlıdır. Ancak, bu durumda, varsayılan olarak __repr__aşağıdaki gibi davranır:

return "%s(%r)" % (self.__class__, self.__dict__)

çok tehlikeli olurdu (örneğin, nesneler birbirine referans veriyorsa sonsuz özyinelemeye girmek çok kolay). Böylece Python dışarı çıkar. Doğru olan bir varsayılan değer olduğuna dikkat edin: eğer __repr__tanımlanmışsa ve tanımlanmamışsa, __str__nesne sanki davranacaktır __str__=__repr__.

Bu, basit bir deyişle: uyguladığınız hemen hemen her nesnenin __repr__, nesneyi anlamak için kullanılabilecek bir işlevselliğe sahip olması gerekir . Uygulama __str__isteğe bağlıdır: “güzel yazdırma” işlevine (örneğin, bir rapor oluşturucu tarafından kullanılırsa) ihtiyacınız varsa bunu yapın.

Amacı __repr__açık olmak

Hemen çıkıp söyleyeyim - Hata ayıklayıcılara inanmıyorum. Herhangi bir hata ayıklayıcıyı nasıl kullanacağımı gerçekten bilmiyorum ve hiçbir zaman ciddiye almadım. Dahası, hata ayıklayıcılardaki büyük hatanın temel doğası olduğuna inanıyorum - hata ayıkladığım çoğu hata çok uzun zaman önce çok uzak bir galakside oldu. Bu, dini hevesle günlüğe inanmam anlamına geliyor. Günlüğe kaydetme, herhangi bir iyi ateşle ve unut sunucu sisteminin can damarıdır. Python günlüğe kaydetmeyi kolaylaştırır: belki de projeye özgü bazı sarıcılar ile ihtiyacınız olan tek şey

log(INFO, "I am in the weird function and a is", a, "and b is", b, "but I got a null C — using default", default_c)

Ancak son adımı yapmanız gerekir - uyguladığınız her nesnenin yararlı bir repr olduğundan emin olun, böylece böyle bir kod çalışabilir. Bu yüzden “eval” olayı ortaya çıkıyor: eğer yeterli bilgiye sahipseniz, bu eval(repr(c))==c, bilinmesi gereken her şeyi bildiğiniz anlamına gelir c. Bu yeterince kolaysa, en azından bulanık bir şekilde, yapın. Değilse, cyine de hakkında yeterli bilgiye sahip olduğunuzdan emin olun . Genellikle eval-benzeri bir format kullanıyorum "MyClass(this=%r,that=%r)" % (self.this,self.that). MyClass'ı gerçekten oluşturabileceğiniz veya bunların doğru yapıcı argümanları olduğu anlamına gelmez - ancak “bu örnek hakkında bilmeniz gereken her şey bu” ifadesini kullanmak yararlı bir formdur.

Not: %rYukarıda kullandım , değil %s. Her zaman uygulama içinde repr()[veya %rbiçimlendirme karakterini eşdeğer şekilde] kullanmak istersiniz veya __repr__repr hedefini yenersiniz. Farklılaşmak MyClass(3)ve MyClass("3").

Amacı __str__okunabilir olmak

Özellikle, açık olması amaçlanmamıştır - buna dikkat edin str(3)==str("3"). Benzer şekilde, bir IP soyutlaması uygularsanız, bunun 192.168.1.1 gibi görünmesi iyi olur. Bir tarih / saat soyutlaması uygularken, str "2010/4/12 15:35:22" vb. Olabilir. Amaç, onu bir programcı değil bir kullanıcının okumak isteyeceği şekilde temsil etmektir. İşe yaramaz basamakları doğrayın, başka bir sınıf gibi davranın - okunabilirliği desteklediği sürece bu bir gelişmedir.

Kapsayıcı __str__içerdiği nesneleri kullanıyor__repr__

Bu şaşırtıcı görünüyor, değil mi? Biraz, ama eğer kullanılırsa ne kadar okunabilir olurdu __str__?

[moshe is, 3, hello
world, this is a list, oh I don't know, containing just 4 elements]

Çok değil. Özellikle, bir kaptaki dizeler dizgi gösterimini rahatsız etmenin çok kolay olduğunu görür. Belirsizlik karşısında, hatırlayın, Python tahmin etme arzusuna direnir. Bir liste yazdırırken yukarıdaki davranışı istiyorsanız,

print "[" + ", ".join(l) + "]"

(muhtemelen sözlükler hakkında ne yapacağınızı da öğrenebilirsiniz.

özet

Uygulamak __repr__uygulamak herhangi bir sınıf için. Bu ikinci doğa olmalı. __str__Okunabilirliğin yanında çalışan bir dize sürümüne sahip olmanın yararlı olacağını düşünüyorsanız uygulayın .


154
Kesinlikle sizin hata ayıklama gitmek için bir yol değildir görüş ile katılmıyorum. Geliştirme için bir hata ayıklayıcı (ve / veya günlük kaydı) kullanın, üretim için günlük kaydı kullanın. Bir hata ayıklayıcı ile, sorun ortaya çıktığında yanlış giden her şeyi görebilirsiniz. Resmin tamamını görebilirsiniz. HER ŞEY'e giriş yapmadıkça bunu alamazsınız. Ayrıca her şeyi günlüğe kaydediyorsanız, istediğiniz şeyi elde etmek için tonlarca veriye girmeniz gerekir.
Samuel

21
Büyük cevap (hata ayıklayıcıları kullanmama hakkında biraz hariç). Python 3'teki str vs unicode hakkında bu diğer soru ve cevaplara , geçiş yapan kişilerin tartışmasıyla ilgili olabilecek bir bağlantı eklemek istiyorum .
ThatAintWorking

11
Hata ayıklayıcılar için artı 1 işe yaramaz ve bir kuruşa değmez. Bunun yerine günlük işlem hacminizi artırın. Ve evet bu iyi yazılmış bir yazıydı. Dönüşler dışarı __repr__ben ayıklama için gerekli oldu. Yardımın için teşekkürler.
personal_cloud

7
hata ayıklayıcının çılgınlığı bir yana,% r öğrendim ve yine de oy vermeye değer
Mickey Perlstein

6
Hata ayıklayıcı vs Hata ayıklayıcı: Böyle köklü görüşler almayın. Bazı uygulamalarda hata ayıklama gerçekçi değildir, tipik olarak gerçek zamanlı olduğunda veya kodunuz çok az erişimi olan veya konsol olmayan bir platformda uzaktan yürütüldüğünde. Diğer birçok durumda, araştırmak veya bir kesme noktası ayarlamak için bir istisnada durmak çok daha hızlı olacaktır, çünkü binlerce satırlık satırdan (diskinizi karmaşıklaştıracak ve uygulamayı yavaşlatacak) geçmeniz gerekmez. Son olarak, örneğin gömülü cihazlarda oturum açmak her zaman mümkün değildir, orada hata ayıklayıcı da arkadaşınızdır.
RedGlyph

523

Temel kuralım: __repr__geliştiriciler __str__için, müşteriler için.


2
Bu doğrudur çünkü obj = uuid.uuid1 () için obj .__ str __ () "2d7fc7f0-7706-11e9-94ae-0242ac110002" ve obj .__ repr __ () "UUID ('2d7fc7f0-7706-11e9-94ae-0242ac000) ')". Geliştiricilerin (değer + köken), müşterilerin bir değere ihtiyacı vardır ve bunu nasıl elde ettikleri umurumda değil!
Naren Yellavula

1
Burada müşteri mutlaka son kullanıcı anlamına gelmeyebilir. Nesnenin istemcisi veya kullanıcısıdır. Yani bir SDK ise, SDK geliştiricileri __str__normal geliştiricilerin okunabilir nesneye sahip olacakları şekilde kullanırlar . Öte yandan, __repr__SDK geliştiricileri içindir.
Shiplu Mokaddim

398

Özellikle aksini sağlamak için hareket etmediğiniz sürece, çoğu sınıf aşağıdakiler için yararlı sonuçlara sahip değildir:

>>> class Sic(object): pass
... 
>>> print str(Sic())
<__main__.Sic object at 0x8b7d0>
>>> print repr(Sic())
<__main__.Sic object at 0x8b7d0>
>>> 

Gördüğünüz gibi - fark yok, sınıf ve nesnenin ötesinde bilgi yok id. İkisinden yalnızca birini geçersiz kılarsanız ...:

>>> class Sic(object): 
...   def __repr__(object): return 'foo'
... 
>>> print str(Sic())
foo
>>> print repr(Sic())
foo
>>> class Sic(object):
...   def __str__(object): return 'foo'
... 
>>> print str(Sic())
foo
>>> print repr(Sic())
<__main__.Sic object at 0x2617f0>
>>> 

Gördüğünüz gibi, geçersiz kılarsanız __repr__, AYRICA kullanılır __str__, ancak tam tersi değildir.

Bilmeniz gereken diğer önemli bilgiler: Yerleşik __str__bir kapta, içerdiği öğeler için __repr__DEĞİL, kullanılır __str__. Ve, tipik dokümanlardaki konuyla ilgili kelimelere rağmen, __repr__nesnelerin yapılmasını neredeyse hiç kimse, evaleşit bir nesne oluşturmak için kullanılabilecek bir dize yapıyor (çok zor ve VEYA ilgili modülün gerçekten nasıl içe aktarıldığını bilmemek aslında düz dışarı imkansız).

Bu yüzden tavsiyem: __str__makul bir __repr__şekilde okunabilir ve olabildiğince açık hale getirmeye odaklanın, bu __repr__geri dönüşü olmayan değeri giriş olarak kabul edilebilir kılmak için bulanık ulaşılamaz hedefe müdahale etse bile __eval__!


34
Birim testlerimde daima eval(repr(foo))bir nesneye eşit olduğunu değerlendiriyorum foo. Bunu benim test vakalarının değil iş dışında ben modül içe nasıl bilmiyorum çünkü bu doğru, ama bu az teminat altın azından çalıştığını bazı öngörülebilir bağlamda. Bunun sonucunun __repr__yeterince açık olup olmadığını değerlendirmenin iyi bir yolu olduğunu düşünüyorum . Bunu birim testinde __repr__yapmak, sınıfta yapılan değişikliklerin takip edilmesini de sağlar.
Steven T. Snyder

4
Her zaman ya eval(repr(spam)) == spam(en azından doğru bağlamda) ya eval(repr(spam))da a SyntaxError. Bu şekilde karışıklığı önlersiniz. (Ve bu neredeyse nerede, örneğin yinelemeli listeleri, builtins için doğru ve dışında stdlib çoğu a=[]; a.append(a); print(eval(repr(a)))verir [[Ellipses]]Tabii ki ben aslında hiç böyle yapma ...) kullanmak eval(repr(spam)) birim testlerinde bir sağlamlık denetimi dışında, ... ama do bazen kopyalayıp yapıştırın repr(spam)interaktif oturumuna.
abarnert

Kaplar (listeler, tupler) neden __str__her öğe için kullanılmasın __repr__? Nesneme okunabilir bir uygulama uyguladığım __str__ve listenin bir parçası olduğu zaman bunun __repr__yerine uglier'ı görüyorum .
SuperGeo

Sadece eval(repr(x))yerleşik türler için bile başarısız class A(str, Enum): X = 'x'olmasıyla ilgili sinir bozucu bir hatayla karşılaştım : SyntaxError'ı yükseltir eval(repr(A.X)). Üzücü ama anlaşılabilir. BTW, eval(str(A.X))aslında işe yarıyor, ancak elbette sadece class Akapsam dahilindeyse - bu yüzden muhtemelen çok yararlı değil.
en fazla

@SuperGeo Diğer cevaplar bunu kapsar: konteyner strkullanım öğesi reprçünkü [1, 2, 3]! = ["1", "2, 3"].
mtraceur

163

__repr__: genellikle eval python nesnesinin temsili onu tekrar bu nesneye dönüştürür

__str__: bu metin biçimindeki nesnenin ne olduğunu düşünüyorsunuz

Örneğin

>>> s="""w'o"w"""
>>> repr(s)
'\'w\\\'o"w\''
>>> str(s)
'w\'o"w'
>>> eval(str(s))==s
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1
    w'o"w
       ^
SyntaxError: EOL while scanning single-quoted string
>>> eval(repr(s))==s
True

151

Kısacası, amacı __repr__açık olmak ve __str__okunabilir olmaktır.

İşte iyi bir örnek:

>>> import datetime
>>> today = datetime.datetime.now()
>>> str(today)
'2012-03-14 09:21:58.130922'
>>> repr(today)
'datetime.datetime(2012, 3, 14, 9, 21, 58, 130922)'

Repr için bu belgeleri okuyun:

repr(object)

Bir nesnenin yazdırılabilir temsilini içeren bir dize döndürür. Bu, dönüşümlerden (ters tırnak) elde edilen değerle aynıdır. Bu işleme normal bir işlev olarak erişebilmek bazen yararlı olabilir. Birçok tür için bu işlev, iletildiğinde aynı değere sahip bir nesneyi verecek bir dize döndürme girişiminde bulunur eval(), aksi takdirde temsil, nesnenin türünün adını ek bilgilerle birlikte içeren açılı parantez içine alınmış bir dizedir genellikle nesnenin adı ve adresini içerir. Bir sınıf, bir __repr__()yöntem tanımlayarak bu işlevin örnekleri için ne döndürdüğünü denetleyebilir .

İşte str için belgeler:

str(object='')

Bir nesnenin güzel yazdırılabilir bir gösterimini içeren bir dize döndürün. Dizeler için bu, dizenin kendisini döndürür. İle farkı repr(object)DİR str(object)her zaman kabul edilebilir bir dize döndürür etmeye çalışmaz eval(); hedefi yazdırılabilir bir dize döndürmektir. Herhangi bir argüman verilmezse, boş dizeyi döndürür ''.


1
Burada yazdırılabilir dizginin anlamı nedir? Açıklayabilir misiniz lütfen?
Vicrobot

115

Arasındaki fark nedir __str__ve __repr__Python?

__str__("dunder (çift alt çizgi) dizesi" __repr__olarak oku ) ve ("dunder-repper" olarak okunur ("temsil" için)), her ikisi de nesnenin durumuna göre dizeleri döndüren özel yöntemlerdir.

__repr____str__eksikse yedekleme davranışı sağlar .

Bu yüzden, önce __repr__, örneğin evalbir Python kabuğunda karakter için karakter kullanarak veya yazarak döndürdüğü dizeden eşdeğer bir nesneyi eski haline getirmenize izin veren bir yazmalısınız .

Herhangi bir zamanda __str__, örneğin gerekli olduğuna inandığında, örneğin kullanıcı tarafından okunabilir bir dize temsili için bir yazı yazılabilir .

__str__

Bir nesneyi yazdırmak veya başarılı olursa etmek format, str.formatya da str, bir o zaman __str__yöntem tanımlanır, bu yöntem adı verilecek, aksi takdirde __repr__kullanılacaktır.

__repr__

__repr__Yöntem yerleşik işlev tarafından çağrılır reprve bir nesne döndüren bir ifade olarak değerlendirilir zaman piton kabuk üzerinde yankılandı budur.

Yedekleme sağladığı için __str__, yalnızca bir tane yazabiliyorsanız,__repr__

İşte yerleşik yardım repr:

repr(...)
    repr(object) -> string

    Return the canonical string representation of the object.
    For most object types, eval(repr(object)) == object.

Diğer bir deyişle, çoğu nesne için, yazdırılan şeyi repryazarsanız, eşdeğer bir nesne oluşturabilmeniz gerekir. Ancak bu varsayılan uygulama değildir.

Varsayılan Uygulaması __repr__

Varsayılan nesne __repr__( C Python kaynağı ) şöyledir :

def __repr__(self):
    return '<{0}.{1} object at {2}>'.format(
      self.__module__, type(self).__name__, hex(id(self)))

Bu, varsayılan olarak nesnenin bulunduğu modülü, sınıf adını ve bellekteki konumunun onaltılı gösterimini yazdıracağınız anlamına gelir - örneğin:

<__main__.Foo object at 0x7f80665abdd0>

Bu bilgi çok kullanışlı değildir, ancak herhangi bir örneğin kanonik bir temsilini nasıl doğru bir şekilde oluşturabileceğini ortaya çıkarmanın bir yolu yoktur ve en azından bize bunu bellekte nasıl benzersiz bir şekilde tanımlayabileceğimizi söyler.

Nasıl __repr__faydalı olabilir ?

Python kabuğunu ve datetimenesnelerini kullanarak ne kadar yararlı olabileceğine bakalım . İlk önce datetimemodülü içe aktarmamız gerekiyor :

import datetime

Biz ararsanız datetime.nowkabuğunda, biz eşdeğer datetime nesnesi yeniden için gereken her şeyi göreceksiniz. Bu datetime tarafından oluşturulur __repr__:

>>> datetime.datetime.now()
datetime.datetime(2015, 1, 24, 20, 5, 36, 491180)

Tarih-saat nesnesi yazdırırsak, hoş bir insan tarafından okunabilir (aslında ISO) formatı görürüz. Bu datetime tarafından uygulanır __str__:

>>> print(datetime.datetime.now())
2015-01-24 20:05:44.977951

Çıkardığımız nesneyi yeniden oluşturmak basit bir konudur çünkü __repr__çıktıyı kopyalayıp yapıştırarak ve sonra yazdırarak bir değişkene atamadık ve onu diğer nesne ile aynı insan tarafından okunabilir çıktıda elde ettik:

>>> the_past = datetime.datetime(2015, 1, 24, 20, 5, 36, 491180)
>>> print(the_past)
2015-01-24 20:05:36.491180

Bunları nasıl uygularım?

Geliştirirken, mümkünse aynı durumdaki nesneleri çoğaltmak isteyeceksiniz. Örneğin, datetime nesnesinin __repr__( Python kaynağı ) nasıl tanımlandığıdır . Böyle bir nesneyi yeniden üretmek için gereken tüm nitelikler nedeniyle oldukça karmaşıktır:

def __repr__(self):
    """Convert to formal string, for repr()."""
    L = [self._year, self._month, self._day,  # These are never zero
         self._hour, self._minute, self._second, self._microsecond]
    if L[-1] == 0:
        del L[-1]
    if L[-1] == 0:
        del L[-1]
    s = "%s.%s(%s)" % (self.__class__.__module__,
                       self.__class__.__qualname__,
                       ", ".join(map(str, L)))
    if self._tzinfo is not None:
        assert s[-1:] == ")"
        s = s[:-1] + ", tzinfo=%r" % self._tzinfo + ")"
    if self._fold:
        assert s[-1:] == ")"
        s = s[:-1] + ", fold=1)"
    return s

Nesnenin daha insan tarafından okunabilir bir temsile sahip olmasını istiyorsanız, bir __str__sonraki uygulamayı uygulayabilirsiniz . Datetime nesnesinin ( Python kaynağı ) __str__, ISO biçiminde görüntüleme işlevine zaten sahip olduğu için kolayca uyguladığı :

def __str__(self):
    "Convert to string, for str()."
    return self.isoformat(sep=' ')

Set __repr__ = __str__?

Bu, ayarlamayı öneren başka bir cevabın eleştirisidir __repr__ = __str__.

Ayar __repr__ = __str__saçma - __repr__bir geri dönüş olduğunu __str__ve bir __repr__, yazılmalıdır ayıklama geliştiricilerin kullanım için yazılı bir yazmadan önce __str__.

Bir ihtiyaç __str__nesnenin metin biçimini gerektiğinde sadece.

Sonuç

__repr__Yazdığınız nesneler için tanımlayın , böylece siz ve diğer geliştiriciler, geliştirirken kullanırken yeniden üretilebilir bir örneğe sahip olursunuz. __str__İnsan tarafından okunabilir bir dize gösterimine ihtiyacınız olduğunda tanımlayın .


Çizgisinde bir şey olmamalı mı type(obj).__qualname__?
Solomon Ucko

@SolomonUcko evet Python 3, durum böyle görünüyor - bunun uygulandığı kaynak kodunu avladım ve bir araya geldiğimde bu bilgilerle cevabımı güncelleyeceğim.
Aaron Hall

33

Hans Petter Langtangen'in hesaplama bilimi için Python senaryosu kitabının 358. sayfasında ,

  • __repr__Nesnenin tam bir dize gösterimi de amaçları;
  • __str__Baskı için güzel bir dize döndürmektir.

Bu yüzden onları

  • repr = çoğalt
  • str = string (gösterim)

Her ne kadar bu python öğrenirken yaptığım bir yanlış anlama olsa da kullanıcının bakış açısından.

Aynı sayfada küçük ama iyi bir örnek de şu şekilde verilmiştir:

Misal

In [38]: str('s')
Out[38]: 's'

In [39]: repr('s')
Out[39]: "'s'"

In [40]: eval(str('s'))
Traceback (most recent call last):

  File "<ipython-input-40-abd46c0c43e7>", line 1, in <module>
    eval(str('s'))

  File "<string>", line 1, in <module>

NameError: name 's' is not defined


In [41]: eval(repr('s'))
Out[41]: 's'

O pg. # 351.
jiten

4
reprÜreme olarak adlandırmak bir tür yanıltıcıdır . Bunu temsil olarak düşünmek daha iyidir.
NelsonGon

31

Verilen tüm cevaplar dışında, birkaç nokta eklemek istiyorum: -

1) __repr__()etkileşimli python konsoluna nesnenin adını yazıp enter tuşuna bastığınızda çağrılır.

2) __str__()print deyimli bir nesne kullandığınızda çağrılır.

3) Eksikse , nesne çağırma __str__işlevini kullanarak yazdırın ve herhangi bir işlev .str()__repr__()

4) __str__()konteynırlar, çağrıldığında __repr__()içerdiği elemanların yöntemini uygulayacaktır.

5) str()içeride çağrılan __str__(), bir temel durum olmadan potansiyel olarak tekrarlanabilir ve maksimum özyineleme derinliğinde hata olabilir.

6) __repr__()arayabilir repr()ile önceden temsil nesne yerine, otomatik olarak sonsuz özyinelemeye önlemek için çalışacaktır olan ....


14

Basitçe söylemek gerekirse:

__str__, başkaları tarafından kolayca okunacak nesnenizin dize olarak temsilini göstermek için kullanılır .

__repr__bir dize temsilini göstermek için kullanılır nesne.

Diyelim ki Fractionbir kesirin dize temsili '(1/2)' ve nesne (Kesir sınıfı) 'Kesir (1,2)' olarak gösterilecek bir sınıf oluşturmak istiyorum.

Böylece basit bir Kesir sınıfı oluşturabiliriz:

class Fraction:
    def __init__(self, num, den):
        self.__num = num
        self.__den = den

    def __str__(self):
        return '(' + str(self.__num) + '/' + str(self.__den) + ')'

    def __repr__(self):
        return 'Fraction (' + str(self.__num) + ',' + str(self.__den) + ')'



f = Fraction(1,2)
print('I want to represent the Fraction STRING as ' + str(f)) # (1/2)
print('I want to represent the Fraction OBJECT as ', repr(f)) # Fraction (1,2)

13

Dürüst olmak gerekirse, eval(repr(obj))asla kullanılmaz. Kendinizi kullanırken bulursanız, durmalısınız, çünkü evaltehlikelidir ve dizeler nesnelerinizi serileştirmek için çok verimsiz bir yoldur ( picklebunun yerine kullanın).

Bu nedenle, ayar tavsiye ederim __repr__ = __str__. Bunun nedeni ise str(list)çağrılar reprunsurları (Ben bunu göz önünde Python 3 ile giderilmeyen Python en büyük tasarım kusurları biri olarak). Bir gerçek reprmuhtemelen çıktı olarak çok yararlı olmayacaktır print [your, objects].

Bunu nitelemek için, benim durumumda, reprişlevin en kullanışlı kullanım durumu, başka bir dizenin içine bir dize koymaktır (dize biçimlendirme kullanarak). Bu şekilde, tırnak işareti ya da başka bir şeyden endişe etmenize gerek kalmaz. Ama burada bir şey olmadığını unutmayın eval.


19
Bence bu noktayı kaçırıyor. Kullanımı eval(repr(obj))bir akıl sağlığı testi ve genel bir kuraldır - bu orijinal nesneyi doğru bir şekilde yeniden oluşturuyorsa, iyi bir __repr__uygulamaya sahip olursunuz . Nesneleri bu şekilde serileştirmeniz amaçlanmamıştır.
jwg

7
evaldoğal olarak tehlikeli değildir. Daha tehlikeli değil mi unlink, openveya dosyalara yazma. Belki de kötü niyetli bir saldırı içeriği içeri koymak için rasgele bir dosya yolu kullanabileceğinden dosyalara yazmayı bırakmalı mıyız? Aptal insanlar tarafından aptalca kullanılıyorsa her şey tehlikelidir. Aptallık tehlikelidir. Dunning-Kruger etkileri tehlikelidir. evalsadece bir işlevdir.
Luis Masuelli


10

str - Verilen nesneden yeni bir dize nesnesi oluşturur.

repr - Nesnenin standart dize olarak temsilini döndürür.

Farklılıklar:

str ():

  • nesneyi okunabilir yapar
  • son kullanıcı için çıktı üretir

Repr ():

  • nesneyi yeniden üreten koda ihtiyaç var
  • geliştirici için çıktı üretir

8

Diğer cevaplarda eksik olan bir yön. Desenin genel olarak şu olduğu doğrudur:

  • Amaç __str__: insan tarafından okunabilir
  • Amaç __repr__: açık, muhtemelen makine tarafından okunabilireval

Ne yazık ki, bu farklılaşma kusurludur, çünkü Python REPL ve ayrıca IPython __repr__, bir REPL konsolundaki nesneleri yazdırmak için kullanır ( Python ve IPython için ilgili sorulara bakın ). Bu nedenle, etkileşimli konsol çalışması (örneğin, Numpy veya Pandalar) için hedeflenen projeler yukarıdaki kuralları göz ardı etmeye ve __repr__bunun yerine insan tarafından okunabilir bir uygulama sağlamaya başlamıştır .


7

Akıcı Python kitabından :

Python nesnesi için temel bir gereksinim, biri hata ayıklama ve günlük kaydı için kullanılan, diğeri son kullanıcılara sunum için kullanılabilen kullanılabilir dize temsillerini sağlamaktır. Bu nedenle veri
yönteminde özel yöntemler __repr__ve __str__varlıklar bulunmaktadır.


5

Mükemmel cevaplar zaten benim için son kullanıcı tarafından bile okunabilir ve ikincisi geliştiriciler için olabildiğince yararlı olan __str__ve arasındaki farkı kapsıyor __repr__. Bununla birlikte, varsayılan olarak uygulanmasının __repr__bu hedefe ulaşmada başarısız olduğunu düşünüyorum, çünkü geliştiriciler için yararlı bilgileri atlıyor .

Bu nedenle, yeterince basit bir şeyim varsa __str__, genellikle sadece her iki dünyanın en iyisini elde etmeye çalışırım:

def __repr__(self):
    return '{0} ({1})'.format(object.__repr__(self), str(self))

4

Akılda tutulması gereken önemli bir şey, kabın __str__içerdiği nesneleri kullanmasıdır __repr__.

>>> from datetime import datetime
>>> from decimal import Decimal
>>> print (Decimal('52'), datetime.now())
(Decimal('52'), datetime.datetime(2015, 11, 16, 10, 51, 26, 185000))
>>> str((Decimal('52'), datetime.now()))
"(Decimal('52'), datetime.datetime(2015, 11, 16, 10, 52, 22, 176000))"

Python okunabilirliği üzerinde net gösterilmesini yana , __str__bir çağrı tupleçağrıları bulunan nesneleri __repr__, 'resmi' bir nesnenin temsili. Resmi temsili gayri resmi bir sunumdan daha zor okumakla birlikte, açık ve hatalara karşı daha sağlamdır.


O kullanır __repr__ o (zaman __str__) tanımlı değil! Yani yanılıyorsunuz.
jiten

4

Kısaca:

class Demo:
  def __repr__(self):
    return 'repr'
  def __str__(self):
    return 'str'

demo = Demo()
print(demo) # use __str__, output 'str' to stdout

s = str(demo) # __str__ is used, return 'str'
r = repr(demo) # __repr__ is used, return 'repr'

import logging
logger = logging.getLogger(logging.INFO)
logger.info(demo) # use __str__, output 'str' to stdout

from pprint import pprint, pformat
pprint(demo) # use __repr__, output 'repr' to stdout
result = pformat(demo) # use __repr__, result is string which value is 'str'

4
>>> print(decimal.Decimal(23) / decimal.Decimal("1.05"))
21.90476190476190476190476190
>>> decimal.Decimal(23) / decimal.Decimal("1.05")
Decimal('21.90476190476190476190476190')

Ne zaman print()bir sonucu olarak adlandırılır decimal.Decimal(23) / decimal.Decimal("1.05")ham sayı basılır; bu çıktı ile elde edilebilen dize biçimindedir__str__() . Sadece ifadeye girersek bir decimal.Decimalçıktı alırız - bu çıktı elde edilebilecek temsili formdadır__repr__() . Tüm Python nesnelerinin iki çıktı formu vardır. Dize formu, insanların okuyabileceği şekilde tasarlanmıştır. Temsili form, bir Python yorumlayıcısına beslendiğinde (mümkünse) temsil edilen nesneyi yeniden üretecek çıktı üretmek için tasarlanmıştır.


4

__str__bir nesne üzerinde çağrılarak çağrılabilir str(obj)ve okunabilir bir dize döndürmelidir.

__repr__çağrılarak bir nesneye çağrılabilir repr(obj)ve dahili nesneyi (nesne alanları / öznitelikleri) döndürmelidir

Bu örnek yardımcı olabilir:

class C1:pass

class C2:        
    def __str__(self):
        return str(f"{self.__class__.__name__} class str ")

class C3:        
    def __repr__(self):        
         return str(f"{self.__class__.__name__} class repr")

class C4:        
    def __str__(self):
        return str(f"{self.__class__.__name__} class str ")
    def __repr__(self):        
         return str(f"{self.__class__.__name__} class repr")


ci1 = C1()    
ci2 = C2()  
ci3 = C3()  
ci4 = C4()

print(ci1)       #<__main__.C1 object at 0x0000024C44A80C18>
print(str(ci1))  #<__main__.C1 object at 0x0000024C44A80C18>
print(repr(ci1)) #<__main__.C1 object at 0x0000024C44A80C18>
print(ci2)       #C2 class str
print(str(ci2))  #C2 class str
print(repr(ci2)) #<__main__.C2 object at 0x0000024C44AE12E8>
print(ci3)       #C3 class repr
print(str(ci3))  #C3 class repr
print(repr(ci3)) #C3 class repr
print(ci4)       #C4 class str 
print(str(ci4))  #C4 class str 
print(repr(ci4)) #C4 class repr

3

Anlayın __str__ve __repr__sezgisel ve kalıcı olarak ayırt edin.

__str__belirli bir nesnenin dize gizlenmiş gövdesini gözlerin okunabilir olması için
__repr__döndürmek Belirsizliğin tanımlanması için belirli bir nesnenin gerçek bedenini döndürür (kendini döndür).

Bir örnekte görün

In [30]: str(datetime.datetime.now())
Out[30]: '2017-12-07 15:41:14.002752'
Disguised in string form

Benzer __repr__

In [32]: datetime.datetime.now()
Out[32]: datetime.datetime(2017, 12, 7, 15, 43, 27, 297769)
Presence in real body which allows to be manipulated directly.

__repr__Sonuçlar üzerinde aritmetik işlem yapabiliriz .

In [33]: datetime.datetime.now()
Out[33]: datetime.datetime(2017, 12, 7, 15, 47, 9, 741521)
In [34]: datetime.datetime(2017, 12, 7, 15, 47, 9, 741521) - datetime.datetime(2
    ...: 017, 12, 7, 15, 43, 27, 297769)
Out[34]: datetime.timedelta(0, 222, 443752)

operasyonu __str__

In [35]: '2017-12-07 15:43:14.002752' - '2017-12-07 15:41:14.002752'
TypeError: unsupported operand type(s) for -: 'str' and 'str'

Hata dışında hiçbir şey döndürmez.

Başka bir örnek.

In [36]: str('string_body')
Out[36]: 'string_body' # in string form

In [37]: repr('real_body')
Out[37]: "'real_body'" #its real body hide inside

Umarım bu, daha fazla cevabı keşfetmek için somut temeller oluşturmanıza yardımcı olur.


3
  1. __str____repr__herhangi bir python ifadesi döndürebilir, ancak dize nesnesi döndürmelidir.
  2. Eğer __str__uygulama daha sonra eksik olan __repr__işlev yedek olarak kullanılır. __repr__İşlev uygulaması eksikse bir geri dönüş yoktur .
  3. Eğer __repr__fonksiyon nesnenin String temsilini dönüyor, biz uygulanmasını atlayabilirsiniz __str__fonksiyonu.

Kaynak: https://www.journaldev.com/22460/python-str-repr-functions


2

__repr__printve stryöntemleri dışında her yerde kullanılır (a __str__tanımlandığında!)

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.