Подборка @pythonetc, ноябрь 2019

от автора

Новая подборка советов про Python и программирование из моего авторского канала @pythonetc.

Previous publications

PATH — это переменная окружения, в которой хранятся пути, по которым ищутся исполняемые файлы. Когда вы просите оболочку выполнить ls, она сначала ищет исполняемый файл ls по всем путям, указанным в PATH.

$ echo $PATH /usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/v.pushtaev/.local/bin:/home/v.pushtaev/bin $ which ls /usr/bin/ls

В этом примере пути в PATH разделены с помощью :. Путаница не возникнет: если путь содержит :, то он не может использоваться в PATH.

Но это верно не для всех операционных систем. В Python вы можете узнать правильный разделитель для вашей ОС с помощью os.pathsep:

Python 3.5.0 [...] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> import os >>> os.pathsep ';'

Не путайте os.pathsep с os.path.sep, которая является разделителем для путей к файлам:

>>> os.path.sep '/'

Чтобы регулярные выражения легче было читать, можете использовать флаг re.VERBOSE. Он позволяет использовать дополнительные пробелы везде, где хотите, а также добавлять комментарии после символа #:

import re  URL_RE = re.compile(r'''     ^     (https?)://     (www[.])?     (     (?: [^.]+[.] )+     (   [^/]+    )  # TLD     )     (/.*)     $ ''', re.VERBOSE)  m = URL_RE.match('https://www.pythonetc.com/about/') schema, www, domain, tld, path = m.groups()  has_www: bool = bool(www)  print(f'schema={schema}, has_www={has_www}') print(f'domain={domain}, tld={tld}') print(f'path={path}') 

re.X является псевдонимом для re.VERBOSE.

complex — это встроенный в Python тип для комплексных чисел:

>>> complex(1, 2).real 1.0 >>> abs(complex(3, 4)) 5.0 >>> complex(1, 2) == complex(1, -2).conjugate() True >>> str(complex(2, -3)) '(2-3j)'

Однако не обязательно использовать его напрямую, потому что в Python есть литералы для комплексных чисел:

>>> (3 + 4j).imag 4.0 >>> not (3 + 4j) False >>> (-3 - 4j) + (2 - 2j) (-1-6j)

Нотацию a : b : c можно использовать для определения slice(a, b, c) с помощью одних лишь скобок:

>>> [1, 2, 3, 4, 5][0:4:2] [1, 3] >>> [1, 2, 3, 4, 5][slice(0, 4, 2)] [1, 3]

Если вы хотите передать функции slice-объект в качестве аргумента, то придётся определить его явным образом:

def multislice(slc, *iterables):     return [i[slc] for i in iterables]   print(multislice(     slice(2, 6, 2),     [1, 2, 3, 4, 5, 6, 7],     [2, 4, 2, 4, 2, 4, 2], ))

Вот так можно преобразовать подобную функцию в объект, который поддерживает [a : b : c]:

from functools import partial   class SliceArgDecorator:     def __init__(self, f):         self._f = f      def __getitem__(self, slc):         return partial(self._f, slc)  slice_arg = SliceArgDecorator   @slice_arg def multislice(slc, *iterables):     return [i[slc] for i in iterables]   print(multislice[2:6:2](     [1, 2, 3, 4, 5, 6, 7],     [2, 4, 2, 4, 2, 4, 2], ))

__getattribute__ — это мощный инструмент, позволяющий легко использовать паттерн делегирования, когда это уместно. Так можно добавить возможность сравнения с несравниваемым объектом:

class CustomEq:     def __init__(self, orig, *, key):         self._orig = orig         self._key = key      def __lt__(self, other):         return self._key(self) < self._key(other)      def __getattribute__(self, name):         if name in {'_key', '_orig', '__lt__'}:             return super().__getattribute__(name)          return getattr(self._orig, name)  class User:     def __init__(self, user_id):         self._user_id = user_id      def get_user_id(self):         return self._user_id   def comparable(obj, *, key):     return CustomEq(obj, key=key)   user1 = comparable(User(1), key=lambda u: u.get_user_id()) user2 = comparable(User(2), key=lambda u: u.get_user_id())  print(user2 > user1)  # True print(user2 < user1)  # False print(user2.get_user_id())  # 2 


ссылка на оригинал статьи https://habr.com/ru/company/mailru/blog/480138/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *