Pull to refresh
826.42
OTUS
Цифровые навыки от ведущих экспертов

9 навыков программирования на Python, которые отличают новичка от опытного

Reading time 9 min
Views 14K
Original author: Martin Andersson Aaberge
Перевод статьи подготовлен в преддверии старта курса «Разработчик Python».




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

Вы начинаете с обширного набора библиотек и добавляете к ним все новые и новые по мере получения опыта в программировании.

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

Начинающий или опытный?


Итак, что же отличает новичка от опытного программиста, когда речь заходит о программировании на Python?

В этой статье я хотел бы сосредоточиться на следующих вопросах:

  • Решение проблем и искусство задавать вопросы
  • Понимание того, почему код работает (или нет)
  • Работа со строками
  • Работа со списками
  • Использование циклов
  • Использование функций (и правильной терминологии)
  • Объектно-ориентированное программирование
  • Уважение к PEP

Решение проблем и искусство задавать вопросы


Как программист, я скажу, что, если вам не хватает опыта в решении задач, вам будет сложно начать писать отличный код.Если у вас хромают навыки решения проблем, вам, вероятно, будет непросто найти наилучшие решения стоящих перед вами задач. Программирование – это не просто написание кода. Навык решения проблем – это тот навык, который вам понадобится, чтобы выползти из категории «новичков».

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

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

Проблема XY


«Мне нужно получить последние три символа в строке.»
«Нет, не нужно! Тебе нужно получить расширение файла.»

Проблема XY очень забавная вещь. У вас есть проблема Х, а когда вы звоните в службу поддержки, вы спрашиваете о проблеме Y, решение которой, как вам кажется, решит проблему X. [1]

Случай, описанный выше, хорошо эту ситуацию иллюстрирует. Если вы хотите получить расширение файла, то можете предположить, что вам нужны последние 3 символа строки.

Как это могло бы выглядеть:

def extract_ext(filename):
    return filename[-3:]
print (extract_ext('photo_of_sasquatch.png'))
>>> png

Прекрасно! Ну, а теперь попробуйте с photo_of_lochness.jpeg
Пользователь мог бы с самого начала спросить про расширение. Проблема Y – это последние три символа. Проблема X – это расширение.

def extract_ext(filename):
    return filename.split('.')[-1]
print (extract_ext('photo_of_sasquatch.png'))
print (extract_ext('photo_of_lochness.jpeg'))
>>> png
>>> jpeg

Вот и все!

А еще вы можете воспользоваться стандартной библиотекой os.path.splitext().
Ознакомиться с ней вы можете здесь.

Понимание того, почему код работает (или нет)


Когда вы новичок, вы можете шлифовать небольшой фрагмент кода несколько дней напролет. А когда этот код вдруг заработает, вы испытаете облегчение и перейдете к следующей части. И это худшая вещь, которую вы только можете сделать. Безмолвное принятие того, что код просто работает и непонимание почему он работает, вероятно, еще опаснее, чем непонимание того, почему код не работает в принципе.

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

Например, если у вас есть ошибка в отступе от начала строки в коде с несколькими блоками, вы можете начать перемещать блоки случайным образом, а затем образуетесь, когда программа наконец запустится.
Помните, что в большинстве IDE вы можете свернуть циклы и if’ы. Так вы сможете с легкостью увидеть, какой блок у вас работает, а какой нет.


ATOM со свернутыми конструкциями if-else справа

Еще один классный способ наглядно увидеть, как работает ваш код – это www.pythontutor.com, где вы можете посмотреть, что происходит в вашей программе построчно.


Выполнение кода в pythontutors

Работа со строками


Текущий раздел не совсем про строки. Он больше про копание в прекрасных библиотеках Python. В Python мы рано узнаем о том, что строку можно рассматривать как список символов. Вы можете получать доступ к символу в строке по индексу.

word = 'supergreat'
print (f'{word[0]}') 
>>> s
print (f'{word[0:5]}')
>>> super

