Смущен str в списке в Python [дубликат]
этот вопрос уже есть ответ здесь:
- Python _ _ str__ и списки 7 ответов
исходя из фона 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 ответов:
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 пригодится!
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