如何在不泄漏内存的情况下在类中使用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的推荐方法是什么?
请注意,这类似于如何在 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
我正在尝试使用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 …
我想让字符串比较不区分大小写。为此,我想创建一个只有一个字符串字段的不可变类。在构造函数中,我想在将值分配给字段之前调用 lower() 。
我想尽可能多地使用标准类,如命名元组或数据类。使用该__post_init__函数(参见例如如何在Python中的数据类中使用__post_init__方法)感觉就像是一种黑客攻击。这也让我想知道在我在函数中更改它后该字段是否仍然冻结__post_init__。
但是,我找不到__pre_init__功能。有没有更好的办法?