weakrefWeak references弱引用

Source code: Lib/weakref.py


The weakref module allows the Python programmer to create weak references to objects.weakref模块允许Python程序员创建对对象的弱引用

In the following, the term referent means the object which is referred to by a weak reference.在下文中,术语referent是指由弱引用引用的对象。

A weak reference to an object is not enough to keep the object alive: when the only remaining references to a referent are weak references, garbage collection is free to destroy the referent and reuse its memory for something else. 对对象的弱引用不足以使对象保持活动状态:当对引用的唯一剩余引用是弱引用时,垃圾收集可以随意销毁引用并将其内存重新用于其他用途。However, until the object is actually destroyed the weak reference may return the object even if there are no strong references to it.然而,在对象实际被破坏之前,弱引用可能会返回该对象,即使没有对其进行强引用。

A primary use for weak references is to implement caches or mappings holding large objects, where it’s desired that a large object not be kept alive solely because it appears in a cache or mapping.弱引用的主要用途是实现包含大型对象的缓存或映射,在这种情况下,大型对象不能仅因为出现在缓存或映射中而保持活动状态。

For example, if you have a number of large binary image objects, you may wish to associate a name with each. 例如,如果您有许多大型二进制图像对象,则可能希望将每个对象关联一个名称。If you used a Python dictionary to map names to images, or images to names, the image objects would remain alive just because they appeared as values or keys in the dictionaries. 如果使用Python字典将名称映射到图像,或将图像映射到名称,则图像对象将保持活动状态,因为它们在字典中显示为值或键。The WeakKeyDictionary and WeakValueDictionary classes supplied by the weakref module are an alternative, using weak references to construct mappings that don’t keep objects alive solely because they appear in the mapping objects. weakref模块提供的WeakKeyDictionaryWeakValueDictionary类是一种替代方法,它们使用弱引用来构造映射,这些映射不会仅仅因为对象出现在映射对象中而保持对象的活性。If, for example, an image object is a value in a WeakValueDictionary, then when the last remaining references to that image object are the weak references held by weak mappings, garbage collection can reclaim the object, and its corresponding entries in weak mappings are simply deleted.例如,如果图像对象是WeakValueDictionary中的一个值,那么当对该图像对象的最后剩余引用是弱映射所持有的弱引用时,垃圾收集可以回收该对象,并且其在弱映射中的对应项被简单删除。

WeakKeyDictionary and WeakValueDictionary use weak references in their implementation, setting up callback functions on the weak references that notify the weak dictionaries when a key or value has been reclaimed by garbage collection. WeakKeyDictionaryWeakValueDictionary在其实现中使用弱引用,在弱引用上设置回调函数,在垃圾收集回收键或值时通知弱字典。WeakSet implements the set interface, but keeps weak references to its elements, just like a WeakKeyDictionary does.WeakSet实现了set接口,但保留了对其元素的弱引用,就像WeakKeyDictionary一样。

finalize provides a straight forward way to register a cleanup function to be called when an object is garbage collected. 提供了一种直接注册清理函数的方法,以便在垃圾收集对象时调用该函数。This is simpler to use than setting up a callback function on a raw weak reference, since the module automatically ensures that the finalizer remains alive until the object is collected.这比在原始弱引用上设置回调函数更简单,因为模块自动确保终结器在收集对象之前保持活动状态。

Most programs should find that using one of these weak container types or finalize is all they need – it’s not usually necessary to create your own weak references directly. 大多数程序应该发现,使用这些弱容器类型之一或finalize就是他们所需要的——通常没有必要直接创建自己的弱引用。The low-level machinery is exposed by the weakref module for the benefit of advanced uses.低级机械由weakref模块暴露,以便于高级使用。

Not all objects can be weakly referenced; those objects which can include class instances, functions written in Python (but not in C), instance methods, sets, frozensets, some file objects, generators, type objects, sockets, arrays, deques, regular expression pattern objects, and code objects.并非所有对象都可以弱引用;这些对象可以包括类实例、用Python编写的函数(但不是用C编写的)、实例方法、集合、冻结集、一些文件对象、生成器、类型对象、套接字、数组、deques、正则表达式模式对象和代码对象。

