Junior Python School
706 subscribers
92 photos
29 links
Surprising the python community with pure python 🔝

Moving channel from Russian to English.


Enthusiastic reviews can be written to @pythonjuniorschoolacc ❤️
Download Telegram
Проекты написанные на django
Python interning
Shared objects - ranges и специфические объекты неизменяемого типа которые CPython инстанцирует и загружает в память каждый раз при запуске интерпретатора
Более того, python умеет интернировать(кешировать ASCII символы, цифры или _ в памяти во время создания новой строки) строки меньше 20 символов
Это все помогает оптимизировать работу python.

Отсюда вывод:
Python что-то ускоряет, когда может:
Пример 1
>> a = 'ee'
>> a[0] is a[1]
True

>> a='x'
>> b='x'
>> a is b
True

Пример 2
>> a = 'ΩΩ'
>> a[0] is a[1]
False

>> a='Ω'
>> b='Ω'
>> a is b
False

Обычно python умеет делать много чего неявно, но его можно заставить...
>> a = 'I hate frontend'
>> b = 'I hate frontend'
>> a is b
False

>> import sys
>> c = sys.intern('I hate frontend')
>> d = sys.intern('I hate frontend')
>> c is d
True
>> c is a
False

Самый простой способ узнать про неявное интернирование - проверить id объекта.
>> s='*'
>> for i in range(2):
.. s+='*'
.. print(id(s), s)
140277841241232 **
140277841241232 ***
Хочу обсудить питонячье понимание модификаторов доступа.
Модификаторы доступа помогают разделить методы и переменные на не предназначенные для внешнего использования, не рекомендуемые для использования из вне и предназначенные только для использования внутри.
Для этого используются нижние подчеркивания перед именем.
class Underscore:

def method():
return 'public method'

def _method(): # одно _ работает на уровне соглашения — означает, что лучше такую переменную не трогать из вне
return 'It is better not to use this method outside'

def __method(): # два __ - питон не даст явно вызвать такой метод из вне(AttributeError)
return 'private method'
Это была простая часть. Очень известная. Но есть более продвинутые штуки.
Переменная с даже одним _ - не импортируется звездочкой
from module import *
Стандартно будут импортироваться только public methods.
Чтобы получить доступ к переменной с нижнем подчеркиванием нужно явно указать ее при импорте, или внести в список __all__ импортируемого модуля.
from module import _var
*Кстати, питонисты используют нижнее подчеркивание в конце имени, чтобы избежать конфликтов имен. Про это читай в PEP8

В питоне, если очень хочется, то можно сделать все. (Ну почти)
Даже достучаться к приватному методу)) Это называется name mangling - искажение имен.
На самом деле питон просто сохраняет имена начинающиеся с двух подчеркиваний немного иначе
class Magic:
def __private(self):
return 'I am private AF'
Попробуем вызвать метод
magic = Magic()
magic.__private()
Получим ожидаемое:
AttributeError: 'Magic' object has no attribute '__private'
На самом деле питон создал этот метод, но с именем _Magic__private, то есть долепил имя класса в имя, чтобы нельзя было переопределить метод точно так же в потомке
Проверим
magic.__Magic__private()
'I am private AF'
Питон искажает имена всех переменных, которые начинаются с двойного подчеркивания. Вот такой вот хак.
Задачка
Почему это работает?

_MagicUnderscore__secret = 'Эта дичь сработает?'


class MagicUnderscore:

def magic(self):
return __secret


print(MagicUnderscore().magic())
Вернет
Эта дичь сработает?

Подумай, почему оно так работает?
Сегодня решил поговорить про lambda functions в python.
lambda функция - анонимная функция(у которой нет имени)
Как мы знаем, в питоне все - объекты. Даже функции. А если объект может существовать без имени, то и функция может просто можно работать с функцией как с объектом.

