2014-07-17 3 views
0

У меня есть концептуальный вопрос. Я пытался избавиться от знаков препинания в строке, поэтому я написал следующую функцию:Как работает str.replace?

def nopunc(str): 
    for x in string.punctuation: 
     str = str.replace(x, " ") 
    return str 

Это работало. Однако, когда я немного изменил функцию:

def nopunc(str): 
    for x in string.punctuation: 
     str1 = str.replace(x, " ") 
    return str1 

это не сработало. Вместо того, чтобы иметь str = str.replace(x, ""), я дал строке новое имя под названием str1. Почему это вызовет проблему? Это имеет какое-то отношение к .replace?

+0

Хорошо подумайте об этом - когда вы переходите ко второму 'x', что такое' str'? (Кроме того, не используйте 'str' в качестве собственного имени переменной.) – jonrsharpe

+1

В сторону: не называйте вашу переменную' str', как это тени Python 'str' и, вероятно, путают читателей вашего кода. –

+0

Ваше замешательство не связано с природой 'replace'. Скорее, речь идет о характере ассимиляции в Python. Прочитайте [Факты и мифы о именах и достоинствах Python] Ned Batchelder (http://nedbatchelder.com/text/names.html), и вы поймете Python намного лучше. –

ответ

4

Поскольку строки являются неизменными, str.replace(x, " ") делает не изменять строку объект, на который ссылается str каким-либо образом. Вместо этого возвращается копия этого объекта x заменена на " ".

В вашем первом for-loop каждая итерация присваивает этот вновь созданный объект существующему имени str. Итак, ваша первая функция в основном эквивалентна:

def nopunc(str): 
    str = str.replace(string.punctuation[0], " ") 
    str = str.replace(string.punctuation[1], " ") 
    str = str.replace(string.punctuation[2], " ") 
    ... 
    str = str.replace(string.punctuation[31], " ") 
    return str 

Обратите внимание, как значение имени str постоянно обновляется, тем самым сохраняя изменений.

Второй для цикла, однако, просто повторно переназначает имя str1 на str.replace(x, " "). Это означает, что ваша вторая функция ничем не отличается, чем делать:

def nopunc(str): 
    str1 = str.replace(string.punctuation[31], " ") 
    return str1 
2

Заменить не изменяют значения, содержащиеся на str. Это ваш = присваивание, которое делает.

В первом случае все замены складываются, поскольку каждый вызов с другим знаком пунктуации заменяет материал в строке, полученной в результате предыдущей замены.

Во втором случае все замены теряются, потому что каждый вызов с новым знаком пунктуации заменяет материал в неизменной исходной строке и возвращает только последнюю замену (которая заменяет тильды пробелами).

Смежные вопросы