Changed in version 3.2:版本3.2中更改: Added support for thread.lock, threading.Lock, and code objects.添加了对threadlock、threading.Lock和code对象的支持。

Several built-in types such as list and dict do not directly support weak references but can add support through subclassing:一些内置类型(如list和dict)不直接支持弱引用,但可以通过子类化添加支持:

class Dict(dict):
pass
obj = Dict(red=1, green=2, blue=3) # this object is weak referenceable

CPython implementation detail:CPython实施细节: Other built-in types such as tuple and int do not support weak references even when subclassed.其他内置类型(如tupleint)即使在子类化时也不支持弱引用。

Extension types can easily be made to support weak references; see Weak Reference Support.扩展类型可以很容易地支持弱引用;参见弱参考支持。

When __slots__ are defined for a given type, weak reference support is disabled unless a '__weakref__' string is also present in the sequence of strings in the __slots__ declaration. 当为给定类型定义__slots__时,弱引用支持被禁用,除非在__slots__声明中的字符串序列中也存在一个'__weakref__'字符串。See __slots__ documentation for details.有关详细信息,请参阅__slots__文档

classweakref.ref(object[, callback])

Return a weak reference to object. 返回对object的弱引用。The original object can be retrieved by calling the reference object if the referent is still alive; if the referent is no longer alive, calling the reference object will cause None to be returned. 如果引用对象仍然存在,则可以通过调用引用对象来检索原始对象;如果引用对象不再处于活动状态,则调用引用对象将导致不返回任何对象。If callback is provided and not None, and the returned weakref object is still alive, the callback will be called when the object is about to be finalized; the weak reference object will be passed as the only parameter to the callback; the referent will no longer be available.如果提供了callback而不是None,并且返回的weakref对象仍处于活动状态,则将在对象即将完成时调用回调;弱引用对象将作为唯一参数传递给回调;引用对象将不再可用。

It is allowable for many weak references to be constructed for the same object. 允许为同一对象构造多个弱引用。Callbacks registered for each weak reference will be called from the most recently registered callback to the oldest registered callback.为每个弱引用注册的回调将从最近注册的回调调用到最早注册的回调。

Exceptions raised by the callback will be noted on the standard error output, but cannot be propagated; they are handled in exactly the same way as exceptions raised from an object’s __del__() method.回调引发的异常将记录在标准错误输出上,但无法传播;它们的处理方式与从对象的__del__()方法引发的异常完全相同。

Weak references are hashable if the object is hashable. 如果object可散列的,则弱引用是可散列的。They will maintain their hash value even after the object was deleted. 即使删除了对象,它们也将保持其object值。If hash() is called the first time only after the object was deleted, the call will raise TypeError.如果仅在删除object后第一次调用hash(),则调用将引发TypeError

Weak references support tests for equality, but not ordering. 弱引用支持相等测试,但不支持排序。If the referents are still alive, two references have the same equality relationship as their referents (regardless of the callback). 如果引用仍然存在,则两个引用与其引用具有相同的相等关系(无论callback)。If either referent has been deleted, the references are equal only if the reference objects are the same object.如果删除了任一引用,则只有引用对象是同一对象时,引用才相等。

This is a subclassable type rather than a factory function.这是一个子类类型,而不是工厂函数。

__callback__

This read-only attribute returns the callback currently associated to the weakref. 该只读属性返回当前与weakref关联的回调。If there is no callback or if the referent of the weakref is no longer alive then this attribute will have value None.如果没有回调,或者weakref的referent不再活动,则该属性的值将为None

Changed in version 3.4:版本3.4中更改: Added the __callback__ attribute.添加了__callback__属性。

weakref.proxy(object[, callback])

Return a proxy to object which uses a weak reference. 将代理返回到使用弱引用的对象。This supports use of the proxy in most contexts instead of requiring the explicit dereferencing used with weak reference objects. 这支持在大多数上下文中使用代理,而不需要对弱引用对象使用显式解引用。The returned object will have a type of either ProxyType or CallableProxyType, depending on whether object is callable. 根据对象是否可调用,返回的对象将具有ProxyTypeCallableProxyType类型。Proxy objects are not hashable regardless of the referent; this avoids a number of problems related to their fundamentally mutable nature, and prevent their use as dictionary keys. 不管引用对象是什么,代理对象都是不可散列的;这避免了与它们的基本易变性相关的许多问题,并防止它们用作字典键。callback is the same as the parameter of the same name to the ref() function.callbackref()函数的同名参数相同。