Простой пример
def hello(me, name):
return f'Hello from {me}, {name}!'
Ничто иное как
hello = lambda me, name: f'Hello from {me}, {name}!'
В общем, ничего сложного - просто функции одного выражения. Кратко и удобно, можно сразу отправлять такую lambda, как аргумент в функцию.
Так и часто и используют, как аргументы функций. Простой пример:
sorted(range(-5, 6), key=lambda x: x * x)
Но все же чаще функции побольше, их удобнее читать в стандартном формате.
Сначала все просто, as always.
Но у питона свои особенности, как всегда и их стоит учитывать.
Lambda функции в питоне живут в nonlocal пространстве и умеют запоминать свой контекст.
Пример
def hello(me):
return lambda name: f'Hello from {me}, {name}!'
greeting = hello('Jack')
greeting('Kate')
Вернет
'Hello from Jack, Kate!'
То есть lambda помнит переменные своего подпространства (me), связана с ними и может их использовать.
Важно не использовать lambda функции просто так.
Я видел код вида
class Hello:
greet = lambda self: print('Hello')
Это может показаться короче, но читать и поддерживать такой код сильно сложнее, к сожалению.
После простой теории надо давать убийственные примеры, а то скучно.


names = ['Jack', 'Michael', 'Kate', 'Jimmy', 'Python']


def greetings():
return [lambda me: f'Hello from {me}, {name}!' for name in names]


for greeting in greetings():
print(greeting('Creator'))

Вернет
Hello from Creator, Python!
Hello from Creator, Python!
Hello from Creator, Python!
Hello from Creator, Python!
Hello from Creator, Python!
Подумай, почему оно так работает?
Если в python3
s = 'f(φ)==f(φ)'
то
s[1] is s[7], s[2] is s[8]

Вернет
Что выведет запрос?

Вариант 1 - 2
👍👍👍 11%
Вариант 2 - 6
👍👍👍👍👍👍👍👍 32%
Вариант 3 - 4
👍👍👍👍👍👍 21%
Вариант 4 - 1
👍👍 5%
А где python? - 6
👍👍👍👍👍👍👍👍 32%
👥 19 человек уже проголосовало.
Channel name was changed to «Junior Python School»
Если у вас есть знакомые питонисты - киньте им этот тест, запутаться в этом может каждый.



fromkeys - позволяет из последовательности и значения сделать словарь с элементами последовательности с данным значением
>>> dict.fromkeys(['python', 'sql', 'c++'], 'good')

{'python': 'good', 'sql': 'good', 'c++': 'good'}



Или setdefault - если ключ в словаре не найден - то создаст этот ключ с заданным значением по умолчанию и вернет его.
>>> d = {'python': 'cool', 'js': 'oh no', 'sql': 'good'}

>>> d.setdefault('js', 'bad')

'oh no'

>>> d.setdefault('php', 'bad')

'bad'



Или get - позволяет получить значение из словаря по ключу или какое-то значение по умолчанию, если ключ не найден.
Пользуюсь этим методом постоянно.
Часто удобнее, чем просто стучаться к элементу через квадратные скобочки ибо не выкидывает исключение KeyError, если ключа не найдено.
>>> d = {'python': 'cool', 'js': 'oh no', 'sql': 'good'}

>>> d.get('js', 'no such key')

'oh no'

>>> d.get('php', 'no such key')

'no such key'

>>> d['php']

Traceback (most recent call last):
 File "<input>", line 1, in <module>
KeyError: 'php'



Интересное происходит с popitem - этот метод возвращает случайную пару ключ-значение из словаря и удаляет его их словаря.
>>> d = {'python': 'cool', 'js': 'oh no', 'sql': 'good'}

>>> d.popitem()

('sql', 'good')

>>> d

{'python': 'cool', 'js': 'oh no'}



С pop похожая ситуация - этот метод удаляет заданное значение из словаря и возвращает значение удаленного элемента. При этом у метода есть тоже параметр по умолчанию, он возвращается если ключа не найдено. Если пара не найдена - кидается наше любимое исключение KeyError
>>> d = {'python': 'cool', 'js': 'oh no', 'sql': 'good'}

