質問

目的は何か __slots__ Pythonでは、特につの場合いたいと思利用できません。

役に立ちましたか?

解決

Pythonでは、目的は何か __slots__ その場合一回避すべきこと。

TLDR:

特殊属性 __slots__ できる旨を明示するインスタンスの属性だくことを期待インスタンスオブジェクトにおいて、期待される成果:

  1. 高速 属性アクセス。
  2. 省スペース アメリカで行われ

省スペースから

  1. 保存価値の参照にはスロットの代わりに __dict__.
  2. を否定 __dict____weakref__ 創造の場合は親の授業を否定していを宣言する __slots__.

早注意

小さな点に注意するべきだけを宣言するのに、特定のスロット時に継承。例えば:

class Base:
    __slots__ = 'foo', 'bar'

class Right(Base):
    __slots__ = 'baz', 

class Wrong(Base):
    __slots__ = 'foo', 'bar', 'baz'        # redundant foo and bar

Pythonなオブジェクトだこの間違い(しかし、問題がなマニフェストが、オブジェクトを取るような。

>>> from sys import getsizeof
>>> getsizeof(Right()), getsizeof(Wrong())
(64, 80)

最大の問題点は、複数の相続-複数の"親クラス空でないスロット"を併用することはできません.

対応この制限は、最良の実践:要因すべてのものはすべての親の抽象化されるコンクリートのクラスそれぞれ新しいコンクリートクラスの総称を継承すから-の抽象化(s)空のスロットのような抽象基底クラスを、標準ライブラリ).

されている複数の継承に関して以下の例です。

要件:

  • ての属性名 __slots__ 実際に格納されるスロットの代わりに __dict__, では、クラスからは継承し object.

  • 防止の創造 __dict__, は、からの継承 object およびすべてのクラスの遺産"として宣言する必要があ __slots__ をおこなうもので '__dict__' 入力します。

あるので詳細をご希望の場合は保ちます。

を利用する理由 __slots__:高速の属性にアクセス。

の作Python Guido van Rossum, 彼が実際に作成された __slots__ により属性にアクセス。

ことになる検討は不可避で大幅な高速アクセス:

import timeit

class Foo(object): __slots__ = 'foo',

class Bar(object): pass

slotted = Foo()
not_slotted = Bar()

def get_set_delete_fn(obj):
    def get_set_delete():
        obj.foo = 'foo'
        obj.foo
        del obj.foo
    return get_set_delete

>>> min(timeit.repeat(get_set_delete_fn(slotted)))
0.2846834529991611
>>> min(timeit.repeat(get_set_delete_fn(not_slotted)))
0.3664822799983085

スロット付きアクセスはほぼ30%より速いブ3.5Ubuntu.

>>> 0.3664822799983085 / 0.2846834529991611
1.2873325658284342

Python2はWindowsしていま測定では約15%になります。

を利用する理由 __slots__:メモリの貯蓄

もう一つの目的の __slots__ 軽空間記憶している各オブジェクトインスタンス。

自分への貢献の書類を明らかにするとともその理由:

のスペースに保存用 __dict__ できます。

SQLAlchemy属性 多くのメモリの節約 __slots__.

を検証するこのAnaconda分布のPython2.7Ubuntu Linux、 guppy.hpy (通称heapy) sys.getsizeof, のサイズクラスのインスタンスな __slots__ 宣言は、何といっても、64バイトまでとなります。ることは ない などの __dict__.まPythonのためのぐさの評価は、再び、 __dict__ そうしないという存在では参照されるが、授業のデータの有無にかかわらず、通常のどちらがいいでしょうか?が呼び出されるとともに __dict__ 属性が最小限280バイトします。

これに対し、クラスのインスタンス __slots__ 宣言されて () (データ)は16バイトは、56総バイスロット、64ます。

64ビットはPythonのかを説明するメモリ消費量のバイトをPython2.7 3.6、 __slots____dict__ (スロット定義した各点の辞が3.6以外は、0、1、2つの属性):

       Python 2.7             Python 3.6
