Yanıtlar:
Alex iyi özetledi ama şaşırtıcı bir şekilde çok kısa ve özdü.
İlk olarak, Alex'in gönderisindeki ana noktaları tekrarlayayım :
__repr__
hedef açık olmak__str__
amaç okunabilir olmak__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, c
yine 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: %r
Yukarıda kullandım , değil %s
. Her zaman uygulama içinde repr()
[veya %r
biç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 .
__repr__
ben ayıklama için gerekli oldu. Yardımın için teşekkürler.
Temel kuralım: __repr__
geliştiriciler __str__
için, müşteriler için.
__str__
normal geliştiricilerin okunabilir nesneye sahip olacakları şekilde kullanırlar . Öte yandan, __repr__
SDK geliştiricileri içindir.
Ö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, eval
eş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__
!
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.
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.
__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 .
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 A
kapsam dahilindeyse - bu yüzden muhtemelen çok yararlı değil.
str
kullanım öğesi repr
çünkü [1, 2, 3]
! = ["1", "2, 3"]
.
__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
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İRstr(object)
her zaman kabul edilebilir bir dize döndürür etmeye çalışmazeval()
; hedefi yazdırılabilir bir dize döndürmektir. Herhangi bir argüman verilmezse, boş dizeyi döndürür''
.
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 eval
bir 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.format
ya 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 repr
ve 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 repr
yazarsanız, eşdeğer bir nesne oluşturabilmeniz gerekir. Ancak bu varsayılan uygulama değildir.
__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.
__repr__
faydalı olabilir ?Python kabuğunu ve datetime
nesnelerini kullanarak ne kadar yararlı olabileceğine bakalım . İlk önce datetime
modülü içe aktarmamız gerekiyor :
import datetime
Biz ararsanız datetime.now
kabuğ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
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=' ')
__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.
__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 .
type(obj).__qualname__
?
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ı
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:
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'
repr
Üreme olarak adlandırmak bir tür yanıltıcıdır . Bunu temsil olarak düşünmek daha iyidir.
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 ...
.
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 Fraction
bir 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)
Dürüst olmak gerekirse, eval(repr(obj))
asla kullanılmaz. Kendinizi kullanırken bulursanız, durmalısınız, çünkü eval
tehlikelidir ve dizeler nesnelerinizi serileştirmek için çok verimsiz bir yoldur ( pickle
bunun yerine kullanın).
Bu nedenle, ayar tavsiye ederim __repr__ = __str__
. Bunun nedeni ise str(list)
çağrılar repr
unsurları (Ben bunu göz önünde Python 3 ile giderilmeyen Python en büyük tasarım kusurları biri olarak). Bir gerçek repr
muhtemelen çıktı olarak çok yararlı olmayacaktır print [your, objects]
.
Bunu nitelemek için, benim durumumda, repr
iş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
.
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.
eval
doğal olarak tehlikeli değildir. Daha tehlikeli değil mi unlink
, open
veya 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. eval
sadece bir işlevdir.
Gönderen bir (An resmi olmayan) Python Referans Wiki (arşiv kopya) effbot tarafından:
__str__
" bir nesnenin" gayri resmi "dize temsilini hesaplar. Bu __repr__
, geçerli bir Python ifadesi olması gerekmediğinden farklıdır : bunun yerine daha uygun veya kısa bir gösterim kullanılabilir. "
__repr__
boş bir Python ifadesi döndürmek için hiçbir şekilde gerekli değildir.
str
- Verilen nesneden yeni bir dize nesnesi oluşturur.
repr
- Nesnenin standart dize olarak temsilini döndürür.
Farklılıklar:
str ():
Repr ():
Diğer cevaplarda eksik olan bir yön. Desenin genel olarak şu olduğu doğrudur:
__str__
: insan tarafından okunabilir__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 .
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.
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))
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.
__repr__
o (zaman __str__
) tanımlı değil! Yani yanılıyorsunuz.
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'
>>> 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.
__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
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.
__str__
__repr__
herhangi bir python ifadesi döndürebilir, ancak dize nesnesi döndürmelidir.__str__
uygulama daha sonra eksik olan __repr__
işlev yedek olarak kullanılır. __repr__
İşlev uygulaması eksikse bir geri dönüş yoktur .__repr__
fonksiyon nesnenin String temsilini dönüyor, biz uygulanmasını atlayabilirsiniz __str__
fonksiyonu.Kaynak: https://www.journaldev.com/22460/python-str-repr-functions