
我的@pythonetc feed中提供了一系列新的Python技巧和编程。
←
以前的收藏在
asyncio
不必启动包含任务的循环。 即使循环已停止,您也可以创建和停止任务。 如果停止,则某些任务可能仍未完成。
import asyncio async def printer(): try: try: while True: print('*') await asyncio.sleep(1) except asyncio.CancelledError: print('') finally: await asyncio.sleep(2) print('')
结果:
* * || *
确保在停止周期之前等待所有任务完成。 如果不这样做,则可以跳过某些
finally
块,并且不会禁用某些上下文管理器。
Python允许您重写许多运算符,包括按位移位运算符。 这是使用此运算符创建功能组合的示例。 箭头指示数据传输的方向:
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')
为了语义上的准确性,您可以定义自己的
exhaust
功能:
def exhaust(iterable): for _ in iterable: pass
假设您有几个类-父子类
User
和
Admin
。 而且,您还有一个将用户列表作为参数的函数。 您可以提供管理员列表吗? 否:该功能可以将另一个用户添加到管理员列表中,这是错误的,并且违反了列表提供的保证。
但是,您可以提供一个
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 。