attrs  __slots__  __dict__*   __slots__  __dict__* | *(no slots defined)
none   16         56 + 272†   16         56 + 112† | †if __dict__ referenced
one    48         56 + 272    48         56 + 112
two    56         56 + 272    56         56 + 112
six    88         56 + 1040   88         56 + 152
11     128        56 + 1040   128        56 + 240
22     216        56 + 3344   216        56 + 408     
43     384        56 + 3344   384        56 + 752

いずれか小さいdicts Python3にしていく __slots__ 規模インスタンスを存メモリは、大きな理由でも使いたい __slots__.

だけで完成度の上記のい場合がありますので注意して一時コスロットのクラスの名前空間の64バイトをPython2は、72バイトをPython3に、スロット用データ記述子としての性質と呼ばれる"会員".

>>> Foo.foo
<member 'foo' of 'Foo' objects>
>>> type(Foo.foo)
<class 'member_descriptor'>
>>> getsizeof(Foo.foo)
72

実証 __slots__:

を拒否する創造の __dict__, は、サブクラス object:

class Base(object): 
    __slots__ = ()

現在:

>>> b = Base()
>>> b.a = 'a'
Traceback (most recent call last):
  File "<pyshell#38>", line 1, in <module>
    b.a = 'a'
AttributeError: 'Base' object has no attribute 'a'

またはサブクラスのクラスを定義する __slots__

class Child(Base):
    __slots__ = ('a',)

現在:

c = Child()
c.a = 'a'

もの:

>>> c.b = 'b'
Traceback (most recent call last):
  File "<pyshell#42>", line 1, in <module>
    c.b = 'b'
AttributeError: 'Child' object has no attribute 'b'

許可する __dict__ 作成中の場合は、サブクラススロット付き物だけで追加 '__dict__'__slots__ (スロットが、なんか繰り返すスロットになってしまった親クラス):

class SlottedWithDict(Child): 
    __slots__ = ('__dict__', 'b')

swd = SlottedWithDict()
swd.a = 'a'
swd.b = 'b'
swd.c = 'c'

>>> swd.__dict__
{'c': 'c'}

または必要な時に必要なだけを宣言する __slots__ サブクラスで、まだ使用スロットから保護者の方が制限するの創造 __dict__:

class NoSlots(Child): pass
ns = NoSlots()
ns.a = 'a'
ns.b = 'b'

と:

>>> ns.__dict__
{'b': 'b'}

しかし、 __slots__ の原因となり問題が複数の継承:

class BaseA(object): 
    __slots__ = ('a',)

class BaseB(object): 
    __slots__ = ('b',)

とは難しく、子供から親非空のスロットに失敗した:

>>> class Child(BaseA, BaseB): __slots__ = ()
Traceback (most recent call last):
  File "<pyshell#68>", line 1, in <module>
    class Child(BaseA, BaseB): __slots__ = ()
TypeError: Error when calling the metaclass bases
    multiple bases have instance lay-out conflict

こんなときにこの問題は、 で削除 __slots__ からの親の場合は制御の両親は、空のスロットに、refactorへの抽象化:

from abc import ABC

class AbstractA(ABC):
    __slots__ = ()

class BaseA(AbstractA): 
    __slots__ = ('a',)

class AbstractB(ABC):
    __slots__ = ()

class BaseB(AbstractB): 
    __slots__ = ('b',)

class Child(AbstractA, AbstractB): 
    __slots__ = ('a', 'b')

c = Child() # no problem!

追加 '__dict__'__slots__ を動的課題:

class Foo(object):
    __slots__ = 'bar', 'baz', '__dict__'

現在:

>>> foo = Foo()
>>> foo.boink = 'boink'

この '__dict__' にスロットを失わせてしまうもののサイズにも上振れの動的な課題だとスロットの名前をい。

きを継承することにより、オブジェクトは、できる限り少ないスロット付きなのに、同じようなセマンティクスを使用す __slots__ -名前がつけられていますが、 __slots__ ポイントスロット付き価値観、その他の値を入れていインスタンスの __dict__.

回避 __slots__ を用いて追加することができ属性に飛んでない理由などを追加 "__dict__"__slots__ これが必要です。

まで同様に追加 __weakref____slots__ 明示的にあなたが必要と特徴です。

設定空のタプルの場合は、サブクラスは、namedtuple:

