__Str__ ve __repr__'nin amacı nedir? [çiftleme]


83

Python'da nerede __str__ve nerede __repr__kullanıldığını gerçekten anlamıyorum . Demek istediğim, __str__bir nesnenin dize temsilini döndürdüğünü anlıyorum . Ama buna neden ihtiyacım olsun ki? Hangi kullanım senaryosunda? Ayrıca,__repr__

Ama anlamadığım şey, onları nerede kullanacağım?



4
Ruby'den gelen herkes için tl; dr şöyledir: __str__= to_sve __repr__= inspect.
Ajedi32

3
Bu sorunuzu yanıtlıyor mu? __Str__ ve __repr__ arasındaki fark?
xiaoou

Yanıtlar:


86

__repr__

repr()Bir nesnenin "resmi" dizgi temsilini hesaplamak için yerleşik işlev ve dize dönüşümleri (ters tırnak) tarafından çağrılır . Mümkünse, bu, aynı değere sahip bir nesneyi yeniden oluşturmak için kullanılabilecek geçerli bir Python ifadesi gibi görünmelidir (uygun bir ortam verildiğinde).

__str__

str()Bir nesnenin "gayri resmi" dizgi temsilini hesaplamak için yerleşik işlev ve print ifadesi tarafından çağrılır .

Kullanım __str__Bir sınıfı var ve dize bir parçası olarak bu nesneyi her kullandığınızda size, bilgilendirici / gayri çıkışını isteyeceksiniz eğer. Örneğin __str__, Django modelleri için yöntemler tanımlayabilirsiniz , bunlar daha sonra Django yönetim arayüzünde işlenir. Böyle bir şey yerine, <Model object>bir kişinin adı ve soyadı, bir olayın adı ve tarihi vb.


__repr__ve __str__benzerdir, aslında bazen eşittir ( Standart kitaplıktaki BaseSetsınıftan örnek sets.py):

def __repr__(self):
    """Return string representation of a set.

    This looks like 'Set([<list of elements>])'.
    """
    return self._repr()

# __str__ is the same as __repr__
__str__ = __repr__

1
Teşekkürler! Bu tam olarak aradığım şey!
Daniel

