質問

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

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

役に立ちましたか?

解決

を使用してインスタンス変数を宣言すると、 __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 = "?"

補足として、単一の要素を含むタプルには要素の後にカンマが必要です。どちらもコード内で機能します。 __slots__ 単一の文字列または文字列の反復可能/シーケンスを受け入れます。一般に、要素を含むタプルを定義するには、 1, 、 使用 (1,) または 1, そしてそうではありません (1).

他のヒント

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

説明したような安全性が必要な場合、Pythonは本当に間違った言語です。 (PythonでJavaを記述しようとする代わりに)Javaのような厳密なものを使用する方が良い。

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

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

__ slots __ はインスタンス変数で動作しますが、クラス変数があります。これがあなたのやり方です:

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

a = MyClass()
a.m = "?"       # No error

これを考慮してください。

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 )

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

class MyClass( object ) :
    m = None # my attribute

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

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top