Changed in version 3.8:版本3.8中更改: Extended the operator support on proxy objects to include the matrix multiplication operators @ and @=.扩展了对代理对象的运算符支持,以包括矩阵乘法运算符#64;@=

weakref.getweakrefcount(object)

Return the number of weak references and proxies which refer to object.返回引用object的弱引用和代理数。

weakref.getweakrefs(object)

Return a list of all weak reference and proxy objects which refer to object.返回引用object的所有弱引用和代理对象的列表。

classweakref.WeakKeyDictionary([dict])

Mapping class that references keys weakly. 弱引用键的映射类。Entries in the dictionary will be discarded when there is no longer a strong reference to the key. 当不再有对键的强引用时,字典中的条目将被丢弃。This can be used to associate additional data with an object owned by other parts of an application without adding attributes to those objects. 这可以用于将附加数据与应用程序其他部分拥有的对象相关联,而无需向这些对象添加属性。This can be especially useful with objects that override attribute accesses.这对于覆盖属性访问的对象特别有用。

Changed in version 3.9:版本3.9中更改: Added support for | and |= operators, specified in PEP 584.增加了对PEP 584中指定的||=运算符的支持。

WeakKeyDictionary objects have an additional method that exposes the internal references directly. 对象有一个直接公开内部引用的附加方法。The references are not guaranteed to be “live” at the time they are used, so the result of calling the references needs to be checked before being used. 引用在使用时不能保证是“活动的”,因此在使用之前需要检查调用引用的结果。This can be used to avoid creating references that will cause the garbage collector to keep the keys around longer than needed.这可以用来避免创建引用,从而导致垃圾收集器将密钥保留的时间超过需要的时间。

WeakKeyDictionary.keyrefs()

Return an iterable of the weak references to the keys.返回对键的弱引用的iterable。

classweakref.WeakValueDictionary([dict])

Mapping class that references values weakly. 弱引用值的映射类。Entries in the dictionary will be discarded when no strong reference to the value exists any more.当不再存在对值的强引用时,字典中的条目将被丢弃。

Changed in version 3.9:版本3.9中更改: Added support for | and |= operators, as specified in PEP 584.根据PEP 584的规定,增加了对||=运算符的支持。

WeakValueDictionary objects have an additional method that has the same issues as the keyrefs() method of WeakKeyDictionary objects.WeakValueDictionary对象有一个附加方法,该方法与WeakKeyDictionary对象的keyrefs()方法具有相同的问题。

WeakValueDictionary.valuerefs()

Return an iterable of the weak references to the values.返回对值的弱引用的可迭代对象。

classweakref.WeakSet([elements])

Set class that keeps weak references to its elements. 集合类,该类保持对其元素的弱引用。An element will be discarded when no strong reference to it exists any more.当不再存在对某个元素的强引用时,该元素将被丢弃。

classweakref.WeakMethod(method)

A custom ref subclass which simulates a weak reference to a bound method (i.e., a method defined on a class and looked up on an instance). 一个自定义ref子类,模拟对绑定方法(即,在类上定义并在实例上查找的方法)的弱引用。Since a bound method is ephemeral, a standard weak reference cannot keep hold of it. 由于边界方法是短暂的,标准弱参考无法保持它。WeakMethod has special code to recreate the bound method until either the object or the original function dies:WeakMethod有特殊代码来重新创建绑定方法,直到对象或原始函数死亡:

>>> class C:
... def method(self):
... print("method called!")
...
>>> c = C()
>>> r = weakref.ref(c.method)
>>> r()
>>> r = weakref.WeakMethod(c.method)
>>> r()
<bound method C.method of <__main__.C object at 0x7fc859830220>>
>>> r()()
method called!
>>> del c
>>> gc.collect()
0
>>> r()
>>>