のnamedtuple組み込みく変更できるインスタンスは非常に軽量化(基本的に、サイズのタプルでの特典を行う必要があります。ったりとしたサブクラスとして

from collections import namedtuple
class MyNT(namedtuple('MyNT', 'bar baz')):
    """MyNT is an immutable and lightweight object"""
    __slots__ = ()

使用量:

>>> nt = MyNT('bar', 'baz')
>>> nt.bar
'bar'
>>> nt.baz
'baz'

ように割り当て予想外の属性を上げ AttributeError い防止の創出 __dict__:

>>> nt.quux = 'quux'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'MyNT' object has no attribute 'quux'

ができ 許可 __dict__ を創造できるよう退off __slots__ = (), が使用できません空 __slots__ とサブタイプのタプル.

最大の問題点:複数の相続

時空スロットが同じ複数の親しなくてはならないため、使用す:

class Foo(object): 
    __slots__ = 'foo', 'bar'
class Bar(object):
    __slots__ = 'foo', 'bar' # alas, would work if empty, i.e. ()

>>> class Baz(Foo, Bar): pass
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Error when calling the metaclass bases
    multiple bases have instance lay-out conflict

使用空 __slots__ の親会見が行われ、そのほか多くの柔軟性 の子どもを選ぶの防止に使用することを目的と (追加 '__dict__' 取得の動的配置の項を参照) の作成 __dict__:

class Foo(object): __slots__ = ()
class Bar(object): __slots__ = ()
class Baz(Foo, Bar): __slots__ = ('foo', 'bar')
b = Baz()
b.foo, b.bar = 'foo', 'bar'

まん してい てスロットできるの追加と削除し、その後はな問題を引き起こす.

したいと願うようになっている肢こちら:だを構成する mixins または使用 抽象基底クラス, 思意のインスタンスが生成され、空の __slots__ この両親が最良の道のり面での柔軟性subclassers.

が、まずクラスを作成するコードしたいと考えて使用複数の継承

class AbstractBase:
    __slots__ = ()
    def __init__(self, a, b):
        self.a = a
        self.b = b
    def __repr__(self):
        return f'{type(self).__name__}({repr(self.a)}, {repr(self.b)})'

また、上記の直接受け継がれることを宣言する想されるスロット数:

class Foo(AbstractBase):
    __slots__ = 'a', 'b'

ものというのは気にしていないが、些細なシングルの継承し、必要なクラスまものを受け継ぐらかと騒音の属性:

class AbstractBaseC:
    __slots__ = ()
    @property
    def c(self):
        print('getting c!')
        return self._c
    @c.setter
    def c(self, arg):
        print('setting c!')
        self._c = arg

今ならも拠点が空でないスロットでは出来ませんでしたのです。(実際には、またして AbstractBase 空ではなスロットa、b、および置いていったのかわからないのは以下の宣言-できるだけ早くも悪い):

class Concretion(AbstractBase, AbstractBaseC):
    __slots__ = 'a b _c'.split()

い機能性の両方からの多重継承できるものを否定 __dict____weakref__ インスタンス生成:

>>> c = Concretion('a', 'b')
>>> c.c = c
setting c!
>>> c.c
getting c!
Concretion('a', 'b')
>>> c.d = 'd'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Concretion' object has no attribute 'd'

その他の場合を避けるスロット数:

  • 避けることときを行っていきたいと考えてい __class__ 課題別のクラスがない(できない追加しない場合にスロットレイアウトのと同一です。(私の学習に興味をもっている者であることはいかがでしょうか。)
  • を回避したい場合はサブクラスは可変長builtinsのように、タプル、またはstrやしたい属性を追加します。
  • 避けることばを提供するデフォルト値で経由クラス属性のためのインスタンス変数.

ることができる絵の一層の注意から __slots__ 書類(3.7dev docsに現在), また、私ども大きく最近の貢献です。

批評のその他の回答

現在のトップ応答挙げ時代遅れの情報はなかなか手波のマークの一部の重要な要素がある。

い"のみを使用 __slots__ スをインスタンス化する際に多くのオブジェ"

し見積もり:

"と思った利用 __slots__ だよりインスタンスを生成する景色は駅の屋根だけという、何百、何千人ものオブジェクトと同じクラスです。"

抽象基底クラスでしっかり果たしていきたいと考え、 collections モジュールなインスタンスを生成し __slots__ 宣言されました。

なぜですか?

本サイトのご利用に拒否 __dict__ または __weakref__ 創造も必要によってご利用になれない親ます。

__slots__ に貢献する再利用性の作成時にインタフェースmixins.

るが、すでに多くのPythonユーザーにな書きのために再利用でき、オプションを拒否する不必要な東北地方太平洋沖地震の影響には貴重なのである。

__slots__ な休憩洗い

時に洗い、スロット付きオブジェクト、ましてご使用いただくことも可能で宣との誤解を招く TypeError:

>>> pickle.loads(pickle.dumps(f))
TypeError: a class that defines __slots__ without defining __getstate__ cannot be pickled

これは実際に間違っています。このメッセージから最も古いプロトコルのデフォルトです。選択できます最新のプロトコルの -1 引数です。Python2.7こ 2 (導入されたものです2.3)、3.6で 4.

>>> pickle.loads(pickle.dumps(f, -1))
<__main__.Foo object at 0x1129C770>

Python2.7:

>>> pickle.loads(pickle.dumps(f, 2))
<__main__.Foo object at 0x1129C770>

Python3.6

>>> pickle.loads(pickle.dumps(f, 4))
<__main__.Foo object at 0x1129C770>

ようなので注意してください。では解決問題です。

批判するまで月2日2016年度)受付回答

最初の段落の半分の短い説明は、半分に予測しやすいものにするかこちらのはみっという問いに対する答え

の適切な利用に関す __slots__ は、保存スペースオブジェクト。を有する動的辞書名またを設定できる追加の属性体自身の自己責任でなされるものである静的構造できない追加後ます。こに保存する架空の辞べてのオブジェクトを使用するスロット

後半は希望的観測としては、のマーク:

なることが多いので、有益な最適化が全く不要な場合はPythonインタプリタがった動くことにするための辞があった追加のオブジェクトです。

Python実際にはそこだけの作成 __dict__ ときにアクセスが、多くのオブジェクトのデータはかなりば.

第二項の規定oversimplifies、ミスを実際に理由を回避 __slots__.以下に示します ない 実際の理由を避けるスロット( 実際の 理由は、自分の答えます。):

その変化の挙動はスロットができる虐待の制御によるフリークおよび静的タイピングweenies.

そして、その議その他の方法で達成するのが僕の目標はPythonではな議論といい __slots__.

第三項の規定は希望的観測かがえます。とほとんどの場合、これは、マークのコンテンツのanswererなかったものの著者への弾薬のための批判のサイトです。

メモリ使用の証拠

を通常のオブジェクトにスロット付きオブジェクト

>>> class Foo(object): pass
>>> class Bar(object): __slots__ = ()

インスタンス化し:

>>> foos = [Foo() for f in xrange(1000000)]
>>> bars = [Bar() for b in xrange(1000000)]

検査と guppy.hpy().heap():

>>> guppy.hpy().heap()
Partition of a set of 2028259 objects. Total size = 99763360 bytes.
 Index  Count   %     Size   % Cumulative  % Kind (class / dict of class)
     0 1000000  49 64000000  64  64000000  64 __main__.Foo
     1     169   0 16281480  16  80281480  80 list
     2 1000000  49 16000000  16  96281480  97 __main__.Bar
     3   12284   1   987472   1  97268952  97 str
...

アクセスの正体とその __dict__ 検査してもらうことを目的として

>>> for f in foos:
...     f.__dict__
>>> guppy.hpy().heap()
Partition of a set of 3028258 objects. Total size = 379763480 bytes.
 Index  Count   %      Size    % Cumulative  % Kind (class / dict of class)
     0 1000000  33 280000000  74 280000000  74 dict of __main__.Foo
     1 1000000  33  64000000  17 344000000  91 __main__.Foo
     2     169   0  16281480   4 360281480  95 list
     3 1000000  33  16000000   4 376281480  99 __main__.Bar
     4   12284   0    987472   0 377268952  99 str
...

この歴史のPythonから 統一種およびクラスをPython2.2

場合はサブクラス内蔵タイプ、余分のスペースが自動的に追加され、インスタンスを調整 __dict____weakrefs__.( __dict__ が初期化されませんでしまい、なんか気の空の辞書のための各インスタンスを作成します.) 必要がない場合はこの余分のスペースに追加することができますの言葉"__slots__ = []"をクラスです。

他のヒント

ヤコブ・ハレンのrel="noreferrer">引用

  

__slots__の適切な使用は、オブジェクト内のスペースを節約することです。代わりになるの   いつでもオブジェクトに属性を追加することができますダイナミック辞書、   作成後の追加を許可していない静的な構造があります。   これは、時には役に立つ最適化ですが、それは完全になり、[すべてのオブジェクトの1つのdictのオーバーヘッドがなくなります。<=>の使用は]   不要なPythonインタプリタは、それがなるように、十分なダイナミックだった場合   実際にオブジェクトへの追加があった場合にのみ辞書を必要とします。

     

残念ながらスロットに副作用があります。彼らはの動作を変更します   コントロールフリークで悪用される可能性が道のスロットを持つオブジェクト   そして、静的型付けweenies。コントロールフリークは、必要があるので、これは悪いです   メタクラスを乱用すると、静的な型付けweeniesが悪用されなければなりません   デコレータは、Pythonでいるので、何かをすることの唯一の明白な方法があるはずです。

     大手である<=>せずに

スペースを節約し処理するのに十分なCPythonのは、スマート作ります   おそらく事業は、なぜそれがP3k(まだ)。

の変更のリストに載っていません

あなたは、同じクラスのオブジェクトの多く(数百、数千の)インスタンス化しようとしている場合__slots__使用するとよいでしょう。 <=>専用メモリ最適化ツールとして存在します。

これは、属性の作成を拘束するため<=>使用することを非常に落胆だし、一般的に、あなたは、Pythonの他のいくつかのイントロスペクション機能と一緒に、それはピクルスを壊すので、それを避けたい。

各Pythonオブジェクトは、他のすべての属性を含む辞書である__dict__ atttributeを有しています。例えばあなたはself.attr入力のpythonは、実際にself.__dict__['attr']やっています。あなたは属性を格納するための辞書を使用して想像できるように、それをアクセスするためのいくつかの余分なスペース&時間がかかります。

あなたは__slots__使用する場合、

しかし、そのクラス用に作成された任意のオブジェクトは、<=>属性を持っていません。代わりに、すべての属性へのアクセスは、ポインタ経由で直接実行されます。

Cスタイルの構造ではなく、本格的なクラスをしたいのであれば、あなたは、オブジェクトのサイズを圧縮&属性アクセス時間を短縮するための<=>使用することができます。良い例は、属性のX&Yを含むPointクラスです。あなたはポイントをたくさん持ってしようとしている場合は、一部のメモリを節約するために<=>使用して試すことができます。

は、他の回答に加えて、ここで使用した例である__slots__

>>> class Test(object):   #Must be new-style class!
...  __slots__ = ['x', 'y']
... 
>>> pt = Test()
>>> dir(pt)
['__class__', '__delattr__', '__doc__', '__getattribute__', '__hash__', 
 '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', 
 '__repr__', '__setattr__', '__slots__', '__str__', 'x', 'y']
>>> pt.x
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: x
>>> pt.x = 1
>>> pt.x
1
>>> pt.z = 2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Test' object has no attribute 'z'
>>> pt.__dict__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Test' object has no attribute '__dict__'
>>> pt.__slots__
['x', 'y']
(それがまだない場合は、新しいスタイルのクラスをし、あなたのクラスを作る)

だから、<=>実装し、それだけで余分なラインを取ります。あなたがhref="http://dev.svetlyak.ru/using-slots-for-optimisation-in-python-en/"を を、それが必要になった場合ならば、カスタム・ピクルス・コードを記述することを犠牲にします。

スロットは、ライブラリ関数呼び出しを行うときに「という名前のメソッドディスパッチ」を排除するために呼び出すために非常に便利です。これはSWIG ドキュメントの中で言及されています。スロットを使用して、一般的に呼ばれる機能のための機能のオーバーヘッドを削減したい、高いパフォーマンスライブラリの場合ははるかに高速です。

さて、これは直接のOPの質問に関連していなくてもよいです。それはそれはオブジェクト上のスロットの構文を使用するよりも、建物の拡張により関連しています。しかし、それは、スロットとその背後にある理由のいくつかの用途のために絵を完成助けるん。

クラスのインスタンスの属性は、3つのプロパティがあります。例えば、属性の名前、および属性の値を

での の通常の属性アクセスを、インスタンスは辞書として機能し、属性の名前は、値を調べることで、辞書のキーとして機能します。

のインスタンス(属性) - >値

での の__ slots__アクセスの、属性の名前が辞書として機能し、インスタンスが値を調べる辞書でキーとして機能します。

の属性(インスタンス) - >値

のFlyweightパターンのでは、属性の名前は、インスタンスを探している辞書でキーとして辞書と値の行為として機能します。

の属性(値) - >例

非常に簡単な例 __slot__ 属性。

問題点:なし __slots__

ばん __slot__ 属性私の授業では、できる新しい属性は私のオブジェクト。

class Test:
    pass

obj1=Test()
obj2=Test()

print(obj1.__dict__)  #--> {}
obj1.x=12
print(obj1.__dict__)  # --> {'x': 12}
obj1.y=20
print(obj1.__dict__)  # --> {'x': 12, 'y': 20}

obj2.x=99
print(obj2.__dict__)  # --> {'x': 99}

見れば、上の例ることが確認でき obj1obj2 独自の xy 属性およびpythonのものでは dict 属性オブジェクトobj1obj2).

