Преобразование букв в строке


Я учусь Python и хотите улучшить свои навыки в нем. Так что может кому-то советы о том, как улучшить код ниже (это простая проблема программирования, взята с одного из сайтов). Я чувствую, что мой код не очень подходящие для Python.

Проблема: с использованием языка Python, имеют функцию LetterChanges(str) взять str параметр передается и изменять его, используя следующий алгоритм. Заменить каждую букву в строке на букву следующей в алфавите (т. е. С становится D и Z становится). Затем использовать все гласные в этой новой строки (А, Е, I, о, U) и, наконец, вернуть эту модифицированную строку.

from sets import Set

def LetterChanges(str): 
   vowels = Set(['a', 'e', 'i', 'o', 'u'])
   new_str = ''
   for i in str:
      cur_char = i.lower()
      if cur_char == 'z':
         new_str += 'A'
      elif ord(cur_char) >= 97 and ord(cur_char) < 122:
         new_char = chr(ord(i) + 1)
         new_str += (new_char if new_char not in vowels else new_char.upper())
      else:
         new_str += i
   return new_str

if __name__=='__main__': 
   print(LetterChanges(raw_input()))


Комментарии
4 ответа

Ваш код определяет функцию с четким входом и ясный выход. Кроме того, вы разместили призыв к нему за if __name__ == '__main__':. Вы взяли хорошие привычки на это указывает. Тем не менее, некоторые вещи все еще могут быть улучшены.

Python версии

Если вы не изучаете Python, существует нет хорошая причина, чтобы начать с Python 2, который достигает своего конца жизни. Вы должны сосредоточиться на изучение Python 3, будет поддерживаться какое-то время и с различных бородавок исправлениями (и, очевидно, больше возможностей).

В любом случае sets модуль не требуется начиная с версии Python 2.6, так как мы имеем set строение.

Стиль

Есть официальный стандартный Python стиль руководства называют ПЭП 8. Это настоятельно рекомендуется к прочтению. Он дает рекомендации, помогающие писать код, который можно как читать, так и последовательным. Сообществе Python пытается следовать этим правилам, более или менее строго (ключевой аспект ОПТОСОЗ 8 является то, что оно содержит рекомендации, а не строгие правила, чтобы слепо следовать).

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

Вы найдете различные инструменты, чтобы попытаться проверить, является ли ваш код ОПТОСОЗ 8 уступчива и если это не, чтобы попытаться исправить это:


  • pycodestyle пакет (ранее известный как pep8) для проверки кода

  • pep8online чтобы проверить ваш код с помощью онлайн-инструмента

  • autopep8 пакет , чтобы исправить ваш код автоматически

  • Кроме того, это также проверил различные Линта: pylint, pyflakes, flake8и т. д.

В вашем случае, основные моменты, которые я хотел бы исправить:


  • абзацный отступ должен быть 4 места

  • имена функций должны snake_cased

  • вы могли бы попытаться учесть советы в использовании join вместо "с CPython эффективной реализации в месте конкатенации строк".

Именования

Поверх змеи-дело упоминали выше, некоторые вещи можно было бы улучшить в именования. Нейминг-это сложная часть программирования, так что я предлагаю всего личного, далеко от совершенства, предложения (из не-носителем английского языка). В вашем случае, я бы вызвать функцию tranform_string так что он передает то, что:


  • это действие (существительное соответствует объект/название класса)

  • это относится к строке (а не один символ, даже если различие размыто в Python по сравнению с другими языками программирования)

