Для прохождения этого самоучителя требуется совсем небольшое время. Он быстро даёт сильный буст для изучения фреймворков и дальнейшего профессионального развития.
В онлайн-интерпретаторе недоступны type() и nonlocal. А в остальном этот учебник прекрасен.
Совет: проговаривайте вслух определения, в которых есть слова, выделенные оранжевым цветом.
Артем Спиридонов, НИИНТ, 2021.
Если код из какого-то примера не запускается:
Интерпретатор игнорирует текст, размеченный как комментарии.
Комментарии бывают однострочными и многострочными.
print('Миру - мир!')
# Пример однострочного комментария
'''
Пример
многострочного
комментария
'''
Добавьте однострочный и многострочный комментарии в код программы. Запустите программу, чтобы убедиться в том, что ошибок нет.
Программа на Python может вводить и выводить данные.
input() просит пользователя ввести строку текста.
int() приводит данные к целочисленному типу.
print() выводит строку в консоль.
Введите текст этой программы без комментариев, и запустите её.
# попросит пользователя ввести строку, приведет её к целому типу, запишет в переменную a
a = int(input('Введите первый множитель'))
# попросит пользователя ввести строку, приведет её к целому типу, запишет в переменную b
b = int(input('Введите второй множитель'))
# создаст переменную c, запишет в неё произведение a и b
c = a * b
# выведет строку с переменными a, b и c
print(f'Результат: {a} * {b} = {c}')
Переменная — это именованная область памяти.
Каждый раз, когда в программе впервые встречается имя новой переменной и знак присваивания =, интерпретатор сам выделяет область в памяти, даёт ей имя, и записывает туда данные, чтобы потом использовать их.
Мутабельные типы данных создают изменяемые переменные. Их значения могут изменяться в ходе выполнения программы.
Иммутабельные типы данных создают неизменяемые переменные. Их значения не изменяются в ходе выполнения программы. Это хороший способ защитить данные от непреднамеренной модификации. К примеру, настройки и параметры.
Технически в Python нет констант. Вместо них есть иммутабельные типы данных.
Обратите внимание на литералы деклараций типов данных, апострофы и разные скобки. И на запятую в литерале кортежа — этим кортеж отличается от выражения.
Кортеж и словарь — такие же, как и список. Только кортеж иммутабельный, в отличие от обычного списка, его нельзя изменить после создания. А в словаре можно использовать любые индексы. Об этом подробнее ниже.
Литералы — как константы. Они не изменяются.
True # истина, 1
False # ложь, 0
True и False — это числа 1 и 0. Они взаимозаменяемы. 5 + True = 6, а 5 / False выдаст ошибку деления на ноль.
5
0 # это целый ноль
888
-888
5.0 # точка указывает интерпретатору на то, что число вещественное, а не целое
0.0 # это вещественный ноль
0.1
0.155
-999.0
Чем отличаются литералы целых и вещественных чисел?
Чем целочисленный ноль отличается от вещественного ноля?
'Строка с текстом'
"Д'Артаньян - текст с ' апострофом" # а что делать с апострофом?
'Д\'Артаньян - текст с \' апострофом' # можно экранировать апостроф обратным слешем
# можно создать многострочный строковый литерал, с помощью трёх апострофов
'''
Многострочный
строковый
литерал
'''
Апострофы и кавычки полностью взаимозаменяемы. Их можно чередовать. Если не хотите чередовать, используйте экранирование обратным слешем.
Многострочный строковый литерал так похож на многострочный комментарий, правда?
[] # пустой список
[1,2,3,4]
(1, 2, 3)
Почему нет литерала пустого кортежа? Создать его можно, но использовать бессмысленно. Почему?
{'one': 1, 'second': 2}
True # истина, 1
False # ложь, 0
Условия — это обычные математические выражения, которые просто возвращают булевы значения.
two = 2
c = (2 == two) # True
c = (5 < 10) # True
c = (5 > 10) # False
= это оператор присваивания, который создаёт переменную.
== это оператор сравнения, который возвращает булево значение.
!= означает «не равно».
and и or — это тоже самое, что умножение и сложение. В булевой логике они выполняют функции «и» и «или».
Простой пример с логикой «если-то-иначе»
five = 5
if 5 == five:
print('Five is 5')
else:
print('Not')
Этот пример похож на предыдущий, но значение вынесено в отдельную переменную, для вашего понимания природы условий.
five = 5
equal = 5 == five # запишет в переменную equal True или False
if equal:
print('Five is 5')
else:
print('Not')
А это однострочник с тернарным оператором. Он позволяет вставлять условия даже внутрь выражений.
Обратите внимание на ключевые слова if и else.
five = 5
print('Five is 5' if 5 == five else 'Not')
Давайте напишем программу для проверки чисел на четность.
% возвращает остаток от деления.
0 будет пониматься как False, все остальное — как НЕ False, а значит True.
Функция not() превращает True в False, а False в True.
Это называется инверсией.
number = int(input('Введите целое число'))
parity = not(number % 2) # если остатка от деления нет - значит число четное. И наоборот
if parity:
print(f'{number} четное')
else:
print(f'{number} нечетное')
Следующий пример работает так же, как и предыдущий.
number = int(input('Введите целое число'))
if number % 2:
print(f'{number} нечетное')
else:
print(f'{number} четное')
Бесконечные циклы используются в программах с графическим пользовательским интерфейсом, к примеру в играх. А также в серверных приложениях, которые нужно запустить так, чтобы они долго работали сами по себе. Когда не нужно завершать выполнение программы до совершения пользователем каких-то действий.
Этот код будет выполняться до тех пор, пока выполнение программы не будет прервано.
while True:
print('Зациклился')
А этот код выведет числа от 1 до 10.
i = 0
while i < 10:
i += 1
print(i)
break остановит выполнение цикла.
i = 0
while True:
i += 1
print(i)
if 10 == i:
break
continue прерывает выполнение текущей итерации (повторения) цикла и начинает следующую.
Этот код выведет только четные числа. Попробуйте. А потом попробуйте вывести только нечетные, not(i % 2)
i = 0
while i <= 10:
i += 1
if i % 2:
continue
print(i)
В циклах Python есть else. Если был break, то он не будет выполнен.
i = 1
while i <= 10:
i += 1
print(i)
else:
print("Расчет окончен")
'Строка с текстом'
"Д'Артаньян - текст с ' апострофом" # а что делать с апострофом?
'Д\'Артаньян - текст с \' апострофом' # можно экранировать апостроф обратным слешем
'''
Многострочный
строковый
литерал
'''
"""
И это тоже многострочный литерал.
Удобно для документирования кода
"""
\n указывает на конец строки.
print("Однажды, в студеную зимнюю пору,\nЯ из лесу вышел.\nБыл сильный мороз")
Функция len() возвращает количество символов в строке.
print(len('В этой фразе тридцать три символа'))
Объединение строк называется конкатенацией. Это очень частое действие в программировании.
a = "Миру"
b = "мир"
c = a + ' - ' + b + '!'
print(c)
Этот код не сработает. Почему?
a = 'Огурец '
print(a + 10)
А этот код будет работать. Python забавный =)
a = 'Огурец '
print(a * 10)
.index() — на какой позиции встречается подстрока?
.count() — сколько раз встречается подстрока?
.startswith() — проверить, что начинается с подстроки
.endswith() — проверить, что заканчивается на подстроку
string = "Привет, Мир!"
print(string.index('и')) # выведет 2. Почему?
print(string.count('и')) # выведет 2
print(string.startswith("Привет")) # True
print(string.endswith("никогда")) # False
f-строки сами заботятся о приведении типов
a = 1
b = 2
c = f'Если сложить {a} и {b}, то получится {(a + b)}'
print(c)
Это очень легко.
string = "Hello world!"
print(string[6:11]) # world взять подстроку от 6 до 11 символа
print(string[6:]) # world! взять подстроку от 6 символа и до конца
print(string[:5]) # Hello взять с начала до 5 символа
print(string[-1:]) # ! взять 1 символ с конца
print(string[0:10:2]) # Hlowr с указанным шагом [start, from, step]
print(string[::-1]) # !dlrow olleH перевернуть строку
print(string.upper()) # HELLO WORLD!
print(string.lower()) # hello world!
Продолжайте пробовать.
string = "1234567890"
print('1:', string[::2])
print('2:', string[1::2])
print('3:', string[::-1])
string = string[::-1]
print('\n4:', string)
print('5:', string[::-1])
Детектор палиндромов. Палиндром — слово которое читается одинаково слева направо и справа налево.
Синтаксис лямбда-функции описан ниже. Вернитесь к этому примеру потом.
dromes = ("demigod", "rewire", "madam", "freer", "anutforajaroftuna", "kiosk")
palindromes = list(filter(lambda word: word == word[::-1], dromes))
print(palindromes)
.replace(из, на) — строковая замена
a = 'По лесам, по лесам, синий трактор едет к нам...'
b = a.replace('лесам', 'полям')
print(b)
S-строки
pi = 3.1415926535
pi_short = '%.2f' % pi
print(pi_short)
Ещё пример.
values = (1, 2, 3)
string = '%s, %s и %s' % values
print(string)
[] # пустой список
[1, 2, 3, 4]
.append(что) — добавить в конец списка.
numbers = []
numbers.append(1)
numbers.append(2)
numbers.append(3)
print(numbers)
.insert(куда, что) — вставить в указанное место.
listing = [1, 2, 3, 4, 5]
listing.insert(0, 'тут')
print(listing)
listing = [1, 2, 3, 4, 5]
listing.insert(2, 'тут')
print(listing)
listing = [1, 2, 3, 4, 5]
listing.insert(-1, 'тут')
print(listing)
listing = [1, 2, 3, 4, 5]
listing.insert(-2, 'тут')
print(listing)
listing = [1, 2, 3, 4, 5]
listing.insert(len(listing), 'тут')
print(listing)
Списки можно легко объединять.
a = [1, 2, 3]
b = [4, 5, 6]
c = a + b
print(c)
Списки удобно итерировать (перебирать) циклами.
listing = [1, 2, 3, 4, 5]
for i in listing:
print(i)
В обратном порядке? Это тоже легко.
listing = [1, 2, 3, 4, 5]
for i in listing[::-1]:
print(i)
Можно получать элементы по индексу.
listing = [1, 2, 3, 4, 5]
print(listing[0]) # 1
print(listing[2]) # 3
print(listing[10]) # ошибка
Обратите внимание, как это похоже на работу со строками. Прекрасно!
listing = [1, 2, 3, 4, 5, 6, 7, 8, 9]
print('Нечетные:', listing[::2])
print('Четные:', listing[1::2])
print('От 4 до конца:', listing[3:])
print('От начала до 3:', listing[:3])
print('Два последних:', listing[-2:])
print('Сначала кроме двух последних:', listing[:-2])
Списки можно итерировать (перебирать).
names = ['artem', 'ramil']
uppered_names = []
for name in names:
uppered_names.append(name.title())
print(uppered_names)
А можно сделать однострочник.
map(функция, список) — применяет функцию к каждому элементу списка.
names = ['artem', 'ramil']
uppered_names = list(map(str.title, names))
print(uppered_names)
filter(функция, список) — удаляет элементы по ответу от проверяющей функции.
numbers = [9, 8, 7, 6, 5, 4, 3, 2, 1]
def odd(number):
return not number % 2
odds = list(filter(odd, numbers)) # выбрать все нечетные
print(odds)
С помощью лямбда-функции можно делать красивые однострочники
lambda аргумент: возвращаемое значение
numbers = [9, 8, 7, 6, 5, 4, 3, 2, 1]
odds = list(filter(lambda number: not number % 2, numbers))
print(odds) # выбрать все четные
Оператор in проверяет, входит ли значение в перечисление.
what = 5
where = [3, 4, 5]
gotit = what in where
print(gotit) # True, нашёл
Генераторы — это простые функции, которые возвращают итерируемое множество элементов по одному за раз.
Генератор запускается оператором for. Как только код функции генератора достигает оператора «выход» yield, генератор передает свое выполнение обратно в цикл for, возвращая новое значение из множества. Генератор может генерировать любое количество значений, выдавая их по очереди.
import random
def lottery():
# вернет 6 чисел от 1 до 40
for i in range(6):
yield random.randint(1, 40)
# вернет седьмое число от 1 до 15
yield random.randint(1, 15)
for random_number in lottery():
print("И следующее число, это... %d!" % random_number)
Генераторы списков и однострочники
Функция range(от, до, шаг) возвращает последовательность чисел.
Вот такой код...
numbers = range(10)
even = []
for number in numbers:
if not number % 2:
even.append(number)
print(even)
...можно упростить до такого
numbers = range(10)
even = [num for num in numbers if not num % 2]
print(even)
Генераторы списков (List Comprehensions) — это более изящная форма для записи циклов обработки списков.
Синтаксис тоже прост: [что откуда какие]. Можно посмотреть много примеров с однострочниками на канале Клуба Хакеров.
Ещё можно отметить, что такие программы быстрее работают. Это бывает критичным при больших объёмах данных, например в Data Science, или при высоких требованиях к быстродействию.
Целые или вещественные числа можно создать с помощью литералов.
a = 5 # int
b = 5.0 # float
c = 0 # int
d = 0.0 # float
Приведение типов может быть явным.
a = 5
print(a)
b = float(a)
print(b)
c = int(b)
print(c)
Словари — они как списки. Только для доступа используются не индексы, а любые объекты.
digits = {
"one": 1,
"two": 2,
"three": 3,
}
print(digits)
Можно добавлять новые элементы и получать доступ к ним.
numbers = {}
numbers["Семен"] = "2-33-44"
numbers["Евгений"] = "3-44-55"
numbers["Анатолий"] = "4-55-66"
print(numbers)
Словари можно перебирать точно так же, как и списки.
Метод .items() возвращает генератор. Копия данных при этом не создаётся.
numbers = {}
numbers["Василий"] = "2-33-55"
numbers["Евгений"] = "3-44-77"
numbers["Анатолий"] = "7-00-11"
for name, number in numbers.items():
print("У пользователя %s номер телефона %s" % name, number)
Можно удалить строчку из словаря.
numbers = {"Василий": "2-33-55", "Евгений": "3-44-77", "Анатолий": "7-00-11"}
print('Было:', numbers)
del numbers["Василий"]
print('Стало:', numbers)
Или так
numbers = {"Василий": "2-33-55", "Евгений": "3-44-77", "Анатолий": "7-00-11"}
print('Было:', numbers)
removed = numbers.pop("Василий")
print('Стало:', numbers)
print('Убрал:', removed)
Множества set — это списки без повторов.
split() разделяет строку в список, а set() приводит список в множество и таким образом удалит повторы.
print(set("моё имя Артем и Артем моё имя".split(' ')))
С помощью множеств удобно вычислять пересечения списков.
a = set(["Первое", "Второе", "Третье"])
b = set(["Третье", "Четвертое"])
print('Пересечение')
print(a.intersection(b))
print(b.intersection(a))
print('\nСимметричная разница')
print(a.symmetric_difference(b))
print(b.symmetric_difference(a))
print('\nРазница')
print(a.difference(b))
print(b.difference(a))
print('\nОбъединение')
print(a.union(b))
Процедура — это последовательность действий.
Процедура, которая принимает и возвращает значения, называется функцией.
Процедура и функция являются частями кода, предназначеными для многократного использования.
Картинка для понимания анатомии функции:
Функция принимает и возвращает значения. Хотя это и не обязательно.
Оператор def указывает на то, что создаётся новая функция.
Оператор return возвращает значение функции и прерывает её работу.
Аргументы (параметры) передаются функции в скобках. Тело этой функции отделено от другого кода отступом. В конце определения названия и аргументов функции стоит двоеточие.
def multiply(a, b):
c = a * b
return c
a = 10
b = 20
c = multiply(a, b)
print(f'{a} * {b} = {c}')
a = 55
b = 77
c = multiply(a, b)
print(f'{a} * {b} = {c}')
Можно задать аргументы по умолчанию.
def sayhello(username, greeting = "хорошего дня"):
print(f"Привет, {username}! Я желаю тебе {greeting})")
sayhello('Артем', 'хорошего настроения') # что выведет?
sayhello('Артем') # что выведет?
Функция может иметь переменное количество аргументов.
def test(one, *other):
print('\n1:', one)
print('2:', other)
test(1)
test(1, 2)
test(1, 2, 3, 4, 5)
Лямбда-функция — это короткая запись функции.
Синтаксис лямбда-функции: lambda параметры: возвращаемое значение
a = 1
b = 2
sum = lambda x,y: x + y
print(sum(a,b))
Следующая тема про функции чуть сложнее. Но не беспокойтесь, вы будете редко пользоваться этим. Замыкание — это функция внутри функции, которая также может запоминать ранее переданные значения.
def print_msg(number):
def printer():
number = 3
print(number)
printer()
print(number)
print_msg(9) # напечатает 3 9
Создавая код классов, вам может понадобится заглушка для тел функций, которые пока не заполнены кодом. Вы можете использовать оператор pass, что означает «пропустить».
def stub():
pass
Код класса тоже можно «пропустить».
class Someclass:
pass
Следующие два примера кода идентичны.
a = 10
b = 'Николай'
print(a, b)
a, b = 10, 'Николай'
print(a, b)
Таким способом можно распаковать список или кортеж. Это удобно для реализации разных архитектурных паттернов.
a, b = [10, 'Достоевский']
print(a, b)
settings = ['superhero', 'swordfish']
login, password = settings
print(login, password)
Можно создавать код, более устойчивый к ошибкам.
Для этого есть блоки try/except.
def test():
try:
print(b)
except:
print('Но у меня нет переменной b!')
test()
ООП — объектно-ориентированное программирование. Это способ программирования с использованием классов и объектов.
Объект — это программная сущность, в которой есть функции и переменные.
Функции объекта называются методами.
Переменные и константы объекта называются свойствами.
Класс — это программа, с помощью которой создаются объекты.
Чем объект отличается от класса?
Класс |
Объект |
---|---|
Абстрактен. Это программа, которая описывает объект | Материален. Это экземпляр класса — объект создаётся из класса во время выполнения программы |
Программист создаёт классы. Классы — это части программы | Объекты создаёт интерпретатор (или ОС) из классов, во время выполнения программы |
У класса могут быть методы и свойства (функции и переменные). Они будут у объектов этого класса. | У объекта могут быть методы и свойства (функции и переменные). Как в классе задано, из которого сделан объект — то в нём и будет |
Обычно имена классов пишут с большой буквы. Имена объектов — с маленькой.
Определение класса выглядит так:
class Cow:
color = "black"
def moo(self):
print('Moo')
Создадим объект из этого класса.
class Cow:
color = "black"
def moo(self):
print('Муу')
cow = Cow()
cow.moo() # выведет "Муу"
Можно получить доступ к свойству объекта.
class Cow:
color = "black"
cow = Cow()
cow.color = "white"
print(cow.color) # эта корова будет белой
cow2 = Cow()
cow2.color = "blue"
print(cow2.color) # эта корова будет не совсем белой
Можно продемонстрировать свое прекрасное воспитание и хорошие манеры, если не лезть напрямую в свойства объекта, а использовать специальные методы — сеттеры и геттеры.
Сеттер, от английского set — устанавливать.
Геттер, от английского get — получать.
self — это ссылка на объект, созданный из этого класса. Как обратиться к методу или свойству объекта изнутри? Через self.
class Cow:
color = "black"
def set_color(self, color):
self.color = color
def get_color(self):
return self.color
cow = Cow()
cow.set_color("white")
print(cow.get_color())
cow2 = Cow()
cow2.set_color("blue")
print(cow2.get_color())
cow3 = Cow()
print(cow3.get_color()) # по умолчанию коровы черные
Зачем нужны сеттеры и геттеры?
Во-первых, во время записи и считывания свойств при дальнейшей разработке программы могут быть выполнены любые действия. Вы создаёте отличный каркас, логичный и понятный, для комфортной разработки.
Во-вторых, вы не вставляете палки в колеса и не создаёте самому себе проблем, напрямую записывая и считывая свойства. Измениться может что угодно — от имени этих свойств, до типов данных, способов извлечения и получения и многое другое. Изменения в одном месте не должны влечь массовые изменения в других частях программы.
Мораль: каждому классу — отдельный файл. Помещайте по одному классу в один файл. Имя файла должно точно соответствовать имени класса. Это очень удобно.
Про модули и пакеты рассказано ниже.
Конструктор — это приватный метод, который автоматически выполняется при создании объекта из класса.
class Cow:
def __init__(self, color):
self.set_color(color)
def set_color(self, color):
self.color = color
def get_color(self):
return self.color
cow = Cow("white")
print(cow.get_color())
cow2 = Cow("blue")
print(cow2.get_color())
Конструктор создаётся с помощью ключевого слова __init__()
Конструктор выполняется автоматически при создании нового объекта класса.
При создании новых классов можно наследовать методы и свойства от других классов.
Класс-родитель указывается в скобках при создании дочернего класса.
class Person():
def create(self, name, surname):
self.name = name
self.surname = surname
def get(self):
return [self.name, self.surname]
class Employee(Person):
pass
new = Employee()
new.create('Ilon', 'Mask')
print(new.get())
Следующие темы к «Основам» уже не относятся. Это скорее практика.
Модули в Питоне — это просто файлы, с раcширением .py
В модуле могут быть функции, классы и переменные.
crm/
crm/program.py
crm/database.py
Файл program.py содержит основные функции программы. А в файл database.py выделены функции для работы с базой данных. Иными словами, модуль database содержит логику, которая позволяет работать с базой данных.
Модули импортируются из других модулей с помощью команды import.
Для следующих примеров онлайн-интерпретатор не подойдёт. Установите Python на свой компьютер или в виртуальную машину.
Создайте файл program.py
import database
def main():
database.get_data()
print('Программа запущена!')
# это условие позволяет проверить, что этот файл запущен как программа, а не подгружен из другого файла как модуль. Если так, то выполнить точку входа - функцию main
if '__main__' == __name__:
main()
def get_data():
print("Данные получены!")
После запуска program.py мы можем увидеть, что выполнены функции из обоих файлов.
Для того, чтобы вызвать функцию из модуля, сначала указывается имя модуля, а потом, через точку, имя функции.
import database
database.get_data()
При запуске этой программы появилась директория `__pycache__ ` с файлами *.pyc. Питон компилирует файлы в байт-код, поэтому ему не нужно анализировать файлы каждый раз при загрузке модулей. Если файл pyc существует, он загружается вместо файла py, и вы можете контролировать это.
Вы можете импортировать модуль в текущее пространство имён с помощью команды from.
from database import get_data
def main():
result = get_data() # get_data() - из database.py, теперь так вместо database.get_data()
Теперь для вызова функции get_data не надо использовать префикс с точкой database.
Удобство заключается в том, что теперь не нужно указывать, из какого именно модуля вы взяли эту функцию. В тоже время, в любом пространстве имён не может быть двух объектов с одинаковыми именами, поэтому импорт заменяет существующий объект.
Импорт всех объектов из модуля
from database import *
Звездочка * означает "всё". Кстати, не только в Python.
Это несколько рискованно, так как можно импортировать то, что перепишет то, что у вас уже есть, или не должно быть переписано.
Вы можете переименовывать модули при загрузке.
import numpy as np
Можно добавить логику переименования
if threed:
import threed as rasterizer
else:
import plain as rasterizer
В примере выше, переменная threed должна содержать False, если не требуется 3Д-отрисовка. И True, если требуются визуализация в 3Д, и платформа пользователя поддерживает её. В зависимости от доступности и востребованности 3Д-режима визуализации, будут использоваться два разных модуля под одинаковым именем. Если в этих модулях заданы одноименные функции для визуализации — остальной код программы может и не догадываться о том, как именно производится визуализация в данный момент.
Инициализация модулей
При первой загрузке модуля он инициализируется сам однократным исполнением его кода. Если другой модуль снова импортирует этот же модуль, он не будет загружен дважды — поэтому локальные переменные внутри модуля действуют по паттерну проектирования Синглтон — они инициализируются только один раз.
Полезно знать, что вы можете положиться на это поведение при инициализации объектов.
# в модуле database.py
class Database():
def __init__():
# установить соединение с базой данных
database = Database() # ОДНО соединение с базой данных будет установлено и использовано повторно в других модулях программы
Указание пути загрузки модуля
Можно указывать Python, где находятся модули, которые вы хотите загружать.
PYTHONPATH=/dir python3 crm.py
Это выполнит crm.py, и включит загрузку скриптов из директории /dir как будто это локальная директория.
А ещё можно использовать функцию sys.path.append. Её надо использовать *перед* командой import.
sys.path.append('/dir')
Встроенных функций очень много. Можно исследовать их тут: https://docs.python.org/3/library/
При изучении этих функций пригодятся две очень важные офункции — dir и help.
Можно посмотреть список функций, к примеру в консоли Python3
С помощью команды help можно открыть справку
help(numpy)
Пакеты — это просто директории с модулями.
Каждый пакет Python 3 должен быть директорией, в которой должен быть специальный файл __init__.py
Этот файл может быть пустым, и именно он показывает Питону, что эта директория — его пакет, и что его можно импортировать.
Имя директории должно соответстовать имени пакета.
Вот несколько полезных однострочников из статьи Abhay Parashar.
Попробуйте самостоятельно проанализировать и изменить их.
a, b = 4, 5
print(a, b)
a, b = b, a
print(a, b)
a, b, *c = [1, 2, 3, 4, 5]
print(a, b, c)
a = [1, 2, 3, 4, 5, 6]
s = sum([num for num in a if num % 2 == 0])
print(s)
a = [1, 2, 3, 4, 5]
del a[1::2]
print(a)
listing = [i for i in range(0, 10)]
print(listing)
listing = [('Привет ' + i) for i in ['Иван', 'Андрей', 'Семен']]
print(listing)
listing = list(map(int, ['1', '2', '3']))
print(listing)
listing = list(map(float, ['1', '2', '3']))
print(listing)
listing = {x**2 for x in range(10) if x % 2 == 0}
print(listing)
Популярная задача на собеседованиях. Напечатать список чисел, вывести Fizz вместо чисел, кратных 3, и Buzz, вместо чисел, кратных 5. Если число кратно и 3, и 5, тогда вывести FizzBuzz.
result = ['FizzBuzz' if i % 3 == 0 and i % 5 == 0 else 'Fizz' if i % 3 == 0 else 'Buzz' if i % 5 == 0 else i for i in range(1,20)]
print(result)
text = input('Введите слово для проверки на палиндром')
ispalindrome = text == text[::-1]
print(text, ' это палиндром' if ispalindrome else ' это не палиндром')
n = 25
print('\n'.join('?' * i for i in range(1, n + 1)))
Найдём простые числа?
l = list(filter(lambda x:all(x % y != 0 for y in range(2, x)), range(2, 13)))
print(l)
import random;
print(random.choice(['Орёл', 'Решка']))