いま私のクラス 試験 何千にもこのようなオブジェクト?を追加で属性 dict 各オブジェクトが多くのオーバーヘッドメモリ、コンピューティング力など) 私のコードです。

【解決と __slots__

現在、以下の例は、私のクラス 試験 含む __slots__ 属性。今はできない新しい属性は私のオブジェクト(以外の属性 x)pythonのなを dict 属性がなくなった。この消費の各オブジェクトは、大きくなっている場合は多くのオブジェクト。

class Test:
    __slots__=("x")

obj1=Test()
obj2=Test()
obj1.x=12
print(obj1.x)  # --> 12
obj2.x=99
print(obj2.x)  # --> 99

obj1.y=28
print(obj1.y)  # --> AttributeError: 'Test' object has no attribute 'y'

__slots__の別のややあいまいな用途はPEAKプロジェクトの一部かつて、ProxyTypesパッケージからオブジェクトプロキシに属性を追加することです。そのObjectWrapperプロキシに別のオブジェクトを許可しますが、プロキシになるオブジェクトとのすべてのやり取りを傍受します。これは非常に一般的に使用されていない(そしてPythonの3のサポート)はありませんが、我々はスレッドセーフを使用して、ioloopを介してプロキシオブジェクトへのすべてのアクセスをバウンス竜巻に基づく非同期実装の周りにスレッドセーフなブロッキングラッパーを実装するためにそれを使用していますconcurrent.Future同期して結果を返すためにオブジェクトます。