New in version 3.4.版本3.4中新增。

classweakref.finalize(obj, func, /, *args, **kwargs)

Return a callable finalizer object which will be called when obj is garbage collected. 返回一个可调用的终结器对象,当obj被垃圾收集时将调用该对象。Unlike an ordinary weak reference, a finalizer will always survive until the reference object is collected, greatly simplifying lifecycle management.与普通弱引用不同,终结器在收集引用对象之前始终有效,这大大简化了生命周期管理。

A finalizer is considered alive until it is called (either explicitly or at garbage collection), and after that it is dead. 终结器在被调用(显式调用或在垃圾收集时调用)之前被认为是alive,然后它就deadCalling a live finalizer returns the result of evaluating func(*arg, **kwargs), whereas calling a dead finalizer returns None.调用活动终结器返回计算func(*arg, **kwargs)的结果,而调用非活动终结器则返回None

Exceptions raised by finalizer callbacks during garbage collection will be shown on the standard error output, but cannot be propagated. 垃圾收集期间终结器回调引发的异常将显示在标准错误输出上,但无法传播。They are handled in the same way as exceptions raised from an object’s __del__() method or a weak reference’s callback.它们的处理方式与从对象的__del__()方法或弱引用的回调引发的异常相同。

When the program exits, each remaining live finalizer is called unless its atexit attribute has been set to false. 当程序退出时,除非其atexit属性设置为false,否则将调用剩余的每个活动终结器。They are called in reverse order of creation.它们按与创造相反的顺序被调用。

A finalizer will never invoke its callback during the later part of the interpreter shutdown when module globals are liable to have been replaced by None.解释器关闭的后期,当模块全局变量可能被None替换时,终结器将永远不会调用其回调。

__call__()

If self is alive then mark it as dead and return the result of calling func(*args, **kwargs). 如果self处于活动状态,则将其标记为dead,并返回调用func(*args, **kwargs)的结果。If self is dead then return None.如果self已死亡,则返回None

detach()

If self is alive then mark it as dead and return the tuple (obj, func, args, kwargs). 如果self是活动的,那么将其标记为dead并返回元组(obj, func, args, kwargs)If self is dead then return None.如果self已死亡,则返回None

peek()

If self is alive then return the tuple (obj, func, args, kwargs). 如果self处于活动状态,则返回元组(obj, func, args, kwargs)If self is dead then return None.如果self已死亡,则返回None

alive

Property which is true if the finalizer is alive, false otherwise.属性,如果终结器处于活动状态,则为true,否则为false

atexit

A writable boolean property which by default is true. 默认情况下为true的可写布尔属性。When the program exits, it calls all remaining live finalizers for which atexit is true. 当程序退出时,它调用atexittrue的所有剩余实时终结器。They are called in reverse order of creation.它们按与创造相反的顺序被调用。

Note

It is important to ensure that func, args and kwargs do not own any references to obj, either directly or indirectly, since otherwise obj will never be garbage collected. 重要的是确保funcargskwargs不直接或间接拥有对obj的任何引用,否则obj将永远不会被垃圾收集。In particular, func should not be a bound method of obj.特别是,func不应该是obj的边界方法。

New in version 3.4.版本3.4中新增。

weakref.ReferenceType

The type object for weak references objects.弱引用对象的类型对象。

weakref.ProxyType

The type object for proxies of objects which are not callable.不可调用的对象的代理的类型对象。

weakref.CallableProxyType

The type object for proxies of callable objects.可调用对象的代理的类型对象。

weakref.ProxyTypes

Sequence containing all the type objects for proxies. 包含代理的所有类型对象的序列。This can make it simpler to test if an object is a proxy without being dependent on naming both proxy types.这可以简化测试对象是否为代理,而不依赖于命名这两种代理类型。

See also另请参见

PEP 205 - Weak References弱引用

The proposal and rationale for this feature, including links to earlier implementations and information about similar features in other languages.此功能的建议和基本原理,包括指向早期实现的链接以及其他语言中类似功能的信息。

Weak Reference Objects弱参考对象

