質問

いくつかの属性を持つクラスがあるとします。これらの属性にアクセスするのは(Pythonic-OOPで)どういう意味ですか? obj.attr のように?または、getアクセサーを記述しますか? そのようなものに受け入れられている命名スタイルは何ですか?

編集: 単一または二重の先頭アンダースコアを使用した属性の命名のベストプラクティスについて詳しく説明できますか?ほとんどのモジュールで、単一のアンダースコアが使用されていることがわかります。


この質問がすでに尋ねられている場合(検索で結果が得られなかったとしても、私は疑問を抱いています)、それを指摘してください-そして、私はこの質問を閉じます。

役に立ちましたか?

解決

一般に受け入れられている方法は、単純な属性を使用することです。

>>> class MyClass:
...     myAttribute = 0
... 
>>> c = MyClass()
>>> c.myAttribute 
0
>>> c.myAttribute = 1
>>> c.myAttribute
1

ゲッターとセッターを記述する必要がある場合は、「pythonクラスプロパティ」を探します。および Ryan Tomaykoの記事 Getters / Setters / Fuxors は開始するのに最適な場所です(少し長いですが)。

他のヒント

単一および二重のアンダースコアに関して:両方とも同じ「プライベート」の概念を示しています。つまり、人々は、属性(メソッドや「通常の」データ属性など)がオブジェクトのパブリックAPIの一部ではないことを知っています。人々はそれに直接触れることが災害を招くことであることを知っているでしょう。

さらに、サブクラスから誤ってアクセスするために、二重のアンダースコア属性(単一のアンダースコア属性ではない)が name-mangled されますまたは、現在のクラスの外部の可能性が低い場所。引き続きアクセスできますが、それほど簡単ではありません。例:

>>> class ClassA:
...     def __init__(self):
...         self._single = "Single"
...         self.__double = "Double"
...     def getSingle(self):
...         return self._single
...     def getDouble(self):
...         return self.__double
... 
>>> class ClassB(ClassA):
...     def getSingle_B(self):
...         return self._single
...     def getDouble_B(self):
...         return self.__double
... 
>>> a = ClassA()
>>> b = ClassB()

a._single および b._single に簡単にアクセスし、 ClassA _single 属性を取得できるようになりました>:

>>> a._single, b._single
('Single', 'Single')
>>> a.getSingle(), b.getSingle(), b.getSingle_B()
('Single', 'Single', 'Single')

ただし、 a または b インスタンスの __ double 属性に直接アクセスしようとしても機能しません。

>>> a.__double
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: ClassA instance has no attribute '__double'
>>> b.__double
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: ClassB instance has no attribute '__double'

そして、 ClassA で定義されたメソッドは、直接取得できます(いずれかのインスタンスで呼び出された場合):

>>> a.getDouble(), b.getDouble()
('Double', 'Double')

ClassB で定義されたメソッドは次のことができません:

>>> b.getDouble_B()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 5, in getDouble_B
AttributeError: ClassB instance has no attribute '_ClassB__double'

そして、そのエラーの中で、何が起こっているかについてのヒントを得ることができます。 __ double 属性名は、クラス内でアクセスされたときに、アクセスされているクラスの名前を含むように名前が変更されています ClassA self .__ double にアクセスしようとすると、実際には-コンパイル時に- self._ClassA__double のアクセスに変わります。 ClassB 。 ( ClassB のメソッドが __ double に割り当てられ、簡潔にするためにコードに含まれていない場合、 ClassA の< code> __ double ただし、新しい属性を作成します。)この属性には他の保護はありません。正しい名前を知っていれば、直接アクセスできます:

>>> a._ClassA__double, b._ClassA__double
('Double', 'Double')

では、なぜこれが問題なのですか?

