Смущен str в списке в Python [дубликат]


этот вопрос уже есть ответ здесь:

исходя из фона Java, я понимаю, что __str__ это что-то вроде версии Python toString (хотя я понимаю, что Python-это более старый язык).

Итак, я определил класс вместе с __str__ метод следующим образом:

class Node:

    def __init__(self, id):
        self.id = id
        self.neighbours = []
        self.distance = 0


    def __str__(self):
        return str(self.id)

затем я создаю несколько экземпляров этого:

uno = Node(1)    
due = Node(2)    
tri = Node(3)    
qua = Node(4)

теперь, ожидаемое поведение при попытке распечатать один из этих объектов является то, что это связанное значение печатается. Это тоже случается.

print uno

доходность

1

но когда я делаю следующее:

uno.neighbours.append([[due, 4], [tri, 5]])

а то

print uno.neighbours

я

[[[<__main__.Node instance at 0x00000000023A6C48>, 4], [<__main__.Node instance at 0x00000000023A6D08>, 5]]]

Где Я ожидается

[[2, 4], [3, 5]]

что я упустил? И что еще я делаю, чтобы съежиться от страха? :)

8 94

8 ответов:

Python имеет два различных способа преобразования объекта в строку:str() и repr(). Печать объекта использует str(); печать списка, содержащего объект использует str() для самого списка, но реализация list.__str__() звонки repr() для индивидуального пользования.

так что вы также должны перезаписать __repr__(). Простой

__repr__ = __str__

в конце класса тело будет делать трюк.

из-за бесконечного превосходства Python над Java, Python не имеет один, а два операции toString.

один __str__, другой __repr__

__str__ вернет читаемую человеком строку. __repr__ возвращает внутреннее представление.

__repr__ можно вызвать на объект, вызвав repr(obj) или с помощью обратных палочек `obj`.

при печати списков, а также других контейнеров классы, содержащиеся элементы будут напечатаны с помощью __repr__.

Он предоставляет читаемую человеком версию вывода, а не "объект": пример:

class Pet(object):

    def __init__(self, name, species):
        self.name = name
        self.species = species

    def getName(self):
        return self.name

    def getSpecies(self):
        return self.species

    def Norm(self):
        return "%s is a %s" % (self.name, self.species)

if __name__=='__main__':
    a = Pet("jax", "human")
    print a 

возвращает

<__main__.Pet object at 0x029E2F90>

пока код " str" вернуть что-то другое

class Pet(object):

    def __init__(self, name, species):
        self.name = name
        self.species = species

    def getName(self):
        return self.name

    def getSpecies(self):
        return self.species

    def __str__(self):
        return "%s is a %s" % (self.name, self.species)

if __name__=='__main__':
    a = Pet("jax", "human")
    print a 

возвращает:

jax is a human

Ну, контейнерные объекты' __str__ методы будет использовать repr по их содержанию, а не str. Так что вы могли бы использовать __repr__ вместо __str__, видя, как вы используете ID в качестве результата.

__str__ вызывается только тогда, когда строковое представление требуются объекта.

str(uno),print "%s" % uno или print uno

однако, есть еще один волшебный метод под названием __repr__ это представление объекта. Если вы явно не преобразуете объект в строку, то представление это.

если вы делаете это uno.neighbors.append([[str(due),4],[str(tri),5]]) он будет делать то, что вы ожидаете.

ответ на вопрос

как указано в другом ответ и как вы можете прочитать в PEP 3140,str на list вызовов для каждого элемента __repr__. С этой частью вы ничего не можете поделать.

если вы реализуете __repr__, вы получите что-то более описательное, но если реализовано правильно, не совсем то, что вы ожидали.

надлежащего исполнения

The быстро, но неправильно решение-это псевдоним __repr__ до __str__.

__repr__ не должно быть установлено в __str__безусловно. __repr__ создать представление, которое должно выглядеть как допустимое выражение Python, которое можно использовать для воссоздания объекта с тем же значением. В этом случае, это скорее будет Node(2) чем 2.

правильная реализация __repr__ позволяет воссоздать объект. В этом примере это также должны содержать другие значимые члены, такие как neighours и distance.

An неполное пример:

class Node:

    def __init__(self, id, neighbours=[], distance=0):
        self.id = id
        self.neighbours = neighbours
        self.distance = distance


    def __str__(self):
        return str(self.id)


    def __repr__(self):
        return "Node(id={0.id}, neighbours={0.neighbours!r}, distance={0.distance})".format(self)
        # in an elaborate implementation, members that have the default
        # value could be left out, but this would hide some information


uno = Node(1)    
due = Node(2)    
tri = Node(3)    
qua = Node(4)

print uno
print str(uno)
print repr(uno)

uno.neighbours.append([[due, 4], [tri, 5]])

print uno
print uno.neighbours
print repr(uno)

Примечание:print repr(uno) вместе с правильной реализацией __eq__ и __ne__ или __cmp__ позволит воссоздать объект и проверить равенство.

дело в классах и установке необремененных глобальных переменных, равных некоторому значению в классе, заключается в том, что ваша глобальная переменная хранит фактически ссылку на местоположение памяти, в котором фактически хранится значение.

то, что вы видите в своем выходе, свидетельствует об этом.

где вы могли бы видеть значение и использовать печать без проблем на начальных глобальных переменных, которые вы использовали из-за str метод и как печать работает, вы не сможете сделать это со списками, потому что то, что хранится в элементах в этом списке, является просто ссылкой на местоположение памяти значения-прочитайте псевдонимы, если вы хотите узнать больше.

кроме того, при использовании списков и потере отслеживания того, что является псевдонимом, а что нет, вы можете обнаружить, что изменяете значение исходного элемента списка, если вы измените его в списке псевдонимов - потому что снова, когда вы устанавливаете элемент списка равным списку или элементу внутри список, новый список хранит только ссылку на ячейку памяти (на самом деле он не создает новое пространство памяти, специфичное для этой новой переменной). Вот где deepcopy пригодится!

print self.id.__str__() будет работать для вас, хотя и не так полезно для вас.

код __str__ метод будет более полезен, когда вы говорите, что хотите распечатать представление сетки или структуры по мере развития вашей программы.

print self._grid.__str__()

def __str__(self):
    """
    Return a string representation of the grid for debugging.
    """
    grid_str = ""
    for row in range(self._rows):
        grid_str += str( self._grid[row] )
        grid_str += '\n'
    return grid_str