デフォルトでは、プロキシオブジェクトへの任意の属性へのアクセスは、あなたのプロキシになるオブジェクトからの結果が得られます。プロキシオブジェクトに属性を追加する必要がある場合は、<=>を使用することができます。

from peak.util.proxies import ObjectWrapper

class Original(object):
    def __init__(self):
        self.name = 'The Original'

class ProxyOriginal(ObjectWrapper):

    __slots__ = ['proxy_name']

    def __init__(self, subject, proxy_name):
        # proxy_info attributed added directly to the
        # Original instance, not the ProxyOriginal instance
        self.proxy_info = 'You are proxied by {}'.format(proxy_name)

        # proxy_name added to ProxyOriginal instance, since it is
        # defined in __slots__
        self.proxy_name = proxy_name

        super(ProxyOriginal, self).__init__(subject)

if __name__ == "__main__":
    original = Original()
    proxy = ProxyOriginal(original, 'Proxy Overlord')

    # Both statements print "The Original"
    print "original.name: ", original.name
    print "proxy.name: ", proxy.name

    # Both statements below print 
    # "You are proxied by Proxy Overlord", since the ProxyOriginal
    # __init__ sets it to the original object 
    print "original.proxy_info: ", original.proxy_info
    print "proxy.proxy_info: ", proxy.proxy_info

    # prints "Proxy Overlord"
    print "proxy.proxy_name: ", proxy.proxy_name
    # Raises AttributeError since proxy_name is only set on 
    # the proxy object
    print "original.proxy_name: ", proxy.proxy_name

