Изменение строки при зацикливании на ней - PullRequest
6 голосов
/ 13 апреля 2020

Здесь мы изменяем строку s, зацикливаясь на ней:

s = 'hello'
for c in s:
    s += c
    print(s)

Она не генерирует бесконечное l oop (это может : мы добавляем новый символ в каждой итерации!).

Я знаю это много лет, но не могу объяснить почему. Это как-то связано с неизменяемостью строк или не связано?

При выполнении for c in s:, копируется ли оригинал s в память перед запуском l oop?


Еще один случай, который, как я думал, может генерировать бесконечное число l oop, но это не так:

s = 'hello'
def f(x):
    i = 0
    while True:
        try:
            yield x[i]
        except IndexError:
            break
        i += 1

for c in f(s):
    s += c
    print(s)

Ответы [ 3 ]

2 голосов
/ 13 апреля 2020

Он не генерирует бесконечное число l oop (это может быть: мы добавляем новый символ в каждой итерации!).

Это потому, что строки в Python неизменны. Когда вы делаете for c in s, for l oop, перебираете исходный объект (объект, содержащий "hello") и когда вы делаете s += c, создается новая строка и, следовательно, вы не изменяете исходный строковый объект что for l oop все еще повторяется.

Кроме того, добавив комментарий @Steven Rumbalski в мой ответ:

Он перебирает исходный объект. Привязка имени к новому объекту не меняет for-l oop, поскольку не разрешает имя на каждой итерации.

Теперь давайте поговорим о вашем втором примере:

Если вы вызываете вашу функцию f(s), она делает ее формальным аргументом x, указывающим на объект, содержащий строку «hello», и создает генератор, используя строковый объект. Теперь последующее переназначение строки s (с использованием s += c) фактически создает другую строку и не влияет на исходный объект. Формальный аргумент вашей функции по-прежнему указывает на объект, содержащий "hello".

Итак, после первой итерации вашего для l oop во втором примере:

  1. Формальный аргумент функции f(x) будет по-прежнему указывать на объект, содержащий «hello».

  2. s будет указывать на объект, содержащий "helloh".

ВАЖНО:

Однако, если вы попробуете свой код с изменяемыми типами данных, он может создать бесконечное l oop. Смотрите это:

li = [ 1, 2, 3, 4 ]
for i in li:
    li.append(i)
    print(li)
1 голос
/ 13 апреля 2020

Измените список, чтобы выполнить sh то, что вы хотите.

array = list('hello')
for c in array:
    array.append(c)
    print(*array, sep='')

печатает

helloh
hellohe
hellohel
hellohell
hellohello
hellohelloh
hellohellohe
hellohellohel
hellohellohell
hellohellohello
hellohellohelloh
hellohellohellohe
...

Если вы хотите l oop одним символом непрерывно, вы можете сделать

from itertools import cycle

for c in cycle('hello'):
    print(c)

отпечатков

h
e
l
l
o
h
e
l
...
0 голосов
/ 13 апреля 2020

Это не рекурсивный метод. Это прекрасно. Он будет запущен только один раз, потому что вы передаете строку f('hello'), теперь l oop имеет "hello" для повторения. поэтому он будет работать только один раз

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...