Пытливый ум узнает о том, что предлагает str(), но вы же можете просто продолжать писать, ни разу не заглянув в документацию str(). Чтобы вызвать документацию по функции вы можете написать help(str) или dir(str). Когда вы это сделаете, то сможете найти методы, о существовании которых даже не подозревали. Возможно, вы заглядывали в документацию и знаете, что у строк есть метод endswith(), например, и вы можете его где-то применить.



Вот пример кода, который делает одно и то же двумя разными способами. В первом варианте используется split, о котором мы недавно говорили. А во втором — endswith(), который вы могли найти в документации.

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

Работа со списками


Списки – отличная и универсальная вещь.
Например, вот тут мы смешиваем целочисленные значения и строки:

my_list = ['a' , 'b' , 'n' , 'x' , 1 , 2 , 3, 'a' , 'n' , 'b']
for item in my_list:
    print (f'current item: {item}, Type: {type(item)}')



Посмотрите, как мы их перемешали. Если мы попробуем отсортировать полученный список, то получим ошибку.

print (my_list.sort())



Что, если нам нужно отделить буквы от чисел? Первый способ – решить задачу с помощью цикла, в котором мы будем проверять каждый элемент списка. Новичок рано познакомится с циклами, ведь циклы – важная часть в программировании.

Код может выглядеть как-то так:

my_list = ['a' , 'b' , 'n' , 'x' , 1 , 2 , 3 , 'a' , 33.3 , 'n' , 'b']
number_list = []
string_list = []
for item in my_list:
    print (f'current item: {item}, Type: {type(item)}')
    if not isinstance(item,str):
        number_list.append(item)
    else:
        string_list.append(item)
my_list = string_list

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

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

my_list = [letter for letter in my_list if isinstance(letter,str)]


Вот и все!

И это еще не конец. Вы можете использовать filter, чтобы получить тот же результат.

def get_numbers(input_char):
    if not isinstance(input_char,str):
        return True
    return False

my_list = [1,2,3,'a','b','c']
check_list = filter(get_numbers, my_list)
for items in check_list:
    print(items)




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

Бонус

  • Переворот списка (или строки):

names = ['First' , 'Middle' , 'Last']
print(names[::-1])
>>> ['Last', 'Middle', 'First']

  • Объединение элементов списка:

names = ['First' , 'Middle' , 'Last']
full_name = ' '.join(names)
print(f'Full Name:\n{full_name}')
>>> First Middle Last

Использование циклов


Вы встречались с подобным кодом?

greek_gods = ['Zeus' , 'Hera' , 'Poseidon' , 'Apollo' , 'Bob']
for index in range(0,len(greek_gods)):
    print (f'at index {index} , we have : {greek_gods[index]}')

Такую конструкцию вы, вероятно, узнаете из других языков, однако это далеко не подход Python. В Python вы будете использовать:

for name in greek_gods:
    print (f'Greek God: {name}')

Вы быстро заметите, что здесь нет индекса. Что делать, если вы захотите оперировать индексом? В Python вы можете воспользоваться enumerate. Это отличный способ получить доступ ко всему, что вам нужно!

for index, name in enumerate(greek_gods):
    print (f'at index {index} , we have : {name}')



Использование функций (и правильной терминологии)


Когда я работаю над анимацией, я всегда говорю, что если вы делаете одно и то же 5 раз, то нужно подумать о том, не нужна ли вам программа? Иногда, потратив две недели на разработку инструмента, вы можете сэкономить шесть недель работы. Когда вы пишете код и понимаете, что вы выполняете одно и то же действие несколько раз, вам нужно подумать, не стоит ли этот код вынести в процедуру или функцию. Функция будет возвращать какое-то значение, а процедура будет просто выполнять код. В первом примере вы видите процедуру, а во втором – функцию.

Звучит запутанно. Вот иллюстрация, отражающая принцип работы:



Обратите внимание на разницу между print и return. Может показаться, что они работают одинаково, но если вы посмотрите в вывод, то увидите, что функция просто вернет переданное имя.

Следующие термины, которые стоит четко разделять – это аргументы и параметры. Параметры – это то, что определено в процедуре или функции (на рисунке выделены красным цветом), а то, что вы передаете в процедуру или функцию – это аргументы (выделены зеленым цветом).

