Pythonのクラスで、関数で定義された形式でクラスのすべてのインスタンスを印刷する関数を定義するにはどうすればよいですか?
この場合、2つのオプションが表示されます。
import gc
for obj in gc.get_objects():
if isinstance(obj, some_class):
dome_something(obj)
これには、多くのオブジェクトがある場合に非常に遅いという欠点がありますが、制御できない型では機能します。
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
- loopsのバリエーションにすぎません。
クラスに静的リストを作成し、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)
非常に便利で便利なコードですが、大きな問題があります:リストは常に大きく、クリーンアップされることはありません。テストするにはprint(len(cls.__refs__[cls]))
を追加してくださいget_instances
メソッドの終わり。
get_instances
メソッドの修正:
__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
または、WeakSetを使用して行うこともできます。
from weakref import WeakSet
__refs__ = defaultdict(WeakSet)
@classmethod
def get_instances(cls):
return cls.__refs__[cls]
他のほとんどすべてのOO言語と同様に、クラスのすべてのインスタンスを何らかのコレクションに保持します。
この種のものを試すことができます。
class MyClassFactory( object ):
theWholeList= []
def __call__( self, *args, **kw ):
x= MyClass( *args, **kw )
self.theWholeList.append( x )
return x
これでできます。
object= MyClassFactory( args, ... )
print MyClassFactory.theWholeList
PythonにはSmallktalkの#allInstancesに相当するものがありません。アーキテクチャにはこのタイプの中央オブジェクトテーブルがないためです(ただし、現代のsmalltalkも実際には機能しません)。
他のポスターが言っているように、コレクションを明示的に管理する必要があります。レジストリを維持するファクトリメソッドの彼の提案は、それを行うための完全に合理的な方法です。 weak reference で何かをしたい場合があるので、オブジェクトの破棄を明示的に追跡する必要はありません。
すべてのクラスインスタンスを一度に印刷する必要があるのか、それらが初期化されたのか、また、サードパーティライブラリのクラスに対して制御するクラスについて話しているのかどうかは明らかではありません。
いずれにしても、Pythonメタクラスサポートを使用してクラスファクトリを記述することでこれを解決します。クラスを制御できない場合は、手動で__metaclass__
追跡しているクラスまたはモジュール。
詳細については、 http://www.onlamp.com/pub/a/python/2003/04/17/metaclasses.html を参照してください。
何もインポートする必要はありません! 「自己」を使用してください。これがあなたのやり方です
class A:
instances = []
def __init__(self):
self.__class__.instances.append(self)
@classmethod
def printInstances(cls):
for instance in cls.instances:
print(instance)
A.printInstances()
これは簡単です。モジュールまたはライブラリがインポートされていません