欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

电报频道_我的电报频道@pythonetc的提示和技巧,2019年9月

程序员文章站 2022-03-09 22:49:03
...

电报频道

电报频道_我的电报频道@pythonetc的提示和技巧,2019年9月

It is a new selection of tips and tricks about Python and programming from my ********-channel @pythonetc.
这是我的********频道@pythonetc中有关Python和编程的一些新技巧和窍门。

Previous publications以前的出版物
电报频道_我的电报频道@pythonetc的提示和技巧,2019年9月
asyncio loop doesn’t have to be run to have tasks. You can create and stop tasks even though the loop is stopped right now. If loop is stopped, some tasks may stay incompleted for good.asyncio循环不必运行就可以执行任务。 即使循环现在已停止,您也可以创建和停止任务。 如果停止循环,则某些任务可能永远无法完成。
import asyncio


async def printer():
    try:
        try:
            while True:
                print('*')
                await asyncio.sleep(1)
        except asyncio.CancelledError:
            print('x')
    finally:
        await asyncio.sleep(2)
        print('o')  # never happens


loop = asyncio.get_event_loop()
run = loop.run_until_complete
task = loop.create_task(printer())

run(asyncio.sleep(1))  # printer works here
print('||')

run(asyncio.sleep(1))  # printer works here
task.cancel()  # nothing happens
run(asyncio.sleep(1))  # x printed

Output:
输出:
*
*
||
*
x

You have to be sure to await all tasks before stopping the loop. In case you don’t you may have some
您必须确保在停止循环之前等待所有任务。 如果您不这样做,则可能会跳过某些finally blocks being skipped and some context managers not being exited.finally块,并且不会退出某些上下文管理器。
电报频道_我的电报频道@pythonetc的提示和技巧,2019年9月

Python lets you overload many different operators and the shift operator is one of them. Here is an example of how to create a function composition using this operator. Here, arrow-like signs show the data-flow direction:
Python使您可以重载许多不同的运算符,而shift运算符就是其中之一。 这是如何使用此运算符创建函数组合的示例。 在这里,箭头状的符号表示数据流的方向:
from collections import deque
from math import sqrt


class Compose:
    def __init__(self):
        self._functions = deque()

    def __call__(self, *args, **kwargs):
        result = None
        for f in self._functions:
            result = f(*args, **kwargs)
            args = [result]
            kwargs = dict()
        return result

    def __rshift__(self, f):
        self._functions.append(f)
        return self

    def __lshift__(self, f):
        self._functions.appendleft(f)
        return self


compose = Compose


sqrt_abs = (compose() << sqrt << abs)
sqrt_abs2 = (compose() >> abs >> sqrt)

print(sqrt_abs(-4))  # 2.0
print(sqrt_abs2(-4))  # 2.0
电报频道_我的电报频道@pythonetc的提示和技巧,2019年9月

You can pass arguments to custom metaclass from the class definition. The
您可以将参数从类定义传递给自定义元类。 class notation support keyword arguments: class表示法支持关键字参数: class Klass(Parent, arg='arg'). The class Klass(Parent, arg='arg')metaclass keyword is reserved for setting metaclass, but others are free to use.metaclass关键字保留用于设置元类,但其他关键字则可以免费使用。
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:remove参数中提供:
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
电报频道_我的电报频道@pythonetc的提示和技巧,2019年9月

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.list(gen()) 。 但是,此代码将所有值保存到内存中,只是在之后立即丢弃它们。 这可能是不希望的。
If you want to avoid this you can use
如果要避免这种情况,可以改用有限大小的deque with the limited size instead:deque
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')</code>
To be more semantically precise you better define your own <code>exhaust</code> function:

<source lang="python">
def exhaust(iterable):
    for _ in iterable:
        pass
电报频道_我的电报频道@pythonetc的提示和技巧,2019年9月

Imagine you have a pair of classes that are a parent and a child, say
假设您有一对父级和子级的类,例如User and UserAdmin. 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.Admin 。 您还具有一个将用户列表作为参数的函数。 您能提供一份管理员名单吗? 答案是否定的:该函数可以将另一个用户添加到无效的管理员列表中,并破坏该列表提供的保证。
However, you can provide a
但是,由于“ Sequence of admins since Sequence是只读的,因此您可以提供“ Sequence is read-only. The proper term here is Sequence管理员”。 这里的恰当术语是Sequence is covariant on its members type.Sequence在其成员类型上是协变的。
You can define covariant types by providing
您可以通过提供covariant=True as a covariant=True作为TypeVar argument:TypeVar参数来定义协变类型:
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.invariant

翻译自: https://habr.com/en/company/mailru/blog/470107/

电报频道