Python __str__ i listy


107

W Javie, jeśli wywołam List.toString (), automatycznie wywoła metodę toString () dla każdego obiektu wewnątrz Listy. Na przykład, jeśli moja lista zawiera obiekty o1, o2 i o3, list.toString () wyglądałaby mniej więcej tak:

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

Czy istnieje sposób na uzyskanie podobnego zachowania w Pythonie? Zaimplementowałem metodę __str __ () w mojej klasie, ale kiedy wydrukuję listę obiektów, używając:

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

wygląda mniej więcej tak:

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

jak mogę zmusić Pythona do automatycznego wywoływania mojego __str__ dla każdego elementu na liście (lub dyktowania w tym przypadku)?


Odpowiedzi:


133

Wywołanie łańcucha znaków na liście w języku Python wywołuje __repr__metodę na każdym elemencie wewnątrz. W przypadku niektórych pozycji __str__i __repr__są takie same. Jeśli chcesz takiego zachowania, zrób:

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

7
Identyfikacja __str__z __repr__zwykle nie zgadza się z modelem danych Pythona , więc rozwiązanie do rozumienia list zaproponowane przez @ daniel-lew jest bardziej pythonowe.
— Ioannis Filippidis

2
Bez argumentów. Odpowiedziałem na pytanie tak, jak zostało zadane, czyli często nowicjusz w Pythonie chce pomyśleć o problemie, ale to nie znaczy, że jest to najlepszy sposób na odpowiedź.
— David Berger,

1
Python powinien być spójny ze swoim własnym modelem danych i robić to samo dla wszystkich prymitywów i agregatów.
— Terrence Brannon,

2
Myślę, że domyślne zachowanie list Pythona jest po prostu błędne. Spodziewałbym się, że str()na liście wróciło str()dla każdego z poszczególnych elementów wewnątrz.
— SuperGeo

21

Możesz użyć funkcji rozumienia list, aby automatycznie wygenerować nową listę z każdym elementem str () 'd:

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

6
Albo po prostu print(map(str, mylist))- jest trochę krótszy
— anula

4
Jednym z problemów jest to, że pozycja w mylist może być również listą
— Breandán Dalton

7

Dwie proste rzeczy, które możesz zrobić, użyj mapfunkcji lub użyj zrozumienia.

Ale to daje ci listę ciągów, a nie ciąg. Musisz więc połączyć ze sobą struny.

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

lub

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

Następnie możesz wydrukować ten złożony obiekt typu string.

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

4

W zależności od tego, do czego chcesz użyć tego wyniku, może __repr__być bardziej odpowiednie:

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

Zgadzam się z poprzednią odpowiedzią dotyczącą używania w tym celu wyrażeń listowych, ale z pewnością można by to ukryć za funkcją, jeśli to właśnie ona unosi łódź.

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]

Dla zabawy utworzyłem list_str () rekurencyjnie str () wszystko zawarte na liście.


+1 Jest to przydatne przy wdrażaniu __str__i __repr__osobno
— vincent gravitas


0

To powinno wystarczyć.

Podczas drukowania list, a także innych klas kontenerów, zawarte w nich elementy zostaną wydrukowane przy użyciu __repr__, ponieważ __repr__mają być używane do wewnętrznej reprezentacji obiektu. Jeśli zadzwonimy: help(object.__repr__)powie nam:

Help on wrapper_descriptor:

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

A jeśli zadzwonimy help(repr), wyświetli:

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.

Jeśli __str__jest zaimplementowane dla obiektu i __repr__nie jest repr(obj), wyprowadza domyślne wyjście, tak jak print(obj)wtedy, gdy żadne z nich nie jest zaimplementowane.

Więc jedynym sposobem jest wdrożenie __repr__dla swojej klasy. Można to zrobić w następujący sposób:

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

Dane wyjściowe, które otrzymujesz, to tylko nazwa modułu obiektu, nazwa klasy, a następnie adres pamięci w formacie szesnastkowym, ponieważ __repr__funkcja nie jest nadpisywana.

__str__służy do reprezentacji obiektu w postaci ciągu znaków podczas korzystania z funkcji print. Ale ponieważ drukujesz listę obiektów, a nie iterujesz po liście w celu wywołania strmetody dla każdego elementu, wypisuje reprezentację obiektów.

Aby wywołać __str__funkcję, musisz zrobić coś takiego:

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

Jeśli nadpisujesz __repr__funkcję, możesz użyć metody drukowania, tak jak poprzednio:

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

Otrzymasz wtedy „ my list is [1, 2, 3]” jako wyjście.


Ta odpowiedź wydaje się odpowiadać na zupełnie niepowiązane pytanie. Czy na pewno umieściłeś go we właściwym miejscu?
— Blckknght

tak Blckknght ta strona, na którą chciałem odpowiedzieć, miała link do tej strony z innego postu. więc poprowadziła mnie tutaj i odpowiadam tutaj, zakładając, że facet, który zadał pytanie, przyjdzie tutaj ponownie i zobaczy moją odpowiedź ... przepraszam za niedogodności !!!
— panagiwtis koligas

Jeśli drugie pytanie zostało zamknięte jako duplikat tego, to w pewnym sensie zakłada się, że istniejące tutaj odpowiedzi powinny już załatwić drugie pytanie. Jeśli tak nie jest, zamiast publikować tutaj niezrozumiałą odpowiedź, powinieneś zgłosić flagę, aby ponownie otworzyć to pytanie, a prawie na pewno zostanie ona usunięta. Możliwe, że masz coś do powiedzenia, czego nie obejmuje żadna z 8 innych odpowiedzi tutaj, ale musisz nadać jej sens w kontekście tej strony, ponieważ odpowiadasz na to pytanie. I nie publikuj dwóch identycznych odpowiedzi!
— Blckknght

1
Och, chociaż teraz, gdy patrzę na to ponownie, wygląda na to, że @charliebeckwith zredagował Twój post, aby był zupełnie inny, zamiast publikować własną odpowiedź, z jakiegoś niewytłumaczalnego powodu. Normalnie nie tak działają zmiany ...
— Blckknght

@blckknght Zacząłem go edytować, zanim zdałem sobie sprawę, jak błędna była odpowiedź. Całkowicie niewytłumaczalne, dlaczego kontynuowałem.
— charliebeckwith
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.