23

Python でいくつかの属性を持つオブジェクトを作成したいのですが、間違った属性名を誤って使用しないように保護したいと考えています。コードは次のとおりです。

class MyClass( object ) :
    m = None # my attribute
    __slots__ = ( "m" ) # ensure that object has no _m etc

a = MyClass() # create one
a.m = "?"  # here is a PROBLEM

しかし、この単純なコードを実行すると、非常に奇妙なエラーが発生します。

Traceback (most recent call last):
  File "test.py", line 8, in <module>
    a.m = "?"
AttributeError: 'test' object attribute 'm' is read-only

少し時間を割いて、「読み取り専用」エラーについて教えてくれる賢明なプログラマーはいますか?

4

5 に答える 5

46

を使用してインスタンス変数を宣言する__slots__と、Python は記述子オブジェクトを同じ名前のクラス変数として作成します。あなたの場合、この記述子はm、次の行で定義しているクラス変数によって上書きされます。

  m = None # my attribute

行う必要があるのは次のとおりです。 というクラス変数を定義せず、メソッドでmインスタンス変数を初期化します。m__init__

class MyClass(object):
  __slots__ = ("m",)
  def __init__(self):
    self.m = None

a = MyClass()
a.m = "?"

補足として、要素が 1 つのタプルには、要素の後にコンマが必要です。__slots__単一の文字列または反復可能な文字列/文字列のシーケンスを受け入れるため、どちらもコードで機能します。一般に、要素を含むタプルを定義するには、orおよび not1を使用します。(1,)1,(1)

于 2009-05-04T16:07:51.587 に答える
12

あなたは完全に誤用して__slots__います。インスタンスの作成を防ぎ__dict__ます。これは、多くの小さなオブジェクトでメモリの問題が発生した場合にのみ意味があります__dict__。削除するとフットプリントを減らすことができるからです。これは、すべてのケースの 99.9% で必要とされないハードコアな最適化です。

あなたが説明した種類の安全性が必要な場合、Python は本当に間違った言語です。(Python で Java を書こうとするのではなく) Java のような厳密なものを使用することをお勧めします。

クラス属性がコードでこれらの問題を引き起こした理由を自分で理解できなかった場合は、このような言語ハックを導入することを再考する必要があります。最初に言語に慣れる方が賢明でしょう。

完全を期すために、スロットのドキュメント リンクを次に示します。

于 2009-05-04T20:05:24.620 に答える
7

__slots__インスタンス変数で動作しますが、そこにあるのはクラス変数です。これはあなたがそれを行うべき方法です:

class MyClass( object ) :
  __slots__ = ( "m", )
  def __init__(self):
    self.m = None

a = MyClass()
a.m = "?"       # No error
于 2009-05-04T16:02:54.873 に答える
6

このことを考慮。

class SuperSafe( object ):
    allowed= ( "this", "that" )
    def __init__( self ):
        self.this= None
        self.that= None
    def __setattr__( self, attr, value ):
        if attr not in self.allowed:
            raise Exception( "No such attribute: %s" % (attr,) )
        super( SuperSafe, self ).__setattr__( attr, value )

より良いアプローチは、この種のチェックに単体テストを使用することです。これはかなりの量のランタイム オーバーヘッドです。

于 2009-05-04T17:06:55.173 に答える
0
class MyClass( object ) :
    m = None # my attribute

これmは、インスタンス属性ではなく、クラス属性です。で自分自身でインスタンスに接続する必要があります__init__

于 2014-10-20T15:51:31.073 に答える