kodu çalıştırdığımda ve anlamaya çalıştığımda, __repr __ () tam olarak bir argüman aldığını söyleyerek `return self._repr () '' ne yapar.
parlıyor

Peki django __repr__yerine kullanabilir miyim __str__?
Amit Tripathi

61

İkisini de sıkça kullandığınız tek yer etkileşimli bir oturumdur. Bir nesneyi yazdırırsanız, __str__yöntemi çağrılır, oysa yalnızca bir nesneyi kullanırsanız, o zaman __repr__gösterilir:

>>> from decimal import Decimal
>>> a = Decimal(1.25)
>>> print(a)
1.25                  <---- this is from __str__
>>> a
Decimal('1.25')       <---- this is from __repr__

__str__Oysa insan tarafından okunabilir mümkün olduğunca olması amaçlanmıştır __repr__nesneyi yeniden oluşturmak için kullanılabilecek bir şey olmayı hedeflemelidir genellikle bu durumda olduğu gibi, oluşturulduğu tam olarak nasıl olmayacaktır rağmen,.

Ayrıca her ikisi için de alışılmadık bir durum değildir __str__ve __repr__aynı değeri döndürür (kesinlikle yerleşik türler için).


Örnek için teşekkürler, bana bunun varsayılan olarak nerede kullanıldığını daha iyi anlamamı
sağladı

17

Çekirge, şüphe duyduğunda dağa gider ve Antik Metinleri okuyun . Bunlarda __repr __ () 'in şunları yapması gerektiğini göreceksiniz:

Mümkünse, bu aynı değere sahip bir nesneyi yeniden oluşturmak için kullanılabilecek geçerli bir Python ifadesi gibi görünmelidir.


6
-1, çünkü bu gerçek soruyu cevaplamaya bile çalışmaz, kullanım durumları budur.
Scott Griffiths

4
@Scott: Haklısınız. Ama sonra yine asıl soru , ilk başta birincil belgelere gitme konusunda kesinlikle hiçbir girişim göstermedi. Kendiniz için cevap vermeye çalıştığınızı gösteren bir soru sormak bir şeydir, ancak yine de bazı yönleriyle ilgili biraz kafanız karışır ve buna benzer bir soru göndermek için başka bir şey. Konu satırına yeni bir soru yazmak, önerilen ilk 6 SO dizisinden 5'inin sorusunu yanıtlayacağını, ancak rahatsız olamayacağını gösteriyor. Ona kesin bir cevap vermedim, ama çok çekiciydim.
Peter Rowell

1
Aslında __repr__, hakkında okuduğunu söyledi , resmi dokümanlar soruyu neden kullanacağınıza dair gerçekten cevap vermiyor ve sırf bir sorunun başka bir yerde yanıtlanması, bunun da olmaması için iyi bir neden değil SO'da yanıtlandı (Google’ın sizi buraya geri getirmeyeceği sıklıkta!) Eğer sorunun yanıtlanmaya değer olduğunu düşünmüyorsanız, o zaman yanıtlayamazsınız, ancak bu durumda sorunun zaten çok iyi ele alındığını kabul ediyorum. SO ve böylece kopyalara bağlanmak uygun bir yanıt olacaktır.
Scott Griffiths

Aslında yanılıyorsun. Dokümanlar, bunu neden kullanacağınızı açıkça söyler: "Bu genellikle hata ayıklama için kullanılır, bu nedenle sunumun bilgi açısından zengin ve açık olması önemlidir." Yardım Vampirlerinin ağırlığı altında kalan çok fazla forum (fora?) Gördüm ve SO'dan geçmeye başladığını görmek beni üzüyor. Diğer bariz SO cevaplarına bağlanmaya gelince, Konu satırınızı yazarken devreye giren öneri mekanizmasının tüm amacı budur, ancak tüm önerileri görmezden gelmeyi seçmiştir. QED ve PDQ da.
Peter Rowell

5
Dokümanlar hala hata ayıklama için nasıl kullanılacağını söylemiyor , ama bununla ilgili bir tartışmaya girmek niyetinde değildim. En azından cevabınızın soruyu ele almadığına katılıyoruz, bu yüzden -1'im hala bana haklı geliyor. Bir soru kötü yazılmışsa / yineleniyorsa / önemsizse, soruyu iyileştirmeye yardımcı olabilir, tekrarlara bağlantı verebilir veya soruya olumsuz oy verebilirsiniz. Sanırım buradaki ana itirazım, cevapların soruyu cevaplamaya çalışması gerektiğidir - soruyu eleştirmek için başka mekanizmalar da vardır. Şimdi susacağım, çünkü ikimizin de burada yapacak daha iyi şeyleri olduğunu düşünüyorum.
Scott Griffiths

14

Önceki cevapları oluşturmak ve daha fazla örnek göstermek. Doğru kullanıldığında, arasındaki fark strve reprnet. Kısacası repr, nesnenin tam durumunu yeniden oluşturmak için kopyalanarak yapıştırılabilen bir dize döndürmelidir, oysa sonuçlar striçin loggingve observinghata ayıklama için yararlıdır . Bilinen bazı kütüphaneler için farklı çıktıları görmek için bazı örnekler.

Tarih saat

print repr(datetime.now())    #datetime.datetime(2017, 12, 12, 18, 49, 27, 134411)
print str(datetime.now())     #2017-12-12 18:49:27.134452

strGibi bir günlük dosyası içine yazdırmak için iyidir reprdoğrudan çalıştırmak veya bir dosyaya komutları olarak dökümü istiyorsanız yeniden amaçlı olabilir.

x = datetime.datetime(2017, 12, 12, 18, 49, 27, 134411)

Dizi

print repr(np.array([1,2,3,4,5])) #array([1, 2, 3, 4, 5])
print str(np.array([1,2,3,4,5]))  #[1 2 3 4 5]

Numpy'de repryine doğrudan tüketilebilir.

Özel Vector3 örneği

class Vector3(object):
    def __init__(self, args):
        self.x = args[0]
        self.y = args[1]
        self.z = args[2]

    def __str__(self):
        return "x: {0}, y: {1}, z: {2}".format(self.x, self.y, self.z)

    def __repr__(self):
        return "Vector3([{0},{1},{2}])".format(self.x, self.y, self.z)

Bu örnekte, reprdoğrudan tüketilebilen / çalıştırılabilen bir dize döndürür, oysa strbir hata ayıklama çıktısı olarak daha kullanışlıdır.

v = Vector3([1,2,3])
print str(v)     #x: 1, y: 2, z: 3
print repr(v)    #Vector3([1,2,3])

Bir şey varsa, akılda tutulması gereken strtanımlı değil ama repr, strotomatik arayacak repr. Yani, en azından tanımlamak her zaman iyidirrepr


5

__str__İşlevsiz bir sınıfa sahip olalım .

class Employee:

    def __init__(self, first, last, pay):
        self.first = first 
        self.last = last
        self.pay = pay

emp1 = Employee('Ivan', 'Smith', 90000)

print(emp1)

Sınıfın bu örneğini yazdırdığımızda emp1, şunu elde ederiz:

<__main__.Employee object at 0x7ff6fc0a0e48>

Bu çok yardımcı olmuyor ve görüntülemek için kullanıyorsak kesinlikle yazdırmak istediğimiz şey bu değil (html'deki gibi)

Şimdi, aynı sınıf, ancak __str__işlevle:

class Employee:

    def __init__(self, first, last, pay):
        self.first = first 
        self.last = last
        self.pay = pay

    def __str__(self):
        return(f"The employee {self.first} {self.last} earns {self.pay}.")
        # you can edit this and use any attributes of the class

emp2 = Employee('John', 'Williams', 90000)

print(emp2)

Şimdi bir nesnenin olduğunu yazdırmak yerine, __str__fonksiyon dönüşü ile belirttiğimiz şeyi elde ederiz :

The employee John Williams earns 90000


3

strresmi olmayan ve okunabilir formatta reprolacak, ancak resmi nesne temsili verecek.

class Complex:
    # Constructor
    def __init__(self, real, imag):
        self.real = real
        self.imag = imag

    # "official" string representation of an object
    def __repr__(self):
        return 'Rational(%s, %s)' % (self.real, self.imag)

    # "informal" string representation of an object (readable)
    def __str__(self):
        return '%s + i%s' % (self.real, self.imag)

    t = Complex(10, 20)

    print (t)     # this is usual way we print the object
    print (str(t))  # this is str representation of object 
    print (repr(t))  # this is repr representation of object   

Answers : 

Rational(10, 20) # usual representation
10 + i20      # str representation
Rational(10, 20)  # repr representation

1

str ve repr , temsil etmenin her iki yoludur. Bir sınıf yazarken bunları kullanabilirsiniz.

class Fraction:
def __init__(self, n, d):
    self.n = n
    self.d = d
def __repr__(self):
    return "{}/{}".format(self.n, self.d)

örneğin bir örneğini yazdırdığımda, bir şeyler döndürür.

print(Fraction(1, 2))

sonuçlanır

1/2

süre

class Fraction:
def __init__(self, n, d):
    self.n = n
    self.d = d
def __str__(self):
    return "{}/{}".format(self.n, self.d)
print(Fraction(1, 2))

ayrıca sonuçlanır

1/2

Peki ya ikisini de yazarsanız, python hangisini kullanır?

class Fraction:
def __init__(self, n, d):
    self.n = n
    self.d = d
def __str__(self):
    return "str"
def __repr__(self):
    return "repr"

print(Fraction(None, None))

Bu sonuçlanır

str

Yani python aslında her ikisi de yazıldığında repr yöntemini değil str yöntemini kullanır .


0

Bir sınıfınız olduğunu ve bir örneği incelemek istediğinizi varsayalım, baskının pek yararlı bilgi vermediğini görüyorsunuz

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age


p1 = Person("John", 36)
print(p1)  # <__main__.Animal object at 0x7f9060250410>

Şimdi str içeren bir sınıf görün , örnek bilgilerini gösterir ve repr ile baskıya bile ihtiyacınız yoktur. Güzel değil mi?

class Animal:
    def __init__(self, color, age, breed):
        self.color = color
        self.age = age
        self.breed = breed

    def __str__(self):
        return f"{self.color} {self.breed} of age {self.age}"

    def __repr__(self):
        return f"repr : {self.color} {self.breed} of age {self.age}"


a1 = Animal("Red", 36, "Dog")
a1  # repr : Red Dog of age 36
print(a1)  # Red Dog of age 36
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.