>>> d.pop('php', 'no such value')

'no such value'

>>> d.pop('js')

'oh no'

>>> d.pop('php')

Traceback (most recent call last):
 File "<input>", line 1, in <module>
KeyError: 'php'



Про keys, values и items - особо говорить не нужно. Нужны чаще всего для итерации по словарю. Нужно только обратить внимание, что возвращаются объекты типов dict_keys, dict_values и dict_items
>>> d = {'python': 'cool', 'sql': 'good'}

>>> d.keys()

dict_keys(['python', 'sql'])

>>> d.values()

dict_values(['cool', 'good'])

>>> d.items()

dict_items([('python', 'cool'), ('sql', 'good')])



Посмотрим на вообще все публичные методы
(которые не начинаются с нижнего подчеркивания)
>>> [attr for attr in dir(dict()) if attr[0]!='_']

>>> ['clear', 'copy', 'fromkeys', 'get', 'items', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values']



Мы не рассмотрели еще методы copy, clear и update.
C ними все не сложно:
copy - создает shallow копию данного словаря,
clean - удаляет все ключи и значения из словаря и оставляет его пустым,
update - обновляет словарь значениями из другого словаря.
>>> d1 = {1:1 , 2:3}
>>> d2 = {3:3 , 2:2}
>>> d1.update(d2)
>>> d1
{1: 1, 2: 2, 3: 3}



Лайфхак для пользователей python 3.5+
update можно заменить вот так:
{**d1, **d2}
{1: 1, 2: 2, 3: 3}
Пришло время обсудить вот этот тест.

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


Запустим в интерпретаторе:
>>> isinstance((), tuple)
True
>>> isinstance((1), tuple)
False
>>> isinstance((1, 2), tuple)
True

Все, можно спокойно выбрать правильный ответ))😜

Но почему так?
Что мы на самом деле делаем:
Мы проверяем является ли какое-то значение объектом класса кортеж.

Значение () - это способ объявления пустого кортежа

Значение (1) - это просто 1 в скобочках
>>> type((1))
<class 'int'>
Для того, чтобы сделать это значение кортежем нужно просто добавить запятую: (1,)
>>> type((1,))
<class 'tuple'>

Ну а (1, 2) - это простой кортеж из двух элементов.

Лайфхак:
Функция tuple() - позволяет сделать из любой последовательности кортеж.

Пример:
>>> tuple('join us')
('j', 'o', 'i', 'n', ' ', 'u', 's')
>>> tuple(['Поделись', 'каналом', 'c', 'друзьями'])
('Поделись', 'каналом', 'c', 'друзьями')
Наша команда создала тест

Просто 9 вопросов по python. В конце можно получить сертификат о прохождении - мелочь, а приятно)
Немного поменяли способ подсчета баллов теста выше.
Все результаты пересчитаны, чтобы стало проще
Интересно увидеть статистику по всем пользователям?
Anonymous Poll
50%
Покажите графики
19%
Покажите лучших
31%
Ещё тестов создайте
Статистика по тесту 📊.

Пока что его прошло 77 человек. Особенно радует, что многие проходили его несколько раз с одного ip, чтобы получить заветную пятерку!


Наша команда уже готовит следующий тест - не пропусти.


У нас есть план запустить бесплатный интенсив, без какой-либо жуткой рекламы, по модулю itertools.

Покажем базовые возможности, а также красивые и удобные фишки библиотеки.

Если интересно поучаствовать - напиши об этом нашему боту, хотим знать сколько тут замотивированных на учебу!




Поделись каналом с друзьями - мы сейчас только начинаем развиваться, и без твоей помощи ничего грандиозного не получится)

Твоя обратная связь мотивирует команду Junior Python School работать лучше и быстрее, пользуйся этим)

Участвуй в нашем конкурсе. Шансы выиграть что-то сейчас очень высоки!