Nice programing

클래스의 모든 인스턴스 인쇄

nicepro 2021. 1. 10. 19:56
반응형

클래스의 모든 인스턴스 인쇄


Python의 클래스를 사용하여 함수에 정의 된 형식으로 클래스의 모든 단일 인스턴스를 인쇄하는 함수를 어떻게 정의합니까?


이 경우 두 가지 옵션이 표시됩니다.

가비지 수집기

import gc
for obj in gc.get_objects():
    if isinstance(obj, some_class):
        dome_something(obj)

이것은 많은 오브젝트가있을 때 매우 느리다는 단점이 있지만 제어 할 수없는 유형에서 작동합니다.

mixin 및 weakrefs 사용

from collections import defaultdict
import weakref

class KeepRefs(object):
    __refs__ = defaultdict(list)
    def __init__(self):
        self.__refs__[self.__class__].append(weakref.ref(self))

    @classmethod
    def get_instances(cls):
        for inst_ref in cls.__refs__[cls]:
            inst = inst_ref()
            if inst is not None:
                yield inst

class X(KeepRefs):
    def __init__(self, name):
        super(X, self).__init__()
        self.name = name

x = X("x")
y = X("y")
for r in X.get_instances():
    print r.name
del y
for r in X.get_instances():
    print r.name

이 경우 모든 참조는 목록에 약한 참조로 저장됩니다. 많은 인스턴스를 자주 생성하고 삭제하는 경우 반복 후 weakref 목록을 정리해야합니다. 그렇지 않으면 많은 엉망이 될 것입니다.

이 경우 또 다른 문제는 기본 클래스 생성자를 호출해야한다는 것입니다. 을 재정의 할 수도 __new__있지만 __new__인스턴스화에는 첫 번째 기본 클래스 메서드 사용됩니다. 이것은 또한 사용자가 제어하는 ​​유형에서만 작동합니다.

편집 : 특정 형식에 따라 모든 인스턴스를 인쇄하는 방법은 연습으로 남겨져 있지만 기본적으로 for루프 의 변형 일뿐입니다.


클래스에 정적 목록을 만들고 weakref가비지 수집기가 더 이상 필요하지 않을 때 인스턴스를 정리할 수 있도록 각 인스턴스에를 추가 할 수 있습니다.

import weakref

class A:
    instances = []
    def __init__(self, name=None):
        self.__class__.instances.append(weakref.proxy(self))
        self.name = name

a1 = A('a1')
a2 = A('a2')
a3 = A('a3')
a4 = A('a4')

for instance in A.instances:
    print(instance.name)

Very nice and useful code, but it has a big problem: list is always bigger and it is never cleaned-up, to test it just add print(len(cls.__refs__[cls])) at the end of the get_instances method.

Here a fix for the get_instances method:

__refs__ = defaultdict(list)

@classmethod
def get_instances(cls):
    refs = []
    for ref in cls.__refs__[cls]:
        instance = ref()
        if instance is not None:
            refs.append(ref)
            yield instance
    # print(len(refs))
    cls.__refs__[cls] = refs

or alternatively it could be done using WeakSet:

from weakref import WeakSet

__refs__ = defaultdict(WeakSet)

@classmethod
def get_instances(cls):
    return cls.__refs__[cls]

Same as almost all other OO languages, keep all instances of the class in a collection of some kind.

You can try this kind of thing.

class MyClassFactory( object ):
    theWholeList= []
    def __call__( self, *args, **kw ):
         x= MyClass( *args, **kw )
         self.theWholeList.append( x )
         return x

Now you can do this.

object= MyClassFactory( args, ... )
print MyClassFactory.theWholeList

Python doesn't have an equivalent to Smallktalk's #allInstances as the architecture doesn't have this type of central object table (although modern smalltalks don't really work like that either).

As the other poster says, you have to explicitly manage a collection. His suggestion of a factory method that maintains a registry is a perfectly reasonable way to do it. You may wish to do something with weak references so you don't have to explicitly keep track of object disposal.


It's not clear if you need to print all class instances at once or when they're initialized, nor if you're talking about a class you have control over vs a class in a 3rd party library.

In any case, I would solve this by writing a class factory using Python metaclass support. If you don't have control over the class, manually update the __metaclass__ for the class or module you're tracking.

See http://www.onlamp.com/pub/a/python/2003/04/17/metaclasses.html for more information.


You don't need to import ANYTHING! Just use "self". Here's how you do this

class A:
    instances = []
    def __init__(self):
        self.__class__.instances.append(self)

    @classmethod
    def printInstances(cls):
        for instance in cls.instances:
            print(instance)
A.printInstances()

It's this simple. No modules or libraries imported

ReferenceURL : https://stackoverflow.com/questions/328851/printing-all-instances-of-a-class

반응형