DMa*_*ack 7 python flyweight-pattern python-2.7
我正在研究一个问题,我正在实例化一个对象的许多实例.大多数情况下,实例化的对象是相同的.为了减少内存开销,我想让所有相同的对象指向同一个地址.但是,当我修改对象时,我想要创建一个新实例 - 基本上是写时复制行为.在Python中实现这一目标的最佳方法是什么?
Flyweight模式很接近.一个例子(来自http://codesnipers.com/?q=python-flyweights):
import weakref
class Card(object):
_CardPool = weakref.WeakValueDictionary()
def __new__(cls, value, suit):
obj = Card._CardPool.get(value + suit, None)
if not obj:
obj = object.__new__(cls)
Card._CardPool[value + suit] = obj
obj.value, obj.suit = value, suit
return obj
Run Code Online (Sandbox Code Playgroud)
其行为如下:
>>> c1 = Card('10', 'd')
>>> c2 = Card('10', 'd')
>>> id(c1) == id(c2)
True
>>> c2.suit = 's'
>>> c1.suit
's'
>>> id(c1) == id(c2)
True
Run Code Online (Sandbox Code Playgroud)
期望的行为是:
>>> c1 = Card('10', 'd')
>>> c2 = Card('10', 'd')
>>> id(c1) == id(c2)
True
>>> c2.suit = 's'
>>> c1.suit
'd'
>>> id(c1) == id(c2)
False
Run Code Online (Sandbox Code Playgroud)
更新:我遇到了Flyweight模式,它似乎几乎适合该法案.但是,我对其他方法持开放态度.
你需要id(c1)==id(c2)相同,还是只是一个演示,真正的目标是避免创建重复的对象?
一种方法是让每个对象都是不同的,但是像上面一样保持对"真实"对象的内部引用.然后,在任何__setattr__呼叫中,更改内部参考.
我以前从未做过__setattr__东西,但我认为它看起来像这样:
class MyObj:
def __init__(self, value, suit):
self._internal = Card(value, suit)
def __setattr__(self, name, new_value):
if name == 'suit':
self._internal = Card(value, new_value)
else:
self._internal = Card(new_value, suit)
Run Code Online (Sandbox Code Playgroud)
同样,通过公开属性getattr.
你仍然有很多重复的对象,但只有一个"真正的"支持对象的副本.因此,如果每个对象都很庞大,这将有所帮助,如果它们是轻量级的,那将无济于事,但是你有数百万个.
| 归档时间: |
|
| 查看次数: |
4143 次 |
| 最近记录: |