Вот несколько примеров.

Пример 1

def print_list(input_list):
    for each in input_list:
        print(f'{each}')
    print() #just to separate output
greek_gods = ['Zeus' , 'Hera' , 'Poseidon' , 'Apollo' , 'Bob']
grocery_list = ['Apples' , 'Milk' , 'Bread']
print_list(greek_gods)
print_list(grocery_list)
print_list(['a' , 'b' , 'c'])



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

Пример 2

def reverse_list(list_input):
    return list_input[::-1]
my_list = ['a', 'b' , 'c']
print (reverse_list(my_list))
>>> ['c', 'b', 'a']

Объектно-ориентированное программирование


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

Объектно-ориентированное программирование (ООП) – это гигантская тема, поэтому этот разделе не вместит в себя всего, что нужно о ней знать, но мы поговорим о нескольких простых примерах, которые помогут вам в работе.

Если вы раньше читали про ООП, то вероятно устали от учебы, но тут снова она. Начнем с определения класса Student. У него будет имя (name) и список дисциплин (subject_list):

class Student():
    def __init__(self,name):
        self._name = name
        self._subject_list = []

Здесь __init__ — это конструктор класса. В нем определяется ядро класса. Позже вы увидите, как происходит добавление методов. Методы – это процедуры или функции, принадлежащие классу, которые можно вызывать при использовании класса внутри программы.
Если вы захотите создать студента, вы создадите следующую переменную:

student1 = Student('Martin Aaberge')

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

student2 = Student('Ninja Henderson')

И student1, и student2 будут экземплярами класса Student. У них одна и та же схема, но больше ничего общего они не имеют. На данный момент, мы мало что можем сделать со студентами, но мы добавили список дисциплин. Чтобы заполнить этот список, мы создадим отдельный метод. Вы можете вызвать методы для взаимодействия с экземплярами класса.

Давайте обновим класс:

class Student():
    def __init__(self,name):
        self._name = name
        self._subject_list = []
    def add_subject(self, subject_name):
        self._subject_list.append(subject_name)
    def get_student_data(self):
        print (f'Student: {self._name} is assigned to:')
        for subject in self._subject_list:
            print (f'{subject}')
        print()

Теперь этот класс можно использовать для создания студентов, редактирования и получения информации о них.

#create students:
student1 = Student('Martin Aaberge')
student2 = Student('Heidi Hummelvold')
#add subjects to student1
student1.add_subject('psychology_101')
student1.add_subject('it_security_101')
#add subject to student2
student2.add_subject('leadership_101')
#print current data on students
student1.get_student_data()
student2.get_student_data()

Обычно классы хранятся в отдельных файлах и импортируются в код. В нашем примере мы создали класс Student в файле student.py и импортировали его в наш файл main.py. (В данном случае оба файла лежат в одной папке).

from student import Student
student1 = Student('Martin')
student1.add_subject('biomechanics_2020')
student1.get_student_data()



Уважайте PEP


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

PEP – это набор рекомендация для вашего кода. Вот ссылка на PEP-8. Отличное чтиво. Прочтите его хотя бы раз, чтобы понять, о чем тут речь. Классический пример – это snake_case. Переменные в Python пишутся в snake_case, то есть слова в имени переменной разделяются с помощью нижнего подчеркивания. Даже в университетах порой учат неправильно, так что не расстраивайтесь, и просто начните писать по правилам.

Вот так правильно:

chocolate_cake = 'yummy'

А вот так – нет:

chocolateCake = 'Yummy'

Заключение


Быть новичком – удивительно. Ваш путь будет непростым, но ваша кривая обучения будет крутой и подарит вам новый опыт! Перестать быть новичком бывает трудно. Иногда сложно понять, на чем нужно сосредоточиться. Каков же будет следующий шаг?

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

Источники:

[1] Проблема XY, en.wikipedia.org/wiki/XY_problem



Бесплатный урок: «Введение в автотесты»


Tags:
Hubs:
-7
Comments 17
Comments Comments 17

Articles

Information

Website
otus.ru
Registered
Founded
Employees
101–200 employees
Location
Россия
Representative
OTUS