这比任何事情都更具好奇心,但我注意到以下内容.如果我定义一个自引用的lambda,我可以轻松地做到:
>>> f = lambda: f
>>> f() is f
True
Run Code Online (Sandbox Code Playgroud)
但是,如果我要定义一个自引用列表,我必须在多个语句中执行:
>>> a = [a]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined
>>> a = []
>>> a.append(a)
>>> a[0] is a
True
>>> a
[[...]]
Run Code Online (Sandbox Code Playgroud)
我也注意到这不仅限于列表,但似乎除了lambda之外的任何其他表达式都不能引用赋值左边的变量.例如,如果您有一个带有一个节点的循环链表,那么您不能简单地去:
>>> class Node(object):
... def __init__(self, next_node):
... self.next = next_node
...
>>> n = Node(n)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'n' is not …
Run Code Online (Sandbox Code Playgroud) 假设您正在使用multiprocessing.Pool
对象,并且您正在使用initializer
构造函数的设置来传递初始化函数,然后在全局命名空间中创建资源.假设资源有一个上下文管理器.您将如何处理上下文管理资源的生命周期,前提是它必须贯穿整个过程的生命周期,但最终应该进行适当的清理?
到目前为止,我有点像这样:
resource_cm = None
resource = None
def _worker_init(args):
global resource
resource_cm = open_resource(args)
resource = resource_cm.__enter__()
Run Code Online (Sandbox Code Playgroud)
从此处开始,池进程可以使用该资源.到现在为止还挺好.但处理清理有点棘手,因为multiprocessing.Pool
类没有提供destructor
或deinitializer
参数.
我的一个想法是使用该atexit
模块,并在初始化程序中注册清理.像这样的东西:
def _worker_init(args):
global resource
resource_cm = open_resource(args)
resource = resource_cm.__enter__()
def _clean_up():
resource_cm.__exit__()
import atexit
atexit.register(_clean_up)
Run Code Online (Sandbox Code Playgroud)
这是一个好方法吗?有更简单的方法吗?
编辑:atexit
似乎没有工作.至少不是我上面使用它的方式,所以到目前为止我还没有解决这个问题的方法.
如何在Python中处理在另一个上下文管理器中创建的上下文管理器?
示例:假设您具有A
充当上下文管理器的类B
,以及充当上下文管理器的类.但是类B
实例必须实例化并使用类的实例A
.我已经通过了PEP 343,这是我想到的解决方案:
class A(object):
def __enter__(self):
# Acquire some resources here
return self
def __exit__(seplf, exception_type, exception, traceback):
# Release the resources and clean up
pass
class B(object):
def __init__(self):
self.a = A()
def __enter__(self):
# Acquire some resources, but also need to "start" our instance of A
self.a.__enter__()
return self
def __exit__(self, exception_type, exception, traceback):
# Release the resources, and make our instance of A clean up as well
self.a.__exit__(exception_type, …
Run Code Online (Sandbox Code Playgroud) 有没有办法在生成器的定义中获取对返回的生成器对象的引用?这类似于self
传递给__next__
迭代器方法内部方法的参数.浏览Python的文档后,我没有找到类似的东西.
这个问题出现的时候,我正在探索以下论文的大部分内容,我可以使用生成器作为协同程序在Python中实现.论文:http://citeseerx.ist.psu.edu/viewdoc/summary?doi = 10.1.1.19.79
我能做的最接近的是使用装饰器,它建立在David Beazley的coroutine
装饰上,但感觉有点像黑客.
from functools import wraps
def coroutine(func):
@wraps(func)
def decorated(*args, **kwargs):
f = func(*args, **kwargs)
next(f)
f.send(f)
return f
return decorated
@coroutine
def A():
self = yield
# do stuff...
Run Code Online (Sandbox Code Playgroud)
编辑:基于下面的答案,下面的类可以用作装饰器,让生成器接收self
作为其第一个参数的引用.它具有额外的好处,任何用它装饰的发电机都具有这种类型coroutine
.
class coroutine(object):
"""Decorator class for coroutines with a self parameter."""
def __new__(cls, func):
@wraps(func)
def decorated(*args, **kwargs):
o = object.__new__(cls)
o.__init__(func, args, kwargs)
return o
return decorated
def __init__(self, generator, args, …
Run Code Online (Sandbox Code Playgroud) 我刚刚在node.js控制台中尝试了以下内容:
> 5 <= "5"
true
Run Code Online (Sandbox Code Playgroud)
这意味着被处理的=
部分<=
是相同==
的,而不是===
.这使我立即尝试<==
希望它会做你希望它会做的事情.但它不存在.
然后我尝试了以下内容:
> 5 < "6"
true
Run Code Online (Sandbox Code Playgroud)
然后我开始观察甚至更奇怪的行为:
> 5 < [6]
true
Run Code Online (Sandbox Code Playgroud)
这带来了一个更重要的问题:有没有类型安全的等价物<
,>
,<=
,和>=
?
给定一个生成器对象,是否可以测试它是否是由给定的生成器创建的?也许更好的说法,是否有可能测试我们的发电机的"类型"?由于生成器对象具有类型generator
,因此使用type
或isinstance
不执行测试.
请考虑以下代码:
>>> def gen1():
... yield 1
...
>>> def gen2():
... yield 2
...
>>> g1 = gen1()
>>> g2 = gen2()
>>>
>>> def do_something(f):
... # need to know if f is a gen1 generator or a gen2 generator here
... # isinstance(f, gen1) raises a TypeError since gen1 is not a type
... # type(f) is gen1 returns false
... print(f)
...
>>> do_something(g1)
<generator object gen1 at 0x100dcb370> …
Run Code Online (Sandbox Code Playgroud) 问题的简短版本:为什么生成器实例的类型不是创建实例的生成器函数?也就是说,如果我们有一个生成器,说是def G(): yield 1
并且g
是由G
它创建的生成器实例g = G()
,那么为什么是type(g) is G
假的?
细节:
我最近问了一个关于如何确定给定生成器对象的生成器类型的问题.(参见在Python中,有没有办法测试生成器对象以找出哪个生成器创建它?.)答案最终需要使用__name__
.但是,这仍然给我一个未解答的问题:为什么生成器不是Python中的类型?
下面的所有代码都考虑到了Python 3.3,但我相信大部分代码都适用于旧版本的Python(至少2.7版本)和更新版本,即3.4版本.
让我们看一个非常简单的迭代器示例,该迭代器首先作为类实现:
class C(object):
def __iter__(self):
return self
def __next__(self):
return 1
c = C()
print(next(c)) # 1
print(type(c)) # <class '__main__.C'>
print(type(c) is C) # True
Run Code Online (Sandbox Code Playgroud)
在功能上,上面的类与下面给出的生成器相同.(当然,我们失踪了throw
,send
而且close
,还有其他微妙的差异,但我认为它们与手头的问题无关.)
def G():
while True:
yield 1
g = G()
print(next(g)) # 1
print(type(g)) # <class 'generator'>
print(type(g) is G) # False …
Run Code Online (Sandbox Code Playgroud)