Pythonのスロット属性は、クラスレベルでデータ属性(インスタンス変数)を明示的に宣言するために使用されるツールであり、より効率的なメモリ使用量と属性アクセスがより高速につながる可能性があります。クラスが__slots__
属性を定義すると、Pythonは、インスタンス属性を保存するために動的辞書を使用する代わりに、クラスの各インスタンスに小さな固定サイズ配列を作成します。このメカニズムはいくつかの目的を果たします。
__slots__
を使用することにより、インスタンスの__dict__
は作成されません。これは、特に多数のインスタンスを扱う場合にメモリを保存します。__slots__
対応のクラスでの属性へのアクセスは、辞書の検索のオーバーヘッドを回避するため、標準の辞書ベースのインスタンスで属性にアクセスするよりも高速になります。__slots__
が定義されている場合、Pythonは__slots__
に明示的に含まれていない限り、 __dict__
__slots__
で定義されたものに新しい属性の作成を制限します。 __slots__
使用方法の基本的な例を次に示します。
<code class="python">class Point: __slots__ = ('x', 'y') def __init__(self, x, y): self.x = x self.y = y</code>
__slots__
の使用は、いくつかのパフォーマンスの利点を提供できます。
__slots__
インスタンスの__dict__
固定サイズの配列に置き換えるため、インスタンスのメモリフットプリントを大幅に削減できます。これは、多数のインスタンスを作成する場合に特に有益です。__slots__
で定義されている属性は、辞書に保存されているものよりも迅速にアクセスできます。これは、小さな固定サイズのアレイで要素にアクセスすることは、辞書の検索を実行するよりも一般的に高速であるためです。__slots__
を使用したインスタンスは、フォローする参照が少ないため、ゴミコレクターによってより迅速に収集される場合があります。これらの利点を説明するには、次の例を考えてみましょう。
<code class="python">import sys class StandardPoint: def __init__(self, x, y): self.x = x self.y = y class SlotPoint: __slots__ = ('x', 'y') def __init__(self, x, y): self.x = x self.y = y standard = StandardPoint(1, 2) slot = SlotPoint(1, 2) print(sys.getsizeof(standard)) # Output may be around 56 bytes print(sys.getsizeof(slot)) # Output may be around 32 bytes</code>
この例では、 SlotPoint
インスタンスでは、 StandardPoint
インスタンスよりも少ないメモリを使用します。
__slots__
を使用すると、次の方法で属性の割り当てに影響を与えます。
__slots__
が定義されている場合、 __slots__
にリストされている属性のみをインスタンスに割り当てることができます。 __slots__
にない属性を割り当てようとすると、 __dict__
が__slots__
に含まれていない限り、 AttributeError
が上昇します。__dict__
__ :デフォルトでは、 __slots__
を使用したクラスのインスタンスには__dict__
がありません。これは、 __dict__
が__slots__
に明示的に含まれていない限り、動的属性の割り当てが無効になることを意味します。__weakref__
:クラスが弱い参照をサポートする必要がある場合、 __weakref__
__slots__
に含める必要があります。これらの効果を示す例は次のとおりです。
<code class="python">class RestrictedPoint: __slots__ = ('x', 'y') point = RestrictedPoint() point.x = 10 # This is allowed point.y = 20 # This is allowed try: point.z = 30 # This will raise an AttributeError except AttributeError as e: print(e) # Output: 'RestrictedPoint' object has no attribute 'z'</code>
はい、 __slots__
継承と組み合わせて使用できますが、留意すべきいくつかの考慮事項があります。
__slots__
を定義する場合、スーパークラスからスロットを継承しますが、スーパークラスが__slots__
を定義した場合のみです。スーパークラスが__slots__
使用しない場合、そのインスタンスは引き続き__dict__
を使用します。これはメモリの非効率性につながる可能性があります。__dict__
を組み合わせて:サブクラスが動的属性を許可したい場合、 __slots__
に__dict__
を含めることができます。ただし、これはそもそも__slots__
を使用するという記憶を救う目的を打ち負かす可能性があります。__slots__
で複数継承を使用する場合、すべてのクラスは__slots__
を定義するか、 __slots__
を定義するクラスから継承する必要があります。 1つの親クラスが__slots__
使用しない場合、サブクラスのインスタンスにはまだ__dict__
があります。これらの考慮事項を説明する例は次のとおりです。
<code class="python">class Base: __slots__ = ('x',) class Derived(Base): __slots__ = ('y',) # Inherits 'x' from Base derived = Derived() derived.x = 10 # Inherited from Base derived.y = 20 # Defined in Derived class FlexibleDerived(Base): __slots__ = ('y', '__dict__') # Allows dynamic attributes flexible = FlexibleDerived() flexible.x = 10 # Inherited from Base flexible.y = 20 # Defined in FlexibleDerived flexible.z = 30 # Dynamic attribute, allowed because of __dict__</code>
結論として、 __slots__
継承で効果的に使用できますが、クラスの階層全体で望ましいメモリの最適化と属性動作が達成されるように慎重に計画する必要があります。
以上が__slots__属性の目的を説明します。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。