まあ、この属性を扱うコードの振る舞いを継承して変更したいときはいつでも問題です。この二重アンダースコア属性に直接関係するすべてを再実装するか、クラス名を推測して手動で名前を変更する必要があります。この二重アンダースコア属性が実際にメソッドである場合、問題は悪化します。メソッドをオーバーライドするか、サブクラスでメソッドを呼び出すとは、名前のマングリングを手動で行うか、メソッドを呼び出すすべてのコードを再実装することを意味します二重アンダースコア名を使用しないでください。 getattr()を使用して属性に動的にアクセスすることは言うまでもありません。手動でそこをマングルする必要があります。

一方、属性は簡単に書き換えられるだけなので、表面的な「保護」のみを提供します。手動でマングリングすることで、コードのどの部分でも属性を取得できますが、自分のコードはあなたのクラスの名前に依存し、あなたの側でリファクタリングする努力をしますコードを作成したり、クラスの名前を変更したり(同じユーザーに表示される名前を保持したまま、Pythonで一般的に行われている)、コードを不必要に壊してしまいます。また、クラスにあなたと同じ名前を付けることで、Pythonを「だまして」名前マングリングを行うことができます。マングルされた属性名にモジュール名が含まれていないことに注意してください。そして最後に、二重アンダースコア属性は、すべての属性リストおよび(単一)アンダースコアで始まる属性をスキップすることに注意を払わないすべての形式のイントロスペクションに引き続き表示されます。

したがって、場合は二重アンダースコア名を使用し、非常に控えめに使用するため、それらを非常に控えめに使用し、メソッドまたはサブクラスが必要とする他のものには決して使用しないでください再実装、オーバーライド、または直接アクセスするには。また、二重のアンダースコアネームマングリングは、本当の保護を提供しないことを理解します。最後に、単一のリードを使用して

  

編集:単一または二重の先頭アンダースコアを使用した属性の命名のベストプラクティスについて詳しく説明できますか?ほとんどのモジュールで、単一のアンダースコアが使用されていることがわかります。

シングルアンダースコアはpythonにとって特別な意味を意味するものではなく、「何をしているのかわからない限り、おそらくアクセスしたくない」と伝えるのがベストプラクティスです。ただし、二重アンダースコアを使用すると、Pythonは内部的に名前をマングルして、定義されているクラスからのみアクセスできるようにします。

二重の先頭と末尾のアンダースコアは、+演算子を使用するときに呼び出される __ add __ などの特別な関数を示します。

詳細については、 PEP 8 、特に「命名規則」をご覧ください;セクション。

ほとんどの場合、直接アクセスするだけで、get / setメソッドは不要だと思います。

>>> class myclass:
...     x = 'hello'
...
>>>
>>> class_inst = myclass()
>>> class_inst.x
'hello'
>>> class_inst.x = 'world'
>>> class_inst.x
'world'

ところで、dir()関数を使用して、どの属性/メソッドがインスタンスにアタッチされているかを確認できます。

>>> dir(class_inst)
['__doc__', '__module__', 'x']

2つの主要なアンダーバー&quot; __&quot;属性または関数をプライベートにするために使用されます。 他の規則については、PEP 08を参照してください。 http://www.python.org/dev/peps/pep-0008/

属性へのプロパティの変換は迅速かつ簡単なので、Pythonは最初からアクセサを定義する必要がありません。鮮明なデモンストレーションについては、次を参照してください。

中毒からの回復

Pythonでgetter / setterを実行する本当の意味はありません。とにかくものを保護することはできません。プロパティを取得/設定するときに追加のコードを実行する必要がある場合は、組み込みのproperty()を見てください(python -c ' help(property) ')

一部の人々はゲッターとセッターを使用しています。使用するコーディングスタイルに応じて、getSpamおよびseteggsという名前を付けることができます。ただし、属性を読み取り専用または割り当て専用にすることもできます。それは少しやっかいです。 1つの方法は

をオーバーライドすることです
> __getattr__

and

> __setattr__

メソッド。

編集:

私の答えはまだ真実ですが、気がついたように正しくありません。 pythonでアクセサーを作成するより良い方法があり、それほど厄介ではありません。

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