相关疑难解决方法(0)

Python functools lru_cache与类方法:释放对象

如何在不泄漏内存的情况下在类中使用functools的lru_cache?在下面的最小示例中,foo虽然超出范围且没有引用者(lru_cache除外),但实例不会被释放.

from functools import lru_cache
class BigClass:
    pass
class Foo:
    def __init__(self):
        self.big = BigClass()
    @lru_cache(maxsize=16)
    def cached_method(self, x):
        return x + 5

def fun():
    foo = Foo()
    print(foo.cached_method(10))
    print(foo.cached_method(10)) # use cache
    return 'something'

fun()
Run Code Online (Sandbox Code Playgroud)

但是foo因此foo.big(a BigClass)仍然活着

import gc; gc.collect()  # collect garbage
len([obj for obj in gc.get_objects() if isinstance(obj, Foo)]) # is 1
Run Code Online (Sandbox Code Playgroud)

这意味着Foo/BigClass实例仍然驻留在内存中.即使删除Foo(del Foo)也不会释放它们.

为什么lru_cache会依赖实例?缓存不是使用一些哈希而不是实际对象吗?

在类中使用lru_caches的推荐方法是什么?

我知道两个解决方法: 使用每个实例缓存使缓存忽略对象(这可能会导致错误的结果)

python caching lru functools python-decorators

33
推荐指数
6
解决办法
9202
查看次数

在 asdict 或序列化中将属性包含在数据类中的推荐方法是什么?

请注意,这类似于如何在 asdict 中获取 @property 方法?

我有一个(冻结的)嵌套数据结构,如下所示。定义了一些(纯粹)依赖于字段的属性。

import copy
import dataclasses
import json
from dataclasses import dataclass

@dataclass(frozen=True)
class Bar:
    x: int
    y: int

    @property
    def z(self):
        return self.x + self.y

@dataclass(frozen=True)
class Foo:
    a: int
    b: Bar

    @property
    def c(self):
        return self.a + self.b.x - self.b.y
Run Code Online (Sandbox Code Playgroud)

我可以按如下方式序列化数据结构:

class CustomEncoder(json.JSONEncoder):
    def default(self, o):
        if dataclasses and dataclasses.is_dataclass(o):
            return dataclasses.asdict(o)
        return json.JSONEncoder.default(self, o)

foo = Foo(1, Bar(2,3))
print(json.dumps(foo, cls=CustomEncoder))

# Outputs {"a": 1, "b": {"x": 2, "y": 3}}
Run Code Online (Sandbox Code Playgroud)

但是,我还想序列化属性 ( …

python serialization immutability python-3.x python-dataclasses

17
推荐指数
3
解决办法
6642
查看次数

如何在 Python 数据类中使用 __post_init__ 方法

我正在尝试使用Python中的数据类,我想做的是在我的类中拥有一个计算字段,并将 sort_index 字段添加到调用中,但也希望将其冻结,以便我无法修改任何属性定义后的此类。下面是我的代码:

from dataclasses import dataclass, field

def _get_year_of_birth(age: int, current_year: int=2019):
    return current_year - age

@dataclass(order=True, frozen=True)
class Person():
    sort_index: int = field(init=False, repr=False)
    name: str
    lastname: str
    age: int
    birthyear: int = field(init=False)


    def __post_init__(self):
        self.sort_index = self.age
        self.birthyear = _get_year_of_birth(self.age)



if __name__ == "__main__":
    persons = [
    Person(name="Jack", lastname="Ryan", age=35),
    Person(name="Jason", lastname="Bourne", age=45),
    Person(name="James", lastname="Bond", age=60)
    ]

    sorted_persons = sorted(persons)
    for person in sorted_persons:
        print(f"{person.name} and {person.age} and year of birth is : {person.birthyear}")
Run Code Online (Sandbox Code Playgroud)

看来我无法在类中设置自定义排序字段,也无法创建从其他属性计算得出的任何属性,因为我使用的是 freeze …

python-3.7 python-dataclasses

9
推荐指数
1
解决办法
2万
查看次数

python 中的 __pre_init__ 功能?

我想让字符串比较不区分大小写。为此,我想创建一个只有一个字符串字段的不可变类。在构造函数中,我想在将值分配给字段之前调用 lower() 。

我想尽可能多地使用标准类,如命名元组或数据类。使用该__post_init__函数(参见例如如何在Python中的数据类中使用__post_init__方法)感觉就像是一种黑客攻击。这也让我想知道在我在函数中更改它后该字段是否仍然冻结__post_init__

但是,我找不到__pre_init__功能。有没有更好的办法?

python

5
推荐指数
2
解决办法
7013
查看次数