
这是我的Telegram频道@pythonetc中有关Python和编程的一些新技巧和窍门。
←
以前的出版物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')
输出:
* * || * x
您必须确保在停止循环之前等待所有任务。 如果您不这样做,则可能会跳过某些
finally
块,而不会退出某些上下文管理器。
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))
您可以将参数从类定义传递给自定义元类。
class
符号支持关键字参数:
class Klass(Parent, arg='arg')
。
metaclass
关键字保留用于设置元类,但其他关键字则可以免费使用。
这是一个创建没有属性之一的类的元类示例。 该属性的名称在
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)
有时您想用尽一个生成器,但是您并不关心生成的值。 不过,您确实会担心一些副作用,这可能是例外,例如写入文件,修改全局变量等。
方便且广泛使用的方法是
list(gen())
。 但是,此代码将所有值保存到内存中,只是在之后立即丢弃它们。 这可能是不希望的。
如果要避免这种情况,可以改用有限大小的
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
假设您有一对父级和子级的类,例如
User
和
Admin
。 您还具有一个将用户列表作为参数的函数。 您能提供一份管理员清单吗? 答案是否定的:该函数可以将另一个用户添加到无效的管理员列表中,并破坏该列表提供的保证。
但是,由于
Sequence
是只读的,因此您可以提供管理员
Sequence
。 这里的适当术语是
Sequence
在其成员类型上是协变的。
您可以通过提供
covariant=True
作为
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)
相反,该功能可能只需要容器即可将管理员放在那里。 这样的只写容器在其成员类型上是
相反的 :
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)
既不是协变也不是协变的类称为
invariant 。