Понимание подсчета ссылок и метаклассов - PullRequest
0 голосов
/ 14 февраля 2019

Я пытаюсь сделать некоторые вещи с метаклассами, и я не понимаю результат этого моего кода на python.

import sys

class Meta(type):
    a = None
    b = None

    def __call__(cls, *args, **kwargs):
        name = args[0]
        if getattr(cls, name) is None:
            setattr(cls, name, super(Meta, cls).__call__(*args, **kwargs))
        return getattr(cls, name)


class A:
    __metaclass__ = Meta

    def __init__(self, name, in_a = None):
        self.a = None
        if in_a:
            self.a = in_a


a = A("a")

print sys.getrefcount(a) - 2  # 1

b = A("b", a)

print sys.getrefcount(a) - 2  # 2

b = None

print sys.getrefcount(a) - 2  # 2?

У меня есть две ссылки на a, один из которых являетсяатрибут b.

Когда я удаляю ссылку b (или установлен на None), количество рефенсов на a по-прежнему равно 2.

Теперь, когдаЯ не использую метаклассы, это хорошо работает:

class A:
    def __init__(self, in_a = None):
        self.a = None
        if in_a is not None:
            self.a = in_a


a = A()

print sys.getrefcount(a) - 1  # 1

b = A(a)

print sys.getrefcount(a) - 1  # 2

b = None

print sys.getrefcount(a) - 1  # 1

Можете ли вы объяснить разницу?

1 Ответ

0 голосов
/ 14 февраля 2019

С вашим кодом, b также хранится как A.b, поэтому просто установка глобального b на None не вызывает сбор этого экземпляра - потому что есть еще ссылка на него - поэтому refcountоставайтесь постоянными.Итак, вы забыли проверить счет на b ;-)

Просто добавьте A.b = None, и вы увидите, что счет уменьшится.

Обратите внимание, что это не имеет ничего общего с метаклассами (не уверен, что вы на самом деле пытаетесь сделать здесь, но, вероятно, есть гораздо более простое / очевидное решение).

...