1

特に、ユーザーが新しい属性を動的に作成できないようにすることで、Python クラスの動的性を低下させる方法について読んでいます。オーバーロード__setattr__はこれを行う良い方法であり、進むべき道で__slots__はないことを読みました。この最後のスレッドの1 つの投稿は、__slots__ピクルス化を中断する可能性があることを実際に示唆しています。(誰かこれを確認できますか?)

ただし、Python 2.2 の whatsnew を読んだだけで、属性アクセス セクション__slots__では、他の人が提案したような最適化のためだけでなく、属性の作成を制限する目的で使用することを実際に提案しています。Python の歴史に関して言えば、Python の当初の意図を知っている人はい__slots__ますか? 変数の作成を制限することは、悪用される機能またはバグですか? 人々は実際にどのように__slots__使用されてきましたか? __setattr__属性の作成を制限するためにオーバーロードされているのを多くの人が見たことがありますか? どれが一番いいですか?いずれかの方法に精通している場合は、知っている方法の長所と短所を自由に投稿してください. また、問題を解決する別の方法がある場合は、共有してください! (そして、そのマイナス面を繰り返さないようにしてください__slots__他のスレッドで表現されています。)

編集:「なぜ?」の議論を避けたいと思っていましたが、最初の回答はこれが発生することを示しているので、ここに記載します。問題のプロジェクトでは、これらのクラスを使用して「構成情報」を保存し、ユーザーが (ユーザーの) パラメータを使用してオブジェクトに属性を設定し、オブジェクトをプログラムの別の部分に渡すことができるようにします。オブジェクトはパラメーターを格納するだけではないため、辞書は機能しません。ユーザーが誤って属性名を間違って入力し、プログラムが期待する属性の 1 つを設定するのではなく、新しい属性を作成してしまうという事例が既に発生しています。これは検出されないため、ユーザーはパラメーターを設定していると思いますが、期待される結果が表示されません。これはユーザーを混乱させ、見つけにくいものです。

EDIT 2, re pickling: これらのオブジェクトは、将来保存したいものになるでしょう。明らかに最善の解決策である場合__slots__、おそらく別の保存方法を見つけることができますが、酸洗いは間違いなく価値があり、考慮に入れておく必要があります.

EDIT 3:メモリの節約は問題ではないことにも言及する必要があります。これらのオブジェクトはほとんど作成されないため、節約されるメモリはごくわずかです (3 ~ 12 GB のマシンで数十キロバイトのように)。

4

2 に答える 2

4

開発者がそれを行うのを制限しようとしているのはなぜですか? 「やりたくない」以外に技術的な理由はありますか?そうでない場合は、それをしないでください。

とにかく、を使用すると__slots__メモリが節約されます(いいえ__dict__)ので、それを行う方が良い解決策です。あなたのコードの一部がオブジェクトを持っている必要がある場合、それを使用することはできません__dict__

それを制限する正当な理由がある場合 (もう一度言いますが、それはありますか?) 、またはメモリを少し節約する必要がある場合は、__slots__.


__setattr__説明を読んだ後、おそらく と組み合わせて使用​​したいと思うかもしれません__slots__(とにかく属性のホワイトリストをどこかに保存する必要があるので、それを使用してメモリを節約することもできます)。そうすれば、どの類似属性が利用可能かなど、より役立つ情報を表示できます。可能な実装は次のようになります。

class Test(object):
    __slots__ = ('foo', 'bar', 'moo', 'meow', 'foobar')

    def __setattr__(self, name, value):
        try:
            object.__setattr__(self, name, value)
        except AttributeError:
            alts = sorted(self.__slots__, key=lambda x: levenshtein(name, x))
            msg = "object has no attribute '{}', did you mean '{}'?"
            raise AttributeError(msg.format(name, alts[0]))

levenshtein()私がテストしたのは、このサイトの実装 #4です。あまり賢くないユーザーの場合は、エラーをさらに詳細にして、最初の一致だけでなくすべての近似一致を含めることをお勧めします。

__setattr__メソッドだけを含む mixin クラスを作成することで、コードをさらに改善できます。そうすれば、コードを実際のクラスから除外し、__setattr__必要に応じてカスタムも作成できます(super(...).__setattr__(...)の代わりにミックスインで使用するだけですobject.__setattr__

于 2013-12-05T17:16:51.710 に答える