あなたは持っていません - 基本的に - __slots__のための使用を。

あなたが<=>必要かもしれないと思う時間のために、あなたは実際の軽量またはフライ級のデザインパターンを使用します。これらはあなたがもはや純粋にPythonのオブジェクトを使用したいない場合もあります。代わりに、配列、構造体、またはnumpyの配列の周りのPythonオブジェクトのようなラッパーを望んます。

class Flyweight(object):

    def get(self, theData, index):
        return theData[index]

    def set(self, theData, index, value):
        theData[index]= value

クラスのようなラッパーには属性がありません - それだけで、基礎となるデータに作用するメソッドを提供します。メソッドは、クラスメソッドに減少させることができます。確かに、それだけでデータの基になる配列上で動作して機能するために減少させることができた。

元の質問は、メモリについてだけでなく、一般的な使用例についてでした。 興味深い例えば - だから、のパフォーマンスのオブジェクトを大量にインスタンス化するときにも良くなることをここで言及されるべきですオブジェクトへ、またはデータベースから大規模な文書を解析するときます。

ここでスロットを使用して、百万のエントリを持つオブジェクトツリーを作成し、スロットなしの比較です。また、基準木(OSX上Py2.7.10)のために普通dictsを使用してパフォーマンスとして:

********** RUN 1 **********
1.96036410332 <class 'css_tree_select.element.Element'>
3.02922606468 <class 'css_tree_select.element.ElementNoSlots'>
2.90828204155 dict
********** RUN 2 **********
1.77050495148 <class 'css_tree_select.element.Element'>
3.10655999184 <class 'css_tree_select.element.ElementNoSlots'>
2.84120798111 dict
********** RUN 3 **********
1.84069895744 <class 'css_tree_select.element.Element'>
3.21540498734 <class 'css_tree_select.element.ElementNoSlots'>
2.59615707397 dict
********** RUN 4 **********
1.75041103363 <class 'css_tree_select.element.Element'>
3.17366290092 <class 'css_tree_select.element.ElementNoSlots'>
2.70941114426 dict