Имя str это немного проблема, потому что она скрывает str строение. Я не нахожу никакой альтернативы лучше str_ что еще плохо :-(.

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

Наконец, i это хорошее название для (число) индекса. Для одного символа, c кажется, легче понять (char если вы чувствуете, многословно).

Прикованный сравнения

В Python, вы можете , услуги сравнения. Если в вашем случае, можно написать:

elif 97 <= ord(cur_char) < 122:

Более красивой проверяем характер

Из Дзен питона:


Красивое лучше, чем уродливое.
Явное лучше, чем неявное.
Простое лучше, чем сложное.

В вашем случае, вы могли бы избежать вызова ord и избавиться от магического числа, написав просто:

elif 'a' <= cur_char < 'z':

Переписывание логики

Вы могли бы логика добавление символа new_str в одном месте.

    cur_char = c.lower()
if cur_char == 'z':
new_char = 'A'
elif 'a' <= cur_char < 'z':
new_char = chr(ord(c) + 1)
if new_char in vowels:
new_char = new_char.upper()
else:
new_char = c
new_str += new_char

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

    low_char = c.lower()
if 'a' <= low_char <= 'z':
new_char = 'a' if low_char == 'z' else chr(ord(c) + 1)
if new_char in vowels:
new_char = new_char.upper()
else:
new_char = c
new_str += new_char

Короче способ определения vowels

Поскольку строки являются Iterable и set принимает любые итерируемые, вы могли бы написать:

vowels = set('aeiou')

Лучше в ASCII проверьте

Вы могли бы повторно использовать значения из string модуль , чтобы сделать тест более красивым:

   if low_char in string.ascii_lowercase:

Удаление конкатенации строк

Как упоминалось ранее, рекомендуется не использовать конкатенацию строк и использовать join вместо этого, в случае необходимости.

На этом этапе код (с добавлением испытаний) выглядит как:

import string

def transform_string(s):
vowels = set('aeiou')
lst = []
for c in s:
if c in string.ascii_letters:
new_c = 'a' if c.lower() == 'z' else chr(ord(c) + 1)
if new_c in vowels:
new_c = new_c.upper()
else:
new_c = c
lst.append(new_c)
return "".join(lst)

if __name__=='__main__':
assert transform_string("") == ""
assert transform_string("qwertyuiop") == "rxfsUzvjpq"
assert transform_string("asdfghjkl") == "btEghIklm"
assert transform_string("zxcvbnm") == "AydwcOn"
assert transform_string("1234567890") == "1234567890"
assert transform_string("QWERTYUIOP") == "RXFSUZVJPQ"
assert transform_string("ASDFGHJKL") == "BTEGHIKLM"
assert transform_string("ZXCVBNM") == "AYDWCON"
assert transform_string("(){}<>+_-=") == "(){}<>+_-="

18
ответ дан 12 марта 2018 в 07:03 Источник Поделиться

Вместо этих ifвы могли бы использовать перевод таблицы для ускорения процесса (см. str.maketrans и str.translate).

import string

def _build_translation_table():
ascii_vowels = 'aeiou'
d = {c: chr(ord(c)+1) for c in string.ascii_lowercase}
d['z'] = 'a' # z is a special case
for k, v in d.items(): # and so are vowels
if v in ascii_vowels:
d[k] = v.upper()
return str.maketrans(d)

_TABLE = _build_translation_table()

def LetterChanges(s):
"""Change letters in string s using a special algorithm.

Replace every letter in the string with the letter following it in the
alphabet (ie. c becomes d, z becomes a) ...

>>> LetterChanges('qwertyuiop')
'rxfsUzvjpq'
>>> LetterChanges('1234567890')
'1234567890'
>>> LetterChanges('zxcvbnm')
'AydwcOn'
"""

return s.translate(_TABLE)

if __name__ == '__main__':
import doctest
doctest.testmod()

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

Я также сделал несколько тестов из Josay ответ и положить их в документации строковые функции, так что doctest модуль может работать с ними.

# python3 letterchanges.py -v
Trying:
LetterChanges('qwertyuiop')
Expecting:
'rxfsUzvjpq'
ok
Trying:
LetterChanges('1234567890')
Expecting:
'1234567890'
ok

13
ответ дан 12 марта 2018 в 08:03 Источник Поделиться

Верить Python-3.x тег, вот способ, чтобы переписать свой метод:

def letter_changes(text):
vowels = set('aeiou')
new_str = ''
for c in text:
cur_char = c.lower()
if cur_char == 'z':
new_str += 'A'
elif ord(cur_char) >= 97 and ord(cur_char) < 122:
new_char = chr(ord(c) + 1)
new_str += new_char.upper() if new_char in vowels else new_char
else:
new_str += i
return new_str

if __name__ == '__main__':
print(letter_changes(input()))

С учетом этих изменений:


  • snake_case имя метода

  • set для Питон3

  • 4 пробела отступ

  • обратная логика upper если буква гласная.

Другой альтернативой было бы работать с генераторами и объединить Буквы в конце вместо того, чтобы строить новую строку посимвольно.

7
ответ дан 12 марта 2018 в 07:03 Источник Поделиться

Вот некоторые улучшения, которые я хотел сделать (предполагая, что ваш код, используя Python 2.х):


  • Я бы отступ кода, так что это будет кратно четырем

  • Нет никаких причин, чтобы сделать гласным Set(). Строки должны работать нормально, строки повторяемое в Python

  • переименовать str аргумент к чему-то другому, как это строение сайта на Python

  • Я бы упростить прикован сравнения: ord(cur_char) >= 97 and ord(cur_char) < 122 для 97 <= ord(cur_char) < 122

Это, как говорится, вы бы до сих пор:

def LetterChanges(str_):
vowels = 'aeiou'
new_str = ''
for i in str_:
cur_char = i.lower()
if cur_char == 'z':
new_str += 'A'
elif 97 <= ord(cur_char) < 122:
new_char = chr(ord(i) + 1)
new_str += (new_char if new_char not in vowels else new_char.upper())
else:
new_str += i
return new_str

if __name__ == '__main__':
print(LetterChanges(raw_input()))

5
ответ дан 12 марта 2018 в 07:03 Источник Поделиться