Weak reference objects have no methods and no attributes besides ref.__callback__. 弱引用对象除了ref.__callback__之外,没有方法和属性。A weak reference object allows the referent to be obtained, if it still exists, by calling it:弱引用对象允许通过调用来获取引用对象(如果它仍然存在):

>>> import weakref
>>> class Object:
... pass
...
>>> o = Object()
>>> r = weakref.ref(o)
>>> o2 = r()
>>> o is o2
True

If the referent no longer exists, calling the reference object returns None:如果引用对象不再存在,则调用引用对象将返回None

>>> del o, o2
>>> print(r())
None

Testing that a weak reference object is still live should be done using the expression ref() is not None. 应该使用表达式ref() is not None来测试弱引用对象是否仍然处于活动状态。Normally, application code that needs to use a reference object should follow this pattern:通常,需要使用引用对象的应用程序代码应遵循以下模式:

# r is a weak reference object
o = r()
if o is None:
# referent has been garbage collected
print("Object has been deallocated; can't frobnicate.")
else:
print("Object is still live!")
o.do_something_useful()

Using a separate test for “liveness” creates race conditions in threaded applications; another thread can cause a weak reference to become invalidated before the weak reference is called; the idiom shown above is safe in threaded applications as well as single-threaded applications.使用单独的“活性”测试在线程化应用程序中创建竞争条件;另一个线程可以导致弱引用在调用该弱引用之前失效;上面显示的习惯用法在线程应用程序和单线程应用程序中都是安全的。

Specialized versions of ref objects can be created through subclassing. 可以通过子类化创建ref对象的专用版本。This is used in the implementation of the WeakValueDictionary to reduce the memory overhead for each entry in the mapping. 这用于WeakValueDictionary的实现,以减少映射中每个条目的内存开销。This may be most useful to associate additional information with a reference, but could also be used to insert additional processing on calls to retrieve the referent.这在将附加信息与引用关联时可能最有用,但也可用于在检索引用的调用中插入附加处理。

This example shows how a subclass of ref can be used to store additional information about an object and affect the value that’s returned when the referent is accessed:此示例显示了如何使用ref的子类来存储有关对象的附加信息,并影响访问引用时返回的值:

import weakref
class ExtendedRef(weakref.ref):
def __init__(self, ob, callback=None, /, **annotations):
super().__init__(ob, callback)
self.__counter = 0
for k, v in annotations.items():
setattr(self, k, v)

def __call__(self):
"""Return a pair containing the referent and the number of
times the reference has been called.
"""
ob = super().__call__()
if ob is not None:
self.__counter += 1
ob = (ob, self.__counter)
return ob

Example实例

This simple example shows how an application can use object IDs to retrieve objects that it has seen before. 这个简单的示例展示了应用程序如何使用对象ID检索它以前看到的对象。The IDs of the objects can then be used in other data structures without forcing the objects to remain alive, but the objects can still be retrieved by ID if they do.然后,可以在其他数据结构中使用对象的ID,而不强制对象保持活动状态,但如果对象保持活动状态,则仍然可以通过ID检索对象。

import weakref
_id2obj_dict = weakref.WeakValueDictionary()

def remember(obj):
oid = id(obj)
_id2obj_dict[oid] = obj
return oid

def id2obj(oid):
return _id2obj_dict[oid]

Finalizer Objects终结器对象

The main benefit of using finalize is that it makes it simple to register a callback without needing to preserve the returned finalizer object. 使用finalize的主要好处是,它使注册回调变得简单,而不需要保留返回的finalizer对象。For instance例如

>>> import weakref
>>> class Object:
... pass
...
>>> kenny = Object()
>>> weakref.finalize(kenny, print, "You killed Kenny!")
<finalize object at ...; for 'Object' at ...>
>>> del kenny
You killed Kenny!

The finalizer can be called directly as well. 也可以直接调用终结器。However the finalizer will invoke the callback at most once.但是,终结器最多调用一次回调。

>>> def callback(x, y, z):
... print("CALLBACK")
... return x + y + z
...
>>> obj = Object()
>>> f = weakref.finalize(obj, callback, 1, 2, z=3)
>>> assert f.alive
>>> assert f() == 6
CALLBACK
>>> assert not f.alive
>>> f() # callback not called because finalizer dead
>>> del obj # callback not called because finalizer dead