テストクラス(IDENT、スロットからアパート):

class Element(object):
    __slots__ = ['_typ', 'id', 'parent', 'childs']
    def __init__(self, typ, id, parent=None):
        self._typ = typ
        self.id = id
        self.childs = []
        if parent:
            self.parent = parent
            parent.childs.append(self)

class ElementNoSlots(object): (same, w/o slots)

testcode、冗長モード:

na, nb, nc = 100, 100, 100
for i in (1, 2, 3, 4):
    print '*' * 10, 'RUN', i, '*' * 10
    # tree with slot and no slot:
    for cls in Element, ElementNoSlots:
        t1 = time.time()
        root = cls('root', 'root')
        for i in xrange(na):
            ela = cls(typ='a', id=i, parent=root)
            for j in xrange(nb):
                elb = cls(typ='b', id=(i, j), parent=ela)
                for k in xrange(nc):
                    elc = cls(typ='c', id=(i, j, k), parent=elb)
        to =  time.time() - t1
        print to, cls
        del root

    # ref: tree with dicts only:
    t1 = time.time()
    droot = {'childs': []}
    for i in xrange(na):
        ela =  {'typ': 'a', id: i, 'childs': []}
        droot['childs'].append(ela)
        for j in xrange(nb):
            elb =  {'typ': 'b', id: (i, j), 'childs': []}
            ela['childs'].append(elb)
            for k in xrange(nc):
                elc =  {'typ': 'c', id: (i, j, k), 'childs': []}
                elb['childs'].append(elc)
    td = time.time() - t1
    print td, 'dict'
    del droot
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top