es
Feedback
Python etc

Python etc

Ir al canal en Telegram

Regular tips about Python and programming in general Owner — @pushtaev The current season is run by @orsinium Tips are appreciated: https://ko-fi.com/pythonetc / https://sobe.ru/na/pythonetc © CC BY-SA 4.0 — mention if repost

Mostrar más
El país no está especificadoTecnologías y Aplicaciones16 318
6 179
Suscriptores
Sin datos24 horas
Sin datos7 días
Sin datos30 días
Archivo de publicaciones
Write a class that is instantiated with a set of disjoint intervals and has a where(k) method that finds the interval that contains k.

Welcome to the weekend task section. Below is the task the you can solve in Python. My solution will be published in 36 hours.

If you want to iterate over several iterables at once, you can use the zip function (it has nothing to do with ZIP file format):
from datetime import timedelta

names = [
    'Eleven. Return and Revert',
    'Wilderness',
    'The Menagerie Inside',
    'Evaporate',
]

years = [
    2010,
    2013,
    2015,
    2018,
]

durations = [
    timedelta(minutes=57, seconds=38),
    timedelta(minutes=48, seconds=5),
    timedelta(minutes=46, seconds=34),
    timedelta(minutes=43, seconds=25),
]

print('Midas Fall LPs:')
for name, year, duration in zip(
    names, years, durations
):
    print(f'  * {name} ({year}) — {duration}')
Output:
Midas Fall LPs:
  * Eleven. Return and Revert (2010) — 0:57:38
  * Wilderness (2013) — 0:48:05
  * The Menagerie Inside (2015) — 0:46:34
  * Evaporate (2018) — 0:43:25

When you write custom __repr__ for some object, you usually want to include representation of its attributes. For that, you should make formatting call repr() on objects, since it calls str() by default. It is done with the !r notation:
class Pair:
    def __init__(self, left, right):
        self.left = left
        self.right = right
        
    def __repr__(self):
        class_name = type(self).__name__
        return f'{class_name}({self.left!r}, {self.right!r})'

A generator can be stopped. You can explicitly call g.close() but usually garbage collector does that for you. Once close is called, the GeneratorExit is raised at the point where the generator function was paused:
def gen():
    try:
        yield 1
        yield 2
    finally:
        print('END')


g = gen()
print(next(g))  # prints '1'
g.close()  # prints 'END'
Mind three things. First, you can’t yield values while handling GeneratorExit:
def gen():
    try:
        yield 1
    finally:
        yield 3


g = gen()
next(g)
g.close()  # RuntimeError
Second, the exception is not raised if a generator is not yet started, but the generator still becomes stopped:
def gen():
    try:
        yield 1
    finally:
        print('END')


g = gen()
g.close()  # nothing
print(list(g))  # prints '[]'
Third, close does nothing if a generator is already finished:
def gen():
    try:
        yield 1
        yield 2
    finally:
        print('END')


g = gen()
print(list(g))
print('Closing now')
g.close()

# END
# [1, 2]
# Closing now

Given a list of integers sorted in ascending order and integer K, return A and B such that A + B = K and A and B are different elements of the list.

Welcome to the weekend task section you voted for. Below is the task the you can solve in Python. My solution will be publish in 36 hours.

Hi there. I guess the weekend task section is not the best that happened to the channel. Do you like it? Would you like to be continued?

mypy lets you view an inferred type of any expression. That could be useful if you don't understand why mypy is not happy with your code. It's done with the reveal_type function:
class User:
   def __init__(self, name: str) -> None:
       self._name = name
   def get_name_length(self) -> int:
       reveal_type(self._name)
       return len(self._name)

$ mypy test.py
test.py:6: error: Revealed type is 'builtins.str'
Note, that reveal_type is a pseudo-function that is only understood by mypy and executed during the analysis, not in runtime. There is no such function for Python itself, so you have to remove all reveal_type calls before running the program. For the same reason, you don't need to import reveal_type, it's always available for mypy. Another useful pseudo-function is reveal_locals, it shows types of all local variables at once.

