Python __str__ ve listeler


108

Java'da List.toString () 'i çağırırsam, List içindeki her nesne için otomatik olarak toString () yöntemini çağıracaktır. Örneğin, listem o1, o2 ve o3 nesnelerini içeriyorsa, list.toString () şunun gibi görünür:

"[" + o1.toString() + ", " + o2.toString() + ", " + o3.toString() + "]"

Python'da benzer davranışlar elde etmenin bir yolu var mı? Sınıfımda bir __str __ () yöntemi uyguladım, ancak şunu kullanarak bir nesne listesi yazdırdığımda:

print 'my list is %s'%(list)

şuna benzer:

[<__main__.cell instance at 0x2a955e95f0>, <__main__.cell instance at 0x2a955e9638>, <__main__.cell instance at 0x2a955e9680>]

Python'un listedeki her öğe için (veya bu konuda dikte) __str__'ımı otomatik olarak çağırmasını nasıl sağlayabilirim?


Yanıtlar:


134

Bir python listesindeki dizeyi çağırmak, __repr__içindeki her öğenin yöntemini çağırır . Bazı öğeler için, __str__ve __repr__aynıdır. Bu davranışı istiyorsanız, şunu yapın:

def __str__(self):
    ...
def __repr__(self):
    return self.__str__()

7
Tanımlama __str__ile __repr__genellikle kabul etmez Python veri modelinin @ daniel-Lew tarafından önerilen liste anlama çözüm daha pythonic yani.
Ioannis Filippidis

2
Tartışmasızdır. Soruyu sorulduğu gibi cevapladım, bu genellikle python'a yeni gelen bir kişinin problemi düşünmek istediği gibi, ancak bu cevaplamanın en iyi yolu olduğu anlamına gelmez.
David Berger

1
Python, kendi veri modeliyle tutarlı olmalı ve tüm ilkel öğeler ve kümeler için aynı şeyi yapmalıdır.
Terrence Brannon

2
Python listeleri için varsayılan davranış tamamen yanlış. İçerideki her bir öğe için str()dönen bir listede bunu beklerdim str().
SuperGeo

21

Her bir str () 'd öğesiyle otomatik olarak yeni bir liste oluşturmak için bir liste anlama özelliğini kullanabilirsiniz :

print([str(item) for item in mylist])

6
Ya da sadece print(map(str, mylist))- biraz daha kısa
anula

4

7

Yapabileceğiniz iki kolay şey, mapişlevi kullanmak veya bir kavrayış kullanmak.

Ama bu size bir dizi değil, dizelerin listesini verir. Yani dizeleri birlikte birleştirmelisiniz.

s= ",".join( map( str, myList ) )

veya

s= ",".join( [ str(element) for element in myList ] )

Daha sonra bu bileşik dize nesnesini yazdırabilirsiniz.

print 'my list is %s'%( s )

4

Bu çıktıyı ne için kullanmak istediğinize bağlı olarak, belki __repr__daha uygun olabilir:

import unittest

class A(object):
    def __init__(self, val):
        self.val = val

    def __repr__(self):
        return repr(self.val)

class Test(unittest.TestCase):
    def testMain(self):
        l = [A('a'), A('b')]
        self.assertEqual(repr(l), "['a', 'b']")

if __name__ == '__main__':
    unittest.main()

3

Bunu yapmak için liste anlamalarını kullanmakla ilgili önceki cevaba katılıyorum, ancak teknenizin yüzmesini sağlayan şey buysa, bunu kesinlikle bir işlevin arkasına saklayabilirsiniz.

def is_list(value):
    if type(value) in (list, tuple): return True
    return False

def list_str(value):
    if not is_list(value): return str(value)
    return [list_str(v) for v in value]

Sırf eğlence için list_str () i yinelemeli olarak str () listedeki her şeyi yaptım.


+1 Bu, uygularken __str__ve __repr__ayrı olarak kullanışlıdır
vincent gravitas


0

