파이썬에서 묘한 문제를 찾았네요

NamedTuple을 GC에서 계속 추적하는 문제에요

from __future__ import annotations

from typing import NamedTuple
import gc


class A(NamedTuple):
    x: list[int] = []


class B(NamedTuple):
    a: A


class FactoryB:
    def create_b(self, a: A) -> B:
        return B(a)

class C(NamedTuple):
    b: B

    @classmethod
    def from_factory(cls, factory: FactoryB) -> C:
        a = A()

        return C(factory.create_b(a))


print(C.from_factory(FactoryB()))
# C(b=B(a=A(x=[])))

C.from_factory(FactoryB()).b.a.x.append(1)
print(C.from_factory(FactoryB()))
# C(b=B(a=A(x=[1])))

print(gc.get_referrers(C.from_factory(FactoryB())))
# []

요거는 이 문제에 대한 분석글 링크

from_factory 메서드를 다음과 같이 수정해 해결하면 되긴 해요

@classmethod
def from_factory(cls, factory: FactoryB) -> C:
    a = A([])

    return C(factory.create_b(a))

NamedTuple 사용시 항상 인자를 넘겨서 초기화해야겠네요…

3 Likes

파이썬을 API 테스트용으로만 싸다보니, 요런 고급기능은 쓸일이 ㅋ

;ㅇ;