电报频道_我的电报频道@pythonetc的提示和技巧,2019年9月
程序员文章站
2022-03-09 22:49:03
...
电报频道
It is a new selection of tips and tricks about Python and programming from my ********-channel @pythonetc.
这是我的********频道@pythonetc中有关Python和编程的一些新技巧和窍门。
←
← Previous publications以前的出版物
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
块,并且不会退出某些上下文管理器。
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
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
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
Imagine you have a pair of classes that are a parent and a child, say
假设您有一对父级和子级的类,例如
User
and User
和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.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 。
电报频道
下一篇: 2019年终自我总结