Imagine you have a pair of classes that are a parent and a child, say User and Admin. You also have a function that takes a list of users as an argument. Can you provide a list of admins then? The answer is no: the function can add another user to the list of admins which is invalid and breaks guarantees that the list provides. However, you can provide a Sequence of admins since Sequence is read-only. The proper term here is Sequence is covariant on its members type. You can define covariant types by providing covariant=True as a TypeVar argument:
from typing import TypeVar, Generic

T = TypeVar('T', covariant=True)


class Holder(Generic[T]):
   def __init__(self, var: T):
       self._var: T = var

   def get(self) -> T:
       return self._var


class User:
   pass


class Admin(User):
   pass


def print_user_from_holder(holder: Holder[User]) -> None:
   print(holder.get())


h: Holder[Admin] = Holder(Admin())
print_user_from_holder(h)
Contrariwise, the function may require container only to put admins there. Such write-only containers are contravariant on its members type:
from typing import TypeVar, Generic

T = TypeVar('T', contravariant=True)


class Holder(Generic[T]):
   def __init__(self, var: T):
       self._var: T = var

   def change(self, x: T):
       self._var = x


class User:
   pass


class Admin(User):
   pass


def place_admin_to_holder(holder: Holder[Admin]) -> None:
   holder.change(Admin())


h: Holder[User] = Holder(User())
place_admin_to_holder(h)
Classes that are neither covariant nor contravariant are called invariant.

Write a function that takes K lists as arguments and returns all possible lists of K items where the first element is from the first list, the second is from the second and so one. Example:
assert combinations([1, 2], [3, 4]) == [
    [1, 3],
    [1, 4],
    [2, 3],
    [2, 4],
]

Welcome to the weekend task section. Below is the task the you can solve in Python. My solution will be publish in 36 hours.

Sometimes you want to exhaust a generator, but you don’t care about the values it yields. You do care about some side effect though, it may be an exception, writing to a file, global variable modification etc. The convenient and widely used way to do this is list(gen()). However, this code saves all the value into the memory just to discard them immediately after. That can be undesirable. If you want to avoid this you can use deque with the limited size instead:
from collections import deque

def inversed(nums):
    for num in nums:
        yield 1 / num

try:
    deque(inversed([1, 2, 0]), maxlen=0)
except ZeroDivisionError:
    print('E')
To be more semantically precise you better define your own exhaust function:
def exhaust(iterable):
    for _ in iterable:
        pass

The standard json module has a command line interface that can be useful to prettify JSON by python alone. The module for this is called json.tool and is meant to be called like this:
$ echo '{"a": [], "b": "c"}' | python -m json.tool
{
    "a": [],
    "b": "c"
}

You can pass arguments to custom metaclass from the class definition. The class notation support keyword arguments: class Klass(Parent, arg='arg'). The metaclass keyword is reserved for setting metaclass, but others are free to use. Here is an example of metaclass that creates class without one of the attributes. The name of that attribute is provided in the remove argument:
class FilterMeta(type):
   def __new__(mcs, name, bases, namespace, remove=None, **kwargs):
       if remove is not None and remove in namespace:
           del namespace[remove]

       return super().__new__(mcs, name, bases, namespace)


class A(metaclass=FilterMeta, remove='half'):
   def half(x):
       return x // 2

   half_of_4 = half(4)
   half_of_100 = half(100)


a = A()
print(a.half_of_4)  # 2
print(a.half_of_100)  # 50
a.half  # AttributeError

Write a function that joins any number of iterables that yield (k, v) into one that yields (k, [v1...vn]). The keys of the result have to be the same as the keys of the first iterable. Example:
assert [
    (1, ('a', 'x', '1')),
    (3, ('b', 'y', '3')),
    (5, ('c', 'z', '5')),
] == list(join(
    [(1, 'a'), (3, 'b'), (5, 'c')],
    [(5, 'z'), (3, 'y'), (1, 'x')],
    ((x, str(x)) for x in itertools.count())
))