You can unregister a finalizer using its detach() method. 可以使用终结器的detach()方法注销终结器。This kills the finalizer and returns the arguments passed to the constructor when it was created.这会终止终结器,并在创建构造函数时返回传递给构造函数的参数。

>>> obj = Object()
>>> f = weakref.finalize(obj, callback, 1, 2, z=3)
>>> f.detach()
(<...Object object ...>, <function callback ...>, (1, 2), {'z': 3})
>>> newobj, func, args, kwargs = _
>>> assert not f.alive
>>> assert newobj is obj
>>> assert func(*args, **kwargs) == 6
CALLBACK

Unless you set the atexit attribute to False, a finalizer will be called when the program exits if it is still alive. 除非将atexit属性设置为False,否则当程序退出时,如果它仍处于活动状态,则将调用终结器。For instance例如

>>> obj = Object()
>>> weakref.finalize(obj, print, "obj dead or exiting")
<finalize object at ...; for 'Object' at ...>
>>> exit()
obj dead or exiting

Comparing finalizers with __del__() methods比较终结器与__del__()方法

Suppose we want to create a class whose instances represent temporary directories. 假设我们要创建一个类,其实例表示临时目录。The directories should be deleted with their contents when the first of the following events occurs:当发生以下第一个事件时,应删除目录及其内容:

  • the object is garbage collected,对象被垃圾收集,

  • the object’s remove() method is called, or调用对象的remove()方法,或

  • the program exits.程序退出。

We might try to implement the class using a __del__() method as follows:我们可以尝试使用__del__()方法实现该类:

class TempDir:
def __init__(self):
self.name = tempfile.mkdtemp()
def remove(self):
if self.name is not None:
shutil.rmtree(self.name)
self.name = None

@property
def removed(self):
return self.name is None

def __del__(self):
self.remove()

Starting with Python 3.4, __del__() methods no longer prevent reference cycles from being garbage collected, and module globals are no longer forced to None during interpreter shutdown. 从Python 3.4开始,_udel_u()方法不再阻止引用周期被垃圾收集,并且在解释器关闭期间不再强制模块全局变量为无。So this code should work without any issues on CPython.因此,这段代码在CPython上应该可以正常工作。

However, handling of __del__() methods is notoriously implementation specific, since it depends on internal details of the interpreter’s garbage collector implementation.然而,__del__()方法的处理是众所周知的特定于实现的,因为它取决于解释器垃圾收集器实现的内部细节。

A more robust alternative can be to define a finalizer which only references the specific functions and objects that it needs, rather than having access to the full state of the object:更可靠的替代方法是定义一个终结器,该终结器只引用它所需的特定函数和对象,而不是访问对象的完整状态:

class TempDir:
def __init__(self):
self.name = tempfile.mkdtemp()
self._finalizer = weakref.finalize(self, shutil.rmtree, self.name)
def remove(self):
self._finalizer()

@property
def removed(self):
return not self._finalizer.alive

Defined like this, our finalizer only receives a reference to the details it needs to clean up the directory appropriately. 这样定义,终结器只接收对适当清理目录所需的详细信息的引用。If the object never gets garbage collected the finalizer will still be called at exit.如果对象从未被垃圾回收,那么终结器仍将在退出时被调用。

The other advantage of weakref based finalizers is that they can be used to register finalizers for classes where the definition is controlled by a third party, such as running code when a module is unloaded:基于weakref的终结器的另一个优点是,它们可以用于为定义由第三方控制的类注册终结器,例如在卸载模块时运行代码:

import weakref, sys
def unloading_module():
# implicit reference to the module globals from the function body
weakref.finalize(sys.modules[__name__], unloading_module)

Note

If you create a finalizer object in a daemonic thread just as the program exits then there is the possibility that the finalizer does not get called at exit. 如果在程序退出时在守护线程中创建终结器对象,则终结器有可能在退出时未被调用。However, in a daemonic thread atexit.register(), try: ... finally: ... and with: ... do not guarantee that cleanup occurs either.但是,在守护线程atexit.register()中,try: ... finally: ...with: ...也不保证进行清理。