Tips and tricks from my Telegram-channel @pythonetc, November 2019


    Tips and tricks from my Telegram-channel @pythonetc, November 2019

    It is a new selection of tips and tricks about Python and programming from my Telegram-channel @pythonetc.

    Previous publications.



    PATH is an environment variable that stores paths where executables are looked for. When you ask your shell to run ls, the shell looks for the ls executable file across all paths that are presented in 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

    In the example above paths are separated by : in PATH. No escaping is possible: a path that contains : cannot be used inside PATH.

    However, that is not true for all operating systems. In Python you can get the right separator for the local system with os.pathsep:

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

    os.pathsep is not to be mixed up with os.path.sep which is the separator for file paths:

    >>> os.path.sep
    '/'



    To make regular expressions more readable you may use the re.VERBOSE flag. It allows you to use extra spaces wherever you want as well as add comments with the # symbol:

    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 is an alias for re.VERBOSE.



    complex is the Python built-in type for complex numbers:

    >>> 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)'

    There is not need to use it directly though since Python has literals for complex numbers:

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



    a : b : c notation can be used to define slice(a, b, c) only within brackets:

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

    If you want to pass the slice object as an argument to a function, you have to define it explicitly:

    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],
    ))

    Here is how you can convert such a function to an object that supports [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__ is a powerful tool that allows you to easily use delegation pattern when it’s appropriate. Here is how you add an ability to be comparable to a non-comparable object:

    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
    
    Mail.ru Group
    790.64
    Building the Internet
    Share post

    Comments 1

      0
      что-то пошло не так

      Only users with full accounts can post comments. Log in, please.