Bu yeterli olmalı.

Listeleri ve diğer kap sınıflarını yazdırırken, içerilen öğeler kullanılarak yazdırılacaktır __repr__, çünkü __repr__dahili nesne gösterimi için kullanılması amaçlanmıştır. Ararsak: help(object.__repr__)bize şunu söyleyecektir:

Help on wrapper_descriptor:

__repr__(self, /)
    Return repr(self).

Ve eğer çağırırsak help(repr)çıktı:

Help on built-in function repr in module builtins:

repr(obj, /)
    Return the canonical string representation of the object.

    For many object types, including most builtins, eval(repr(obj)) == obj.

Eğer __str__bir nesne için uygulanan ve __repr__değil repr(obj)çıktısı gibi varsayılan çıkış, print(obj)bunların sigara uygulandığında.

Yani tek yol, __repr__sınıfınız için uygulamaktır . Bunu yapmanın olası bir yolu şudur:

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

C.__repr__=C.__str__       
ci = C()    


print(ci)       #C class str 
print(str(ci))  #C class str 
print(repr(ci)) #C class str 

-3

Aldığınız çıktı yalnızca nesnenin modül adı, sınıf adı ve ardından __repr__işlev geçersiz kılınmadığından onaltılık olarak bellek adresidir .

__str__print kullanılırken bir nesnenin dizgi gösterimi için kullanılır. Ancak, bir nesne listesi yazdırdığınızdan ve strher öğe için yöntemi çağırmak üzere listeyi yinelemediğiniz için, nesnelerin temsilini yazdırır.

Sahip olmak __str__fonksiyonu böyle bir şey yapmak gerekiyordu çağrılan:

'my list is %s' % [str(x) for x in myList]

__repr__İşlevi geçersiz kılarsanız, yazdırma yöntemini daha önce olduğu gibi kullanabilirsiniz:

class cell:
    def __init__(self, id):
        self.id = id
    def __str__(self):
        return str(self.id) # Or whatever
    def __repr__(self):
        return str(self) # function invoked when you try and print the whole list.

myList = [cell(1), cell(2), cell(3)]
'my list is %s' % myList

Sonra my list is [1, 2, 3]çıktınız olarak " " alırsınız .


Bu yanıt, tamamen ilgisiz bir soruyu yanıtlıyor gibi görünüyor. Doğru yere koyduğunuzdan emin misiniz?
Blckknght

Evet Blck, cevabımı vermek istediğim bu sayfanın başka bir gönderiden bu sayfaya bir bağlantısı olduğunu düşündüm. bu yüzden beni buraya yönlendirdi ve soruyu soran adamın buraya tekrar gelip cevabımı göreceğini varsayarak cevap verdim ... rahatsızlık !!!
panagiwtis koligas

Eğer diğer soru bunun bir kopyası olarak kapatılmışsa, o zaman buradaki mevcut cevapların diğer soruyu halihazırda halletmesi gerektiği varsayılır . Durum bu değilse, burada anlaşılmaz bir cevap göndermek yerine bu soruyu tekrar açmak için işaretlemelisiniz, bu neredeyse kesinlikle silinecektir. Şimdi, söyleyeceğiniz ve buradaki diğer 8 cevaptan birinin kapsamadığı bir şeyiniz olabilir, ancak cevabınızı bu sayfa bağlamında mantıklı yapmanız gerekir, çünkü cevapladığınız soru budur. Ve aynı iki yanıtı göndermeyin!
Blckknght

1
Oh, şimdi tekrar baktığıma göre, görünen o ki @charliebeckwith, açıklanamayan bir nedenden ötürü kendi cevabını göndermek yerine tamamen farklı bir yayınınızı düzenledi. Düzenlemeler normalde böyle çalışmaz ...
Blckknght

@blckknght Cevabın ne kadar yanlış olduğunu fark etmeden önce düzenlemeye başladım. Neden devam ettiğim tamamen açıklanamaz.
charliebeck ile
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.