Программирование — мощный инструмент. Python — это простой способ освоить важный навык
Я отправляюсь в путешествие по изучению Python. Python — это язык программирования общего назначения, который отлично подходит, если вы хотите начать изучать программирование или создать компанию, которая завоюет мир.
Программирование — это мощный навык, а Python — это простая отправная точка.
Не теряя много времени, этот пост предлагает от нуля до сотни с Python… с некоторыми советами в конце.
Вот демонстрация видео:
Печать и переменные
Урок №1 (или 0…), печать в консоль. Открываем интерпретатор Python:
$ pipenv run ipython
И пишем нашу пресловутую первую строчку кода.
print("Hello World")
>>> Hello World
Далее мы узнаем о комментировании кода.
# this is a comment and will not be
# evaluated like code
Переменные хранят значения.
number = 10 string = "This is a string"
print(number) >>> 10 print(string) >>> "This is a string"
Мы можем использовать f-strings
для печати нашего кода в строке, используя фигурные скобки для заключения имен наших переменных или кода Python.
print(f"number: {number}, and string: {string}")
>>> "number: 10, and string: This is a string"
Переменные не одинаковы. У них есть типы. Например, number
— это целое число, а string
— это набор символов, называемый строкой.
print(f"{type(number} and {type(string)}")
>>> "<class 'int'> and <class 'str'>"
Функции
Если у нас есть код, который мы должны писать снова и снова, рекомендуется не повторяться. Вместо того, чтобы повторяться, мы помещаем этот код в функцию и вызываем эту функцию. Давайте создадим функцию для последовательности Фибоначчи, в которую мы передаем число n
, и это даст последовательность nth
# the fibonacci sequence # 0, 1, 1, 2, 3, 5, 8...
def f(n: int) -> int: """ Fibonacci sequence --- params n (int) number requested in sequence
returns integer in fibonacci sequence """ if n == 0: return 0 elif n == 1 or n == 2: return 1 else: return f(n-1) + f(n-2)
В приведенном выше коде есть ряд понятий. Во-первых, мы вводим функцию, используя def. Мы используем типизацию, где мы принимаем n как целое число (n: int), и функция возвращает целое число (-> n
).
Мы включаем строку документа, заключенную в тройные кавычки (""). Основная цель doc-string — объяснить, что делает функция.
Кроме того, эта функция является хорошим примером условного оператора. Операторы if
проверяют, является ли следующее True
или False
. Если True
, то кодовый блок выполняется.
ПРИМЕЧАНИЕ. Отступы в Python очень важны.
Если оператор if
равен False
, то проверяется elif
(сокращение от else-if). Мы видим, что использование or
означает, что только n == 1
или n == 2
должны быть истинными для срабатывания блока кода, в данном случае возвращается 1
. Наконец, else
запускается, когда предыдущие операторы if
и elif
равны False
.
Эта строка f(n-1) + f(n-2)
является примером рекурсии. Функция f
вызывает сама себя, но с одним меньше n
и двумя меньше n
.
Дополнительные типы данных — списки
Мы можем многое сделать с функциями и переменными. Давайте рассмотрим различные типы данных в Python, начиная со списков.
Настраиваем диапазон.
r = range(10)
r
>>> range(0, 10) # number from 0 up to and not including 10
Создаем список.
lst = list(r)
lst
>>> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Если мы хотим получить доступ к элементам в списке, мы делаем это:
lst[0] # the first element of the list is "0th" index
>>> 0
lst[1:3] # the second and up to and not including the 3rd element
>>> [1, 2]
lst[-1] # the last element
>>> 9
lst[::-1] # reverses the list
>>> [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
Списки не обязательно должны быть целыми числами, они могут быть функциями.
def f1(x: int) -> str: return f"f1: {x + 1}"
def f2(x: int) -> str: return f"f2: {x ** 2}"
def f3(x: int) -> str: return f"f3: {1 / x}"
funcs = [f1, f2, f3]
for func in funcs: print(func(2))
>>> "f1: 3" >>> "f2: 4" >>> "f3: 0.5"
Это хороший способ представить пресловутый цикл for. Список является примером итератора. Например, мы можем использовать цикл for для перебора списка.
for i in lst: output = f(i) print(output, end=", ")
>>> "0, 1, 1, 2, 3, 5, 8, 13, 21, 34"
Вместо того, чтобы печатать список чисел, мы можем вернуть список.
output = [] for i in lst: output.append(f(i))
output >>> [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
Вместо того, чтобы создавать пустой список и использовать несколько строк, мы можем превратить его в «однострочный». Мы используем печально известное понимание списков.
output = [f(i) for i in lst]
output
>>> [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
Импорт библиотек
Большую часть времени мы будем использовать хорошо написанный код других людей. Это экономит время, но также на этой планете есть очень умные люди. Они предлагают решения проблем, которые я не мог решить в своей жизни БЕСПЛАТНО. Одним из примеров является библиотека под названием pandas
, популярная в области анализа данных.
Вернемся к нашей функции Фибоначчи. Вы заметите, что проблема с рекурсиями заключается в том, что чем больше чисел мы запрашиваем в последовательности, тем дольше выполняется программа.
Мы можем показать это, используя магическую функцию IPython, %timeit
.
times = []
for i in range(33): # we will do the first 32 numbers in sequence
t = %timeit -n1 -o f(i)
times.append(t.best)
Тег -n<N>
означает, сколько раз функция будет зацикливаться, в нашем случае только один раз; -o
выводит результат timeit
в переменную, в нашем случае t
, для последующей проверки.
Теперь мы будем использовать pandas
для табулирования наших данных.
import pandas as pd
df = pd.DataFrame(data=times, columns=["f"] df.head() # prints first five results by default >>> f 0 5.829997e-07 1 6.790001e-07 2 7.760000e-07 3 1.695000e-06 4 2.799000e-06
Мы дали pandas
псевдоним pd
. Это избавляет нас от необходимости постоянно писать «панды».
Импортируя pandas
, мы получаем доступ к классу DataFrame
. Мы можем построить эти данные и сохранить их. Мы используем другую библиотеку, matplotlib
, которая представляет собой графическую библиотеку для сохранения нашего графика в виде изображения.
import matplotlib.pyplot as plt
g = df.plot(title="Time on Fib") g.set_xlabel("n") g.set_ylabel("times (s)") plt.savefig("f.png")
Мы можем видеть экспоненциальный рост времени работы программы по мере увеличения n
.
Мы можем рассчитать общее время:
df.sum()
>>> f 3.693825 # total time
>>> dtype: float64
Дополнительные типы данных — Словари
Мы представим словари. Словари имеют пару ключ и значение.
dct = {
"key1": "value1",
"key2": ["value2", "value3"],
"random name for a key": 1,
"key4": (2000, 3000)
}
И чтобы получить значение из словаря:
dct["key4"]
>>> (2000, 3000) # this is a tuple by the way
Если мы ссылаемся на несуществующий ключ (например, dct["key5"]
), мы получаем ошибку. В качестве альтернативы мы можем использовать метод get()
, чтобы наш код не выдавал ошибку и вместо этого возвращал None
.
dct.get("key5") is None
>>> True
Мы можем даже применить цикл for к словарям.
for k, v in dct.items(): print(f"key: {k}, value: {v}")
>>> key: key1, value: value1 >>> key: key2, value: ['value2', 'value3'] >>> key: key3, value: 1 >>> key: key4, value: (2000, 3000)
Возвращаясь к нашему примеру с функцией Фибоначчи, мы можем использовать словари для хранения некоторых ранее рассчитанных значений вместо того, чтобы вычислять их снова и снова. Это называется кэшированием, и мы обмениваем память на меньшее время вычислений.
cache = {}
def f_better(n: int) -> int: """ Fibonacci sequence - !!with caching!! --- params n (int) number requested in sequence returns interger in fibonacci sequence """ if all([cache.get(n-1), cache.get(n-2)]): return cache[n-1] + cache[n-2] elif n == 0: return 0 elif n == 1 or n == 2: return 1 else: cache[n] = f_better(n-1) + f_better(n-2) return cache[n]
В начале мы добавили условие, которое просто проверяет, находится ли предыдущий результат в кеше, и использует это сохраненное значение вместо того, чтобы все время вычислять с нуля.
Еще одним дополнением является то, что вновь вычисленное значение сохраняется в кэше.
Мы можем измерить, как долго работает эта новая функция.
times = []
for i in range(35):
t = %timeit -n1 -o -q f_better(i)
times.append(t.best)
df['f_better'] = pd.DataFrame(data=times)
df.tail(10)
>>>
f f_better
23 0.005453 5.040001e-07
24 0.008786 1.269000e-05
25 0.014167 1.357200e-05
26 0.022997 4.909998e-07
27 0.037203 1.430600e-05
28 0.060064 1.520500e-05
29 0.097307 5.379998e-07
30 0.157304 1.653000e-05
31 0.254740 1.687500e-05
32 0.412715 5.299999e-07
Мы можем построить это.
g = df.plot(title="Comparing")
g.set_xlabel("n")
g.set_ylabel("time (s)")
plt.savefig("f_better.png")
Мы видим, что время, затрачиваемое на эту реализацию кэширования, значительно меньше.
Наконец, мы можем напечатать это cache
.
cache
>>> {
3: 2,
4: 3,
6: 8,
7: 13,
9: 34,
10: 55,
12: 144,
13: 233,
15: 610,
16: 987,
18: 2584,
19: 4181,
21: 10946,
22: 17711,
24: 46368,
25: 75025,
27: 196418,
28: 317811,
30: 832040,
31: 1346269,
33: 3524578,
34: 5702887
}
Классы
В Python все является объектами. Для создания собственных объектов мы создаем classes
.
class Car:
"""
Class for cars that people drive
---
params
make (str): make of the car
model (str): model of the car
year (int): year car was made
"""
def __init__(self, make: str, model: str, year: int=2021):
self.make = make
self.model = model
self.year = year
self.__is_driving = False
def __repr__(self):
return f'{self.make} - {self.model}'
def drive(self) -> str:
if self.__is_driving == False:
print(f'{self.make} - {self.model} is now driving')
self.__is_driving = True
else:
print(f'{self.make} - {self.model} is already driving!')
def stop(self) -> str:
if self.__is_driving == True:
print(f'{self.make} - {self.model} has stopped')
self.__is_driving = False
else:
print(f'{self.make} - {self.model} is already stopped!')
Давайте протестируем наш новый класс.
shivan = Car('Toyota', 'Corolla', '2008')
bruno = Car('Tesla', 'Model3')
У нас есть два объекта, shivan
и bruno
, производные от класса Car
.
bruno >>> "Tesla - Model3"
shivan.drive() >>> "Toyota - Corolla is now driving"
shivan.drive() >>> "Toyota - Corolla is ALREADY driving"
shivan.stop() >>> "Toyota - Corolla has stopped"
bruno.stop() >>> "Tesla - Model3 is ALREADY stopped!"
Заключительные примечания
Итак, вы ознакомились с основами Python. Это только начало. Иди строй что-нибудь. Иди будь кем-нибудь.
Что бы вас ни интересовало, большое или маленькое, идите и делайте это. Не бойтесь совершать ошибки, но обращайтесь за помощью, когда это необходимо. Выработайте привычку: маленькие шаги каждый день ведут к большому расстоянию с течением времени.
Наконец, если у вас есть какие-либо отзывы, предложения или вопросы, пожалуйста, дайте мне знать. Не забывайте уважать себя, оставайтесь Pythonic.
Ка кайт Ано!