Начиная с Python 3.7, модуль
Для более старых версий Python можно использовать
👉@BookPython
contextlib
предоставляет декоратор asynccontextmanager
, который позволяет определять асинхронные контекстные менеджеры точно так же, как contextmanager
:
import asyncio
from contextlib import asynccontextmanager
@asynccontextmanager
async def slow(delay):
half = delay / 2
await asyncio.sleep(half)
yield
await asyncio.sleep(half)
async def main():
async with slow(1):
print('slow')
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
Для более старых версий Python можно использовать
@asyncio_extras.async_contextmanager
.👉@BookPython
👍4
В Python нет оператора
Суть в том, что в Python есть унарный плюс, и выражение
Здесь
👉@BookPython
++
, вместо него используется x += 1
. Однако синтаксис ++x
всё ещё допустим (в отличие от x++
, который вызывает ошибку).Суть в том, что в Python есть унарный плюс, и выражение
++x
на самом деле интерпретируется как x.__pos__().__pos__()
. Этим можно злоупотребить и заставить ++
работать как инкремент (хотя так делать не рекомендуется):
class Number:
def __init__(self, value):
self._value = value
def __pos__(self):
return self._Incrementer(self)
def inc(self):
self._value += 1
def __str__(self):
return str(self._value)
class _Incrementer:
def __init__(self, number):
self._number = number
def __pos__(self):
self._number.inc()
x = Number(4)
print(x) # 4
++x
print(x) # 5
Здесь
++x
вызывает дважды __pos__()
: сначала на x
, затем на возвращённом объекте _Incrementer
, в котором второй __pos__()
вызывает inc()
, увеличивая значение.👉@BookPython
👍3🌚2❤1
Иногда в тестах нужно сравнивать сложные структуры, игнорируя некоторые значения. Обычно это делается путем сравнения отдельных значений внутри структуры:
Однако можно создать специальное значение, которое будет считаться равным любому другому значению:
Это легко реализовать, определив метод
👉@BookPython
>>> d = dict(a=1, b=2, c=3)
>>> assert d['a'] == 1
>>> assert d['c'] == 3
Однако можно создать специальное значение, которое будет считаться равным любому другому значению:
>>> assert d == dict(a=1, b=ANY, c=3)
Это легко реализовать, определив метод
__eq__
:
>>> class AnyClass:
... def __eq__(self, another):
... return True
...
>>> ANY = AnyClass()
👉@BookPython
👍5❤2🥱2❤🔥1👎1
Если вы хотите итерироваться одновременно по нескольким итерируемым объектам, функция
Вывод:
Обратите внимание, что
👉@BookPython
zip
может быть хорошим выбором. Она возвращает генератор, который выдаёт кортежи, содержащие по одному элементу из каждого исходного итерируемого объекта:
In : eng = ['one', 'two', 'three']
In : ger = ['eins', 'zwei', 'drei']
In : for e, g in zip(eng, ger):
...: print('{e} = {g}'.format(e=e, g=g))
...:
Вывод:
one = eins
two = zwei
three = drei
Обратите внимание, что
zip
принимает итерируемые объекты как отдельные аргументы, а не в виде списка аргументов. Чтобы «развернуть» значения (unzip), можно использовать оператор *
:
In : list(zip(*zip(eng, ger)))
Out: [('one', 'two', 'three'), ('eins', 'zwei', 'drei')]
👉@BookPython
👍4
💡10 функций, для продвинутых Python-разработчиков
1. Разворачиваем вложенных списков любой глубины
2. Декоратор для мемоизации результатов функции
3. Разбиение списка на куски длины n
4. Уникализация последовательности с сохранением порядка
5. Глубокий доступ к вложенным ключам словаря
6. Преобразование Python-объекта в читаемый JSON
7. Чтение последних n строк файла (аналог tail)
8. Выполнение shell-команды и возврат вывода
9. Быстрое объединение путей
10. Группировка списка словарей по значению ключа
👉@BookPython
1. Разворачиваем вложенных списков любой глубины
flatten = lambda lst: [x for sub in lst for x in (flatten(sub) if isinstance(sub, list) else [sub])]
2. Декоратор для мемоизации результатов функции
memoize = lambda f: (lambda *args, _cache={}, **kwargs: _cache.setdefault((args, tuple(kwargs.items())), f(*args, **kwargs)))
3. Разбиение списка на куски длины n
chunked = lambda lst, n: [lst[i:i+n] for i in range(0, len(lst), n)]
4. Уникализация последовательности с сохранением порядка
uniq = lambda seq: list(dict.fromkeys(seq))
5. Глубокий доступ к вложенным ключам словаря
deep_get = lambda d, *keys: __import__('functools').reduce(lambda a, k: a.get(k) if isinstance(a, dict) else None, keys, d)
6. Преобразование Python-объекта в читаемый JSON
pretty_json = lambda obj: __import__('json').dumps(obj, ensure_ascii=False, indent=2)
7. Чтение последних n строк файла (аналог tail)
tail = lambda f, n=10: list(__import__('collections').deque(open(f), maxlen=n))
8. Выполнение shell-команды и возврат вывода
sh = lambda cmd: __import__('subprocess').run(cmd, shell=True, check=True, capture_output=True).stdout.decode().strip()
9. Быстрое объединение путей
path_join = lambda *p: __import__('os').path.join(*p)
10. Группировка списка словарей по значению ключа
group_by = lambda seq, key: {k: [d for d in seq if d.get(key) == k] for k in set(d.get(key) for d in seq)}
👉@BookPython
👍5🤔4❤1
У Python очень короткий список встроенных констант. Одна из них —
В библиотеке NumPy
PEP 484 придаёт
Наконец,
👉@BookPython
Ellipsis
, которую также можно записать как ...
. Эта константа не имеет особого значения для интерпретатора, но используется в ситуациях, где такой синтаксис уместен.В библиотеке NumPy
Ellipsis
поддерживается в качестве аргумента для __getitem__
, например, x[...]
возвращает все элементы массива x
.PEP 484 придаёт
Ellipsis
дополнительный смысл: Callable[..., type]
используется для обозначения типа вызываемых объектов без указания типов аргументов.Наконец,
...
можно использовать, чтобы показать, что функция ещё не реализована. Это полностью допустимый Python-код:
def x():
...
👉@BookPython
👍5❤3👎1
Иногда программное обеспечение начинает вести себя странно в продакшене. Вместо того чтобы просто перезапустить его, вы, вероятно, захотите понять, что именно происходит, чтобы позже это исправить.
Очевидный способ сделать это — проанализировать, что делает программа, и попытаться угадать, какой участок кода выполняется. Безусловно, корректная система логирования облегчает эту задачу, но логи приложения могут быть недостаточно подробными — либо по замыслу, либо из-за настроек, ограничивающих уровень логирования.
В таком случае может пригодиться
Каждая строка в выводе
В следующем примере вывод приостанавливается до тех пор, пока кто-то не введёт данные в STDIN:
👉@BookPython
Очевидный способ сделать это — проанализировать, что делает программа, и попытаться угадать, какой участок кода выполняется. Безусловно, корректная система логирования облегчает эту задачу, но логи приложения могут быть недостаточно подробными — либо по замыслу, либо из-за настроек, ограничивающих уровень логирования.
В таком случае может пригодиться
strace
. Это утилита Unix, которая отслеживает системные вызовы. Вы можете запустить её заранее — strace python script.py
— но чаще бывает удобнее подключиться к уже работающему процессу: strace -p PID
.
$ cat test.py
with open('/tmp/test', 'w') as f:
f.write('test')
$ strace python test.py 2>&1 | grep open | tail -n 1
open("/tmp/test", O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, 0666) = 3
Каждая строка в выводе
strace
содержит имя системного вызова, его аргументы в скобках и возвращаемое значение. Поскольку некоторые аргументы являются выходными параметрами (используются для возврата результата, а не для передачи данных), вывод строки может быть прерван до завершения системного вызова.В следующем примере вывод приостанавливается до тех пор, пока кто-то не введёт данные в STDIN:
$ strace python -c 'input()'
...
read(0,
👉@BookPython
👍6❤4
Чтобы немедленно остановить выполнение программы на Python, следует использовать
И
Поскольку это может быть проблемой, можно использовать функцию
👉@BookPython
sys.exit()
. Альтернативой является функция exit()
, однако она предназначена для использования в интерактивном режиме. Благодаря строковому представлению, она может помочь пользователям, которые пытаются завершить сессию, используя exit
(что поддерживается многими оболочками):
>>> exit
Use exit() or Ctrl-D (i.e. EOF) to exit
>>> str(exit)
'Use exit() or Ctrl-D (i.e. EOF) to exit'
И
exit()
, и sys.exit()
на самом деле не завершают программу, а просто выбрасывают исключение SystemExit
. SystemExit
— это прямой подкласс BaseException
, а значит, он не может быть перехвачен через except Exception
, но может быть перехвачен через except BaseException
или через голый except:
.
>>> try:
... exit()
... except:
... 'Nothing'
...
'Nothing'
Поскольку это может быть проблемой, можно использовать функцию
os._exit
. Она не выбрасывает никаких исключений — просто завершает текущий процесс. Однако это означает, что блоки finally
, а также завершающие действия менеджеров контекста не будут выполнены.
$ python3
Python 3.4.3 (default, Apr 28 2015, 13:37:07)
[GCC 4.8.3 20140911 (Red Hat 4.8.3-9)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> try:
... os._exit(42)
... finally:
... print('Bye!')
...
$ ...
👉@BookPython
👍4❤1
Стандартный модуль
👉@BookPython
json
имеет интерфейс командной строки, который может быть полезен для форматирования JSON только с помощью Python. Модуль для этого называется json.tool
и предназначен для вызова следующим образом:
$ echo '{"a": [], "b": "c"}' | python -m json.tool
{
"a": [],
"b": "c"
}
👉@BookPython
👍4❤1
Функция
Также можно задать отрицательную точность:
Для собственных классов можно определить поведение округления с помощью метода
Значения округляются до ближайшего кратного
Если два значения одинаково близки, округление происходит в сторону чётного числа:
Иногда округление чисел с плавающей точкой может казаться неожиданным:
Это связано с тем, что большинство десятичных дробей не могут быть точно представлены в формате
Если нужно округление "в большую сторону при 0.5" (round half up), можно использовать
👉@BookPython
round
округляет число до заданной точности в десятичных знаках.
>>> round(1.2)
1
>>> round(1.8)
2
>>> round(1.228, 1)
1.2
Также можно задать отрицательную точность:
>>> round(413.77, -1)
410.0
>>> round(413.77, -2)
400.0
round
возвращает значение того же типа, что и входное число:
>>> type(round(2, 1))
<class 'int'>
>>> type(round(2.0, 1))
<class 'float'>
>>> type(round(Decimal(2), 1))
<class 'decimal.Decimal'>
>>> type(round(Fraction(2), 1))
<class 'fractions.Fraction'>
Для собственных классов можно определить поведение округления с помощью метода
__round__
:
>>> class Number(int):
... def __round__(self, p=-1000):
... return p
...
>>> round(Number(2))
-1000
>>> round(Number(2), -2)
-2
Значения округляются до ближайшего кратного
10 ** (-precision)
. Например, при precision=1
, значение округляется до кратного 0.1
: round(0.63, 1)
возвращает 0.6
.Если два значения одинаково близки, округление происходит в сторону чётного числа:
>>> round(0.5)
0
>>> round(1.5)
2
Иногда округление чисел с плавающей точкой может казаться неожиданным:
>>> round(2.85, 1)
2.9
Это связано с тем, что большинство десятичных дробей не могут быть точно представлены в формате
float
:
>>> format(2.85, '.64f')
'2.8500000000000000888178419700125232338905334472656250000000000000'
Если нужно округление "в большую сторону при 0.5" (round half up), можно использовать
decimal.Decimal
:
>>> from decimal import Decimal, ROUND_HALF_UP
>>> Decimal(1.5).quantize(0, ROUND_HALF_UP)
Decimal('2')
>>> Decimal(2.85).quantize(Decimal('1.0'), ROUND_HALF_UP)
Decimal('2.9')
>>> Decimal(2.84).quantize(Decimal('1.0'), ROUND_HALF_UP)
Decimal('2.8')
👉@BookPython
👍5❤1
Python-разработчики раньше инициализировали словари разными способами:
На первый взгляд результат один и тот же, но давай копнём глубже:
Похоже, второй способ инициализации словаря как минимум в два раза медленнее.
Давайте посмотрим, почему так, с помощью модуля
Ответ лежит на поверхности — когда ты используешь
Но в большинстве Python-приложений это не имеет значения, так как речь идёт о микросекундах. Тем не менее — стоит иметь это в виду.
👉@BookPython
>>> foo = {}
>>> foo = dict()
На первый взгляд результат один и тот же, но давай копнём глубже:
>>> timeit.timeit('{}', number=10**8)
2.65754420599842
>>> timeit.timeit('dict()', number=10**8)
6.245466648993897
Похоже, второй способ инициализации словаря как минимум в два раза медленнее.
Давайте посмотрим, почему так, с помощью модуля
dis
, который позволяет заглянуть в байткод Python:
>>> dis.dis('foo={}')
1 0 BUILD_MAP 0
2 STORE_NAME 0 (foo)
4 LOAD_CONST 0 (None)
6 RETURN_VALUE
>>> dis.dis('foo=dict()')
1 0 LOAD_NAME 0 (dict)
2 CALL_FUNCTION 0
4 STORE_NAME 1 (foo)
6 LOAD_CONST 0 (None)
8 RETURN_VALUE
Ответ лежит на поверхности — когда ты используешь
dict()
вместо {}
, ты теряешь время на лишний вызов функции.Но в большинстве Python-приложений это не имеет значения, так как речь идёт о микросекундах. Тем не менее — стоит иметь это в виду.
👉@BookPython
😱5❤3👍3
Сортировка списка с элементами
Попытка сортировки приведёт к ошибке:
Можно удалить
Это громоздко. Лучше использовать более сложную функцию ключа:
Если тип данных не поддерживает бесконечность (
👉@BookPython
None
может быть затруднительной:
In [1]: data = [
...: dict(a=1),
...: None,
...: dict(a=-3),
...: dict(a=2),
...: None,
...: ]
Попытка сортировки приведёт к ошибке:
In [2]: sorted(data, key=lambda x: x['a'])
---------------------------------------------------------------------------
TypeError: 'NoneType' object is not subscriptable
Можно удалить
None
перед сортировкой, а затем добавить их обратно (в конец или начало списка — в зависимости от задачи):
In [3]: sorted(
...: (d for d in data if d is not None),
...: key=lambda x: x['a']
...: ) + [
...: d for d in data if d is None
...: ]
Out[3]: [{'a': -3}, {'a': 1}, {'a': 2}, None, None]
Это громоздко. Лучше использовать более сложную функцию ключа:
In [4]: sorted(data, key=lambda x: float('inf') if x is None else x['a'])
Out[4]: [{'a': -3}, {'a': 1}, {'a': 2}, None, None]
Если тип данных не поддерживает бесконечность (
float('inf')
), можно сортировать кортежи:
In [5]: sorted(data, key=lambda x: (1, None) if x is None else (0, x['a']))
Out[5]: [{'a': -3}, {'a': 1}, {'a': 2}, None, None]
👉@BookPython
👍4❤2
Когда вы используете
Чтобы избежать этого, необходимо вручную вызывать
Однако, если вы используете модуль
Пример:
Вывод будет примерно такой:
Причём, начиная с Python 3.7,
Так что в Python 3.7+ вывод кода выше может быть таким:
👉@BookPython
fork
для создания нового процесса, текущее состояние генератора случайных чисел (включая seed) копируется в дочерний процесс. Это может привести к тому, что разные процессы будут генерировать одинаковые «случайные» значения.Чтобы избежать этого, необходимо вручную вызывать
random.seed()
в каждом процессе.Однако, если вы используете модуль
multiprocessing
, он уже автоматически выполняет это за вас.Пример:
import multiprocessing
import random
import os
import sys
def test(a):
print(random.choice(a), end=' ')
a = [1, 2, 3, 4, 5]
# Вызов в основном процессе
for _ in range(5):
test(a)
print()
# Вызов с multiprocessing.Process
for _ in range(5):
p = multiprocessing.Process(
target=test, args=(a,)
)
p.start()
p.join()
print()
# Вызов с использованием os.fork
for _ in range(5):
pid = os.fork()
if pid == 0:
test(a)
sys.exit()
else:
os.wait()
print()
Вывод будет примерно такой:
4 4 4 5 5
1 4 1 3 3
2 2 2 2 2
Причём, начиная с Python 3.7,
os.fork
также использует механизм at_fork
hook, который переинициализирует генератор случайных чисел, как и multiprocessing
.Так что в Python 3.7+ вывод кода выше может быть таким:
1 2 2 1 5
4 4 4 5 5
2 4 1 3 1
👉@BookPython
❤4👍2✍1
Скажем, вы хотите получить первые N элементов итерируемого объекта. Прямолинейный способ — использовать
Если вы также хотите получить индексы элементов, можно применить
Другой способ сделать это — использовать
👉@BookPython
islice
:
from itertools import islice
def fib():
a, b = 0, 1
while True:
yield b
a, b = b, (a + b)
list(islice(fib(), 5))
# Результат: [1, 1, 2, 3, 5]
Если вы также хотите получить индексы элементов, можно применить
enumerate
:
list(enumerate(islice(fib(), 5)))
# Результат: [(0, 1), (1, 1), (2, 2), (3, 3), (4, 5)]
Другой способ сделать это — использовать
zip
и range
, что может показаться более читаемым:
list(zip(range(5), fib()))
# Результат: [(0, 1), (1, 1), (2, 2), (3, 3), (4, 5)]
👉@BookPython
👍5
collections.defaultdict
позволяет создать словарь, который возвращает значение по умолчанию, если запрашиваемого ключа нет (вместо того чтобы выбрасывать исключение KeyError
).При создании
defaultdict
необходимо указывать не само значение по умолчанию, а фабрику для его создания.Это позволяет создавать словари с бесконечным числом вложенных уровней, что дает возможность писать что-то вроде
d[a][b][c]...[z]
.
>>> def infinite_dict():
... return defaultdict(infinite_dict)
...
>>> d = infinite_dict()
>>> d[1][2][3][4] = 10
>>> dict(d[1][2][3][5])
{}
Такое поведение называется “автовивификация” (от англ. autovivification) — термин пришёл из языка Perl.
👉@BookPython
👍4✍1
Некоторые модули Python компилируются непосредственно в сам интерпретатор. Они называются встроенными модулями (built-in), и их не следует путать со стандартной библиотекой. Чтобы получить полный список таких модулей, можно использовать
Обычно вам не важно, является ли модуль встроенным или нет; однако стоит иметь в виду, что
👉@BookPython
sys.builtin_module_names
. Примеры таких модулей — sys
, gc
, time
и т. д.Обычно вам не важно, является ли модуль встроенным или нет; однако стоит иметь в виду, что
import
сначала ищет модуль среди встроенных. Поэтому будет загружен встроенный модуль sys
, даже если в текущей директории есть файл sys.py
. С другой стороны, если, например, в текущей директории есть файл datetime.py
, он действительно может быть загружен вместо стандартного модуля datetime
.👉@BookPython
👍4❤1
Reduce
— это функция высшего порядка, которая рекурсивно обрабатывает итерируемый объект, применяя некоторое действие к следующему элементу и уже вычисленному значению. Возможно, вы также знаете её под названиями fold, inject, accumulate или другими.Reduce
с выражением result = result + element
даёт сумму всех элементов, result = min(result, element)
— минимум, а result = element
позволяет получить последний элемент последовательности.В Python есть функция
reduce
(в Python 3 она перенесена в functools.reduce
):
from functools import reduce
reduce(lambda s, i: s + i, range(10))
# 45
reduce(lambda s, i: min(s, i), range(10))
# 0
reduce(lambda s, i: i, range(10))
# 9
Кроме того, если вам нужны простые лямбда-функции вроде
a, b: a + b
, Python предлагает модуль operator
:
from operator import add
reduce(add, range(10))
# 45
👉@BookPython
👍4🤓1
Самый большой недостаток объектов с
Чтобы включить возможность динамического присваивания атрибутов объекту, просто добавьте
Также учтите, что наследуемые классы автоматически получают
👉@BookPython
__slots__
заключается в том, что они не могут динамически получать произвольные атрибуты. Однако можно совместить подход с __slots__
и обычным __dict__
.Чтобы включить возможность динамического присваивания атрибутов объекту, просто добавьте
'__dict__'
в __slots__
:
class A:
__slots__ = ('a', 'b', '__dict__')
A().x = 3
Также учтите, что наследуемые классы автоматически получают
__dict__
, если явно не указаны пустые __slots__
:
class A:
__slots__ = ('a', 'b')
class B(A):
pass
B().x = 3
👉@BookPython
👍3
🚀 Подборка Telegram каналов для программистов
Системное администрирование, DevOps 📌
https://t.me/bash_srv Bash Советы
https://t.me/win_sysadmin Системный Администратор Windows
https://t.me/sysadmin_girl Девочка Сисадмин
https://t.me/srv_admin_linux Админские угодья
https://t.me/linux_srv Типичный Сисадмин
https://t.me/devopslib Библиотека девопса | DevOps, SRE, Sysadmin
https://t.me/linux_odmin Linux: Системный администратор
https://t.me/devops_star DevOps Star (Звезда Девопса)
https://t.me/i_linux Системный администратор
https://t.me/linuxchmod Linux
https://t.me/sys_adminos Системный Администратор
https://t.me/tipsysdmin Типичный Сисадмин (фото железа, было/стало)
https://t.me/sysadminof Книги для админов, полезные материалы
https://t.me/i_odmin Все для системного администратора
https://t.me/i_odmin_book Библиотека Системного Администратора
https://t.me/i_odmin_chat Чат системных администраторов
https://t.me/i_DevOps DevOps: Пишем о Docker, Kubernetes и др.
https://t.me/sysadminoff Новости Линукс Linux
1C разработка 📌
https://t.me/odin1C_rus Cтатьи, курсы, советы, шаблоны кода 1С
https://t.me/DevLab1C 1С:Предприятие 8
https://t.me/razrab_1C 1C Разработчик
https://t.me/buh1C_prog 1C Программист | Бухгалтерия и Учёт
https://t.me/rabota1C_rus Вакансии для программистов 1С
Программирование C++📌
https://t.me/cpp_lib Библиотека C/C++ разработчика
https://t.me/cpp_knigi Книги для программистов C/C++
https://t.me/cpp_geek Учим C/C++ на примерах
Программирование Python 📌
https://t.me/pythonofff Python академия.
https://t.me/BookPython Библиотека Python разработчика
https://t.me/python_real Python подборки на русском и английском
https://t.me/python_360 Книги по Python
Java разработка 📌
https://t.me/BookJava Библиотека Java разработчика
https://t.me/java_360 Книги по Java Rus
https://t.me/java_geek Учим Java на примерах
GitHub Сообщество 📌
https://t.me/Githublib Интересное из GitHub
Базы данных (Data Base) 📌
https://t.me/database_info Все про базы данных
Мобильная разработка: iOS, Android 📌
https://t.me/developer_mobila Мобильная разработка
https://t.me/kotlin_lib Подборки полезного материала по Kotlin
Фронтенд разработка 📌
https://t.me/frontend_1 Подборки для frontend разработчиков
https://t.me/frontend_sovet Frontend советы, примеры и практика!
https://t.me/React_lib Подборки по React js и все что с ним связано
Разработка игр 📌
https://t.me/game_devv Все о разработке игр
Библиотеки 📌
https://t.me/book_for_dev Книги для программистов Rus
https://t.me/programmist_of Книги по программированию
https://t.me/proglb Библиотека программиста
https://t.me/bfbook Книги для программистов
БигДата, машинное обучение 📌
https://t.me/bigdata_1 Big Data, Machine Learning
Программирование 📌
https://t.me/bookflow Лекции, видеоуроки, доклады с IT конференций
https://t.me/rust_lib Полезный контент по программированию на Rust
https://t.me/golang_lib Библиотека Go (Golang) разработчика
https://t.me/itmozg Программисты, дизайнеры, новости из мира IT
https://t.me/php_lib Библиотека PHP программиста 👨🏼💻👩💻
https://t.me/nodejs_lib Подборки по Node js и все что с ним связано
https://t.me/ruby_lib Библиотека Ruby программиста
https://t.me/lifeproger Жизнь программиста. Авторский канал.
QA, тестирование 📌
https://t.me/testlab_qa Библиотека тестировщика
Шутки программистов 📌
https://t.me/itumor Шутки программистов
Защита, взлом, безопасность 📌
https://t.me/thehaking Канал о кибербезопасности
https://t.me/xakep_2 Хакер Free
Книги, статьи для дизайнеров 📌
https://t.me/ux_web Статьи, книги для дизайнеров
Математика 📌
https://t.me/Pomatematike Канал по математике
https://t.me/phis_mat Обучающие видео, книги по Физике и Математике
https://t.me/matgeoru Математика | Геометрия | Логика
Excel лайфхак📌
https://t.me/Excel_lifehack
https://t.me/mir_teh Мир технологий (Technology World)
Вакансии 📌
https://t.me/sysadmin_rabota Системный Администратор
https://t.me/progjob Вакансии в IT
Системное администрирование, DevOps 📌
https://t.me/bash_srv Bash Советы
https://t.me/win_sysadmin Системный Администратор Windows
https://t.me/sysadmin_girl Девочка Сисадмин
https://t.me/srv_admin_linux Админские угодья
https://t.me/linux_srv Типичный Сисадмин
https://t.me/devopslib Библиотека девопса | DevOps, SRE, Sysadmin
https://t.me/linux_odmin Linux: Системный администратор
https://t.me/devops_star DevOps Star (Звезда Девопса)
https://t.me/i_linux Системный администратор
https://t.me/linuxchmod Linux
https://t.me/sys_adminos Системный Администратор
https://t.me/tipsysdmin Типичный Сисадмин (фото железа, было/стало)
https://t.me/sysadminof Книги для админов, полезные материалы
https://t.me/i_odmin Все для системного администратора
https://t.me/i_odmin_book Библиотека Системного Администратора
https://t.me/i_odmin_chat Чат системных администраторов
https://t.me/i_DevOps DevOps: Пишем о Docker, Kubernetes и др.
https://t.me/sysadminoff Новости Линукс Linux
1C разработка 📌
https://t.me/odin1C_rus Cтатьи, курсы, советы, шаблоны кода 1С
https://t.me/DevLab1C 1С:Предприятие 8
https://t.me/razrab_1C 1C Разработчик
https://t.me/buh1C_prog 1C Программист | Бухгалтерия и Учёт
https://t.me/rabota1C_rus Вакансии для программистов 1С
Программирование C++📌
https://t.me/cpp_lib Библиотека C/C++ разработчика
https://t.me/cpp_knigi Книги для программистов C/C++
https://t.me/cpp_geek Учим C/C++ на примерах
Программирование Python 📌
https://t.me/pythonofff Python академия.
https://t.me/BookPython Библиотека Python разработчика
https://t.me/python_real Python подборки на русском и английском
https://t.me/python_360 Книги по Python
Java разработка 📌
https://t.me/BookJava Библиотека Java разработчика
https://t.me/java_360 Книги по Java Rus
https://t.me/java_geek Учим Java на примерах
GitHub Сообщество 📌
https://t.me/Githublib Интересное из GitHub
Базы данных (Data Base) 📌
https://t.me/database_info Все про базы данных
Мобильная разработка: iOS, Android 📌
https://t.me/developer_mobila Мобильная разработка
https://t.me/kotlin_lib Подборки полезного материала по Kotlin
Фронтенд разработка 📌
https://t.me/frontend_1 Подборки для frontend разработчиков
https://t.me/frontend_sovet Frontend советы, примеры и практика!
https://t.me/React_lib Подборки по React js и все что с ним связано
Разработка игр 📌
https://t.me/game_devv Все о разработке игр
Библиотеки 📌
https://t.me/book_for_dev Книги для программистов Rus
https://t.me/programmist_of Книги по программированию
https://t.me/proglb Библиотека программиста
https://t.me/bfbook Книги для программистов
БигДата, машинное обучение 📌
https://t.me/bigdata_1 Big Data, Machine Learning
Программирование 📌
https://t.me/bookflow Лекции, видеоуроки, доклады с IT конференций
https://t.me/rust_lib Полезный контент по программированию на Rust
https://t.me/golang_lib Библиотека Go (Golang) разработчика
https://t.me/itmozg Программисты, дизайнеры, новости из мира IT
https://t.me/php_lib Библиотека PHP программиста 👨🏼💻👩💻
https://t.me/nodejs_lib Подборки по Node js и все что с ним связано
https://t.me/ruby_lib Библиотека Ruby программиста
https://t.me/lifeproger Жизнь программиста. Авторский канал.
QA, тестирование 📌
https://t.me/testlab_qa Библиотека тестировщика
Шутки программистов 📌
https://t.me/itumor Шутки программистов
Защита, взлом, безопасность 📌
https://t.me/thehaking Канал о кибербезопасности
https://t.me/xakep_2 Хакер Free
Книги, статьи для дизайнеров 📌
https://t.me/ux_web Статьи, книги для дизайнеров
Математика 📌
https://t.me/Pomatematike Канал по математике
https://t.me/phis_mat Обучающие видео, книги по Физике и Математике
https://t.me/matgeoru Математика | Геометрия | Логика
Excel лайфхак📌
https://t.me/Excel_lifehack
https://t.me/mir_teh Мир технологий (Technology World)
Вакансии 📌
https://t.me/sysadmin_rabota Системный Администратор
https://t.me/progjob Вакансии в IT
Telegram
Bash Советы
🚀 Секреты и советы по Bash
🔹 Полезные трюки, хитрые однострочники и лайфхаки для работы в терминале.
🔹 Автоматизация, скрипты и оптимизация работы в Linux.
🔹 Стать мастером Bash легко – просто подпишись!
По всем вопросам @evgenycarter
🔹 Полезные трюки, хитрые однострочники и лайфхаки для работы в терминале.
🔹 Автоматизация, скрипты и оптимизация работы в Linux.
🔹 Стать мастером Bash легко – просто подпишись!
По всем вопросам @evgenycarter
В Python 3, после выхода из блока
Если нужно сохранить ссылку на исключение, используйте другую переменную:
В Python 2 это правило не действует.
👉@BookPython
except
переменные, в которых хранятся перехваченные исключения, удаляются из locals()
, даже если они существовали раньше:
>>> e = 2
>>> try:
... 1/0
... except Exception as e:
... pass
...
>>> e
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'e' is not defined
Если нужно сохранить ссылку на исключение, используйте другую переменную:
>>> error = None
>>> try:
... 1/0
... except Exception as e:
... error = e
...
>>> error
ZeroDivisionError('division by zero',)
В Python 2 это правило не действует.
👉@BookPython
👍4✍1❤1