Python 简明教程
Python - Weak References
在实现垃圾收集策略的时候,Python 使用引用计数机制。当在内存中引用一个对象时,计数会增加 1。相反,当移除该引用时,计数会减少 1。如果在后台运行的垃圾收集器找到一个计数为 0 的对象,它将会被移除,且它占用的内存将会被回收。
Python uses reference counting mechanism while implementing garbage collection policy. Whenever an object in the memory is referred, the count is incremented by one. On the other hand, when the reference is removed, the count is decremented by 1. If the garbage collector running in the background finds any object with count as 0, it is removed and the memory occupied is reclaimed.
弱引用是一个不保护对象不受垃圾回收影响的引用。当你需要实现大型对象的缓存时,它非常重要,并且在你希望减少循环引用的痛苦的情况下也是如此。
Weak reference is a reference that does not protect the object from getting garbage collected. It proves important when you need to implement caches for large objects, as well as in a situation where reduction of Pain from circular references is desired.
为了创建弱引用,Python 为我们提供了名为 weakref 的模块。
To create weak references, Python has provided us with a module named weakref.
这个模块中的 ref 类管理到一个对象的弱引用。当被调用时,它检索原始对象。
The ref class in this module manages the weak reference to an object. When called, it retrieves the original object.
创建弱引用的方法:
To create a weak reference −
weakref.ref(class())
Example
import weakref
class Myclass:
def __del__(self):
print('(Deleting {})'.format(self))
obj = Myclass()
r = weakref.ref(obj)
print('object:', obj)
print('reference:', r)
print('call r():', r())
print('deleting obj')
del obj
print('r():', r())
在删除引用之后调用引用对象将返回 None。
Calling the reference object after deleting the referent returns None.
它将生成以下 output −
It will produce the following output −
object: <__main__.Myclass object at 0x00000209D7173290>
reference: <weakref at 0x00000209D7175940; to 'Myclass' at
0x00000209D7173290>
call r(): <__main__.Myclass object at 0x00000209D7173290>
deleting obj
(Deleting <__main__.Myclass object at 0x00000209D7173290>)
r(): None
The callback Function
ref 类的构造函数有一个可选的参数称为回调函数,它在引用的对象被删除时被调用。
The constructor of ref class has an optional parameter called callback function, which gets called when the referred object is deleted.
import weakref
class Myclass:
def __del__(self):
print('(Deleting {})'.format(self))
def mycallback(rfr):
"""called when referenced object is deleted"""
print('calling ({})'.format(rfr))
obj = Myclass()
r = weakref.ref(obj, mycallback)
print('object:', obj)
print('reference:', r)
print('call r():', r())
print('deleting obj')
del obj
print('r():', r())
它将生成以下 output −
It will produce the following output −
object: <__main__.Myclass object at 0x000002A0499D3590>
reference: <weakref at 0x000002A0499D59E0; to 'Myclass' at
0x000002A0499D3590>
call r(): <__main__.Myclass object at 0x000002A0499D3590>
deleting obj
(Deleting <__main__.Myclass object at 0x000002A0499D3590>)
calling (<weakref at 0x000002A0499D59E0; dead>)
r(): None
Finalizing Objects
weakref 模块提供了 finalize 类。当垃圾收集器收集对象的时候,调用它的对象。对象在引用对象被调用之前存在。
The weakref module provides finalize class. Its object is called when the garbage collector collects the object. The object survives until the reference object is called.
import weakref
class Myclass:
def __del__(self):
print('(Deleting {})'.format(self))
def finalizer(*args):
print('Finalizer{!r})'.format(args))
obj = Myclass()
r = weakref.finalize(obj, finalizer, "Call to finalizer")
print('object:', obj)
print('reference:', r)
print('call r():', r())
print('deleting obj')
del obj
print('r():', r())
它将生成以下 output −
It will produce the following output −
object: <__main__.Myclass object at 0x0000021015103590>
reference: <finalize object at 0x21014eabe80; for 'Myclass' at
0x21015103590>
Finalizer('Call to finalizer',))
call r(): None
deleting obj
(Deleting <__main__.Myclass object at 0x0000021015103590>)
r(): None
Weakref 模块提供 WeakKeyDictionary 和 WeakValueDictionary 类。它们不会让对象在映射对象中看似存活。它们更适用于创建多个对象的缓存。
The weakref module provides WeakKeyDictionary and WeakValueDictionary classes. They don’t keep the objects alive as they appear in the mapping objects. They are more appropriate for creating a cache of several objects.
WeakKeyDictionary
引用键的弱映射类。当键不再有强引用时,字典中的条目将被丢弃。
Mapping class that references keys weakly. Entries in the dictionary will be discarded when there is no longer a strong reference to the key.
WeakKeyDictionary 类的实例使用现有字典创建,也可以不使用任何参数创建它的功能与普通字典相同,可以向其中添加和删除映射条目。
An instance of WeakKeyDictionary class is created with an existing dictionary or without any argumentThe functionality is the same as a normal dictionary to add and remove mapping entries to it.
在下面给出的代码中,创建了三个 Person 实例。然后使用字典创建 WeakKeyDictionary 实例,其中键是 Person 实例,而值是 Person 的名称。
In the code given below three Person instances are created. It then creates an instance of WeakKeyDictionary with a dictionary where the key is the Person instance and the value is the Person’s name.
我们调用 keyrefs() 方法来检索弱引用。当对 Person1 的引用被删除时,字典键将再次被打印。将新 Person 实例添加到具有弱引用键的字典中。最后,我们再次打印字典的键。
We call the keyrefs() method to retrieve weak references. When the reference to Peron1 is deleted, dictionary keys are printed again. A new Person instance is added to a dictionary with weakly referenced keys. At last, we are printing keys of dictionary again.
Example
import weakref
class Person:
def __init__(self, person_id, name, age):
self.emp_id = person_id
self.name = name
self.age = age
def __repr__(self):
return "{} : {} : {}".format(self.person_id, self.name, self.age)
Person1 = Person(101, "Jeevan", 30)
Person2 = Person(102, "Ramanna", 35)
Person3 = Person(103, "Simran", 28)
weak_dict = weakref.WeakKeyDictionary({Person1: Person1.name, Person2: Person2.name, Person3: Person3.name})
print("Weak Key Dictionary : {}\n".format(weak_dict.data))
print("Dictionary Keys : {}\n".format([key().name for key in weak_dict.keyrefs()]))
del Person1
print("Dictionary Keys : {}\n".format([key().name for key in weak_dict.keyrefs()]))
Person4 = Person(104, "Partho", 32)
weak_dict.update({Person4: Person4.name})
print("Dictionary Keys : {}\n".format([key().name for key in weak_dict.keyrefs()]))
它将生成以下 output −
It will produce the following output −
Weak Key Dictionary : {<weakref at 0x7f542b6d4180; to 'Person' at 0x7f542b8bbfd0>: 'Jeevan', <weakref at 0x7f542b6d5530; to 'Person' at 0x7f542b8bbeb0>: 'Ramanna', <weakref at 0x7f542b6d55d0; to 'Person' at 0x7f542b8bb7c0>: 'Simran'}
Dictionary Keys : ['Jeevan', 'Ramanna', 'Simran']
Dictionary Keys : ['Ramanna', 'Simran']
Dictionary Keys : ['Ramanna', 'Simran', 'Partho']
WeakValueDictionary
引用值的弱映射类。当不再有对值的强引用时,字典中的条目将被丢弃。
Mapping class that references values weakly. Entries in the dictionary will be discarded when no strong reference to the value exists any more.
我们将演示如何使用 WeakValueDictionary 创建具有弱引用值的字典。
We shall demonstrate how to create a dictionary with weakly referenced values using WeakValueDictionary.
代码与前一个示例类似,但这次我们使用 Person 名称作为键,使用 Person 实例作为值。我们使用 valuerefs() 方法来检索字典的弱引用值。
The code is similar to previous example but this time we are using Person name as key and Person instance as values. We are using valuerefs() method to retrieve weakly referenced values of the dictionary.
Example
import weakref
class Person:
def __init__(self, person_id, name, age):
self.emp_id = person_id
self.name = name
self.age = age
def __repr__(self):
return "{} : {} : {}".format(self.person_id, self.name, self.age)
Person1 = Person(101, "Jeevan", 30)
Person2 = Person(102, "Ramanna", 35)
Person3 = Person(103, "Simran", 28)
weak_dict = weakref.WeakValueDictionary({Person1.name:Person1, Person2.name:Person2, Person3.name:Person3})
print("Weak Value Dictionary : {}\n".format(weak_dict.data))
print("Dictionary Values : {}\n".format([value().name for value in weak_dict.valuerefs()]))
del Person1
print("Dictionary Values : {}\n".format([value().name for value in weak_dict.valuerefs()]))
Person4 = Person(104, "Partho", 32)
weak_dict.update({Person4.name: Person4})
print("Dictionary Values : {}\n".format([value().name for value in weak_dict.valuerefs()]))
它将生成以下 output −
It will produce the following output −
Weak Value Dictionary : {'Jeevan': <weakref at 0x7f3af9fe4180; to 'Person' at 0x7f3afa1c7fd0>, 'Ramanna': <weakref at 0x7f3af9fe5530; to 'Person' at 0x7f3afa1c7eb0>, 'Simran': <weakref at 0x7f3af9fe55d0; to 'Person' at 0x7f3afa1c77c0>}
Dictionary Values : ['Jeevan', 'Ramanna', 'Simran']
Dictionary Values : ['Ramanna', 'Simran']
Dictionary Values : ['Ramanna', 'Simran', 'Partho']