Python __str__ e listas


107

Em Java, se eu chamar List.toString (), ele chamará automaticamente o método toString () em cada objeto dentro da Lista. Por exemplo, se minha lista contiver objetos o1, o2 e o3, list.toString () seria algo assim:

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

Existe uma maneira de obter um comportamento semelhante em Python? Implementei um método __str __ () em minha classe, mas quando imprimo uma lista de objetos, usando:

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

parece algo assim:

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

como posso fazer com que o python chame meu __str__ automaticamente para cada elemento dentro da lista (ou dict para esse assunto)?


Apenas para referência, existe o PEP 3140: "str (container) deve chamar str (item), não repr (item)" , que foi rejeitado.
— Alexey

Respostas:


133

Chamar string em uma lista python chama o __repr__método em cada elemento interno. Para alguns itens, __str__e __repr__são iguais. Se você deseja esse comportamento, faça:

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

7
Identificar __str__com __repr__geralmente não concorda com o modelo de dados Python , então a solução de compreensão de lista proposta por @ daniel-lew é mais pythônica.
— Ioannis Filippidis

2
Sem discussão. Respondi à pergunta conforme perguntado, que geralmente é como um novato em python deseja pensar no problema, mas isso não significa que essa é a melhor maneira de responder.
— David Berger

1
Python deve ser consistente com seu próprio modelo de dados e fazer a mesma coisa para todos os primitivos e agregados.
— Terrence Brannon,

2
Eu acho que o comportamento padrão para listas python é totalmente errado. Eu esperaria isso str()em uma lista retornada str()para cada um dos elementos individuais dentro.
— SuperGeo

21

Você pode usar uma compreensão de lista para gerar uma nova lista com cada item str () 'd automaticamente:

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

6
Ou apenas print(map(str, mylist))- é um pouco mais curto
— anula de

4
Um problema com isso é se o item em minha lista também pode ser uma lista
— Breandán Dalton

7

Duas coisas fáceis que você pode fazer, usar a mapfunção ou usar uma compreensão.

Mas isso dá a você uma lista de strings, não uma string. Portanto, você também precisa juntar as cordas.

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

ou

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

Em seguida, você pode imprimir este objeto de string composto.

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

4

Dependendo da finalidade para a qual você deseja usar essa saída, talvez __repr__seja mais apropriado:

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

Eu concordo com a resposta anterior sobre o uso de compreensões de lista para fazer isso, mas você certamente poderia esconder isso atrás de uma função, se é isso que faz seu barco flutuar.

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]

Apenas por diversão, fiz list_str () recursivamente str () tudo contido na lista.


+1 Isso é útil ao implementar __str__e __repr__separadamente
— vincent gravitas


0

Isso deve bastar.

Ao imprimir listas, bem como outras classes de contêineres, os elementos contidos serão impressos usando __repr__, porque __repr__deve ser usado para representação de objetos internos. Se ligarmos: help(object.__repr__)ele nos dirá:

Help on wrapper_descriptor:

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

E se chamarmos help(repr), a saída será:

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.

Se __str__for implementado para um objeto e __repr__não for repr(obj), produzirá a saída padrão, assim como print(obj)quando nenhum desses for implementado.

Portanto, a única maneira é implementar __repr__para sua classe. Uma maneira possível de fazer isso é:

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

A saída que você está obtendo é apenas o nome do módulo do objeto, o nome da classe e o endereço da memória em hexadecimal como o __repr__ função não é substituída.

__str__é usado para a representação de string de um objeto ao usar imprimir. Mas como você está imprimindo uma lista de objetos, e não iterando a lista para chamar o strmétodo para cada item, ele imprime a representação dos objetos.

Para ter a __str__função invocada, você precisa fazer algo assim:

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

Se você substituir a __repr__função, poderá usar o método de impressão como fazia antes:

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

Então você obterá " my list is [1, 2, 3]" como sua saída.


Esta resposta parece responder a uma pergunta completamente não relacionada. Tem certeza de que o colocou no lugar certo?
— Blckknght

Sim, Blckconhecia esta página que eu queria dar a minha resposta tinha um link para esta página de outro post. então me guiou aqui e eu respondo aqui supondo que o cara que fez a pergunta venha aqui novamente e veja minha resposta ... desculpe por o inconveniente !!!
— panagiwtis koligas

Se a outra pergunta foi fechada como uma duplicata desta, é como se presumisse que as respostas existentes aqui já deveriam cuidar da outra pergunta. Se esse não for o caso, você deve sinalizar para reabrir essa pergunta, em vez de postar uma resposta incompreensível aqui, que quase certamente será excluída. Agora, é possível que você tenha algo a dizer que não seja abordado por nenhuma das 8 outras respostas aqui, mas você precisa fazer sua resposta fazer sentido no contexto desta página, uma vez que é a esta pergunta que você está respondendo. E não poste duas respostas idênticas!
— Blckknght

1
Oh, embora agora que olhei para ele novamente, parece que @charliebeckwith editou sua postagem para ser completamente diferente, em vez de postar sua própria resposta, por algum motivo inexplicável. Normalmente não é assim que as edições funcionam ...
— Blckknght

@blckknght Eu comecei a editá-lo antes de perceber como a resposta estava errada. Completamente inexplicável porque eu continuei.
— charliebeckwith
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.