我发现了一个记忆代码片段,我想知道它在 copy.copy 下的表现如何

发布于 2024-10-22 16:12:24 字数 387 浏览 6 评论 0原文

我发现了这个不错的记忆装饰器:

http://wiki.python.org/moin/PythonDecoratorLibrary#Memoize< /a>

特定的应用程序是在人工智能中,它将存在于不可变的状态类中。问题是我通过返回父状态的 copy.copy 来执行运算符的应用,并应用了请求的运算符。 copy.copy 节省了大量本来会被浪费的时间,因为大部分状态与其父状态相同。

现在,这是我的问题。如果我要在类中使用上述记忆类,是否会传递记忆到潜在无效值的函数的记忆副本?我想我需要以某种方式使记忆的副本无效。

I found this nice memoizing decorator:

http://wiki.python.org/moin/PythonDecoratorLibrary#Memoize

The particular application is in artificial intelligence, and it will live inside an immutable state class. The trouble is that I perform application of operators by returning a copy.copy of the parent state, with requested operator applied. The copy.copy saves a lot of time that would otherwise be wasted, since most of the state is identical to its parent.

Now, here is my problem. If I were to use the above memoization class within the class, would the memoized copies of the functions, which memoize to potentially invalid values, be passed along? I presume I would need to invalidate the memoized copy somehow.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

嘦怹 2024-10-29 16:12:24

是的。 copy.copy 是浅层的,因此它只是复制对记忆包装对象的引用。如果您删除 memoized__get__ 方法,您可以这样尝试(否则,您将得到一个用于支持的 partial 对象)绑定方法):

class C(object):
    @memoized
    def foo(): pass

o1 = C()
o2 = copy.copy(o1)
print o1.foo.cache is o2.foo.cache

您可以在需要时(即复制时)构造一个新的包装器:memoized(C.foo.func)

Yes. copy.copy is shallow, so it just copies a reference to the memoizing wrapper object. You can try it out like this if you remove the __get__ method of memoized (otherwise, you'd get a partial object that's used to support bound methods):

class C(object):
    @memoized
    def foo(): pass

o1 = C()
o2 = copy.copy(o1)
print o1.foo.cache is o2.foo.cache

You can construct a new wrapper when needed (i.e. when you copy): memoized(C.foo.func).

漫雪独思 2024-10-29 16:12:24

一般来说,复制一个对象应该创建一个精确的克隆:如果它有缓存的值,它们也应该被复制。如果不这样做,通常是为了深度复制的速度优化,并且不会产生明显的副作用。

如果您正在制作某些内容的副本并且希望清除副本中的缓存值,那么您应该显式清除缓存。

如果您确实希望对象的副本不复制缓存,请定义 __copy__ 或 __deepcopy__ 方法来控制复制。 (请注意,它的正常用途是复制底层资源,例如文件描述符和句柄。)我不建议这样做。

这是两者的示例。

class memoized(object):
    """
    Decorator that caches a function's return value each time it is called.
    If called later with the same arguments, the cached value is returned, and
    not re-evaluated.
    """
    def __init__(self, func):
        self.func = func
        self.cache = {}
    def __copy__(self):
        """
        Don't copy the cache in a copy.
        """
        return memoized(self.func)
    def __deepcopy__(self, memo):
        """
        Don't copy the cache in a deep copy.
        """
        return memoized(self.func)

    def __call__(self, *args):
       try:
           return self.cache[args]
       except KeyError:
           value = self.func(*args)
           self.cache[args] = value
           return value
       except TypeError:
           # uncachable -- for instance, passing a list as an argument.
           # Better to not cache than to blow up entirely.
           return self.func(*args)
    def __repr__(self):
        """Return the function's docstring."""
        return self.func.__doc__
    def __get__(self, obj, objtype):
        """Support instance methods."""
        return functools.partial(self.__call__, obj)
    def clear_cache(self):
        self.cache = {}

@memoized
def fibonacci(n):
    "Return the nth fibonacci number."
    if n in (0, 1):
        return n
    return fibonacci(n-1) + fibonacci(n-2)

fibonacci(12)
print fibonacci.cache
fibonacci.clear_cache()
print fibonacci.cache

fibonacci(12)
print fibonacci.cache
import copy
f = copy.deepcopy(fibonacci)
print f.cache

Generally, copying an object should create an exact clone: if there it has cached values, they should be copied too. If this isn't done, it's generally as a speed optimization for deep copies and shouldn't have visible side-effects.

If you're making a copy of something and you want cached values in the copy to be cleared, then you should clear the cache explicitly.

If you really want copies of an object to not copy a cache, then define the __copy__ or __deepcopy__ methods to control copying. (Note that the normal use of this is for copying underlying resources, like file descriptors and handles.) I don't recommend doing this.

Here's an example of both.

class memoized(object):
    """
    Decorator that caches a function's return value each time it is called.
    If called later with the same arguments, the cached value is returned, and
    not re-evaluated.
    """
    def __init__(self, func):
        self.func = func
        self.cache = {}
    def __copy__(self):
        """
        Don't copy the cache in a copy.
        """
        return memoized(self.func)
    def __deepcopy__(self, memo):
        """
        Don't copy the cache in a deep copy.
        """
        return memoized(self.func)

    def __call__(self, *args):
       try:
           return self.cache[args]
       except KeyError:
           value = self.func(*args)
           self.cache[args] = value
           return value
       except TypeError:
           # uncachable -- for instance, passing a list as an argument.
           # Better to not cache than to blow up entirely.
           return self.func(*args)
    def __repr__(self):
        """Return the function's docstring."""
        return self.func.__doc__
    def __get__(self, obj, objtype):
        """Support instance methods."""
        return functools.partial(self.__call__, obj)
    def clear_cache(self):
        self.cache = {}

@memoized
def fibonacci(n):
    "Return the nth fibonacci number."
    if n in (0, 1):
        return n
    return fibonacci(n-1) + fibonacci(n-2)

fibonacci(12)
print fibonacci.cache
fibonacci.clear_cache()
print fibonacci.cache

fibonacci(12)
print fibonacci.cache
import copy
f = copy.deepcopy(fibonacci)
print f.cache
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文