メソッド属性とデータ属性とは何ですか? それらの違いと共通点は何ですか?
私はPython 2.7.9を読んでいました(https://docs.python.org/2/tutorial/classes.html#ランダムマーク) 突然、両方とも理解しにくくなりました。この点についてご説明いただければ幸いです。
ベストアンサー1
属性は、ドット構文を使用して別のオブジェクトで検索される変数です。Pythonobj.attribute
の設計上、属性検索ではさまざまなことを行うことができますが、何が起こっているのかよく理解していないと、その多様性によってバグが発生することがあります (これは、リンク先のドキュメントで警告されている内容です)。
最も基本的な問題は、属性の検索では、オブジェクトのインスタンス ディクショナリに格納されている値、またはオブジェクトのクラス (継承が行われている場合は基本クラス) から何かが見つかる可能性があるということです。メソッドはクラスに格納されている関数ですが、通常はインスタンスで検索して使用します (インスタンスはメソッドを「バインド」し、メソッドが呼び出されたときにオブジェクトを最初の引数として挿入します)。
いつ何がチェックされるかの正確な順序は少し複雑です(私は全体のプロセスを別の質問への答え) ですが、最も基本的なレベルでは、インスタンス属性は通常、クラス属性よりも優先されます。
同じ名前のインスタンス属性とクラス属性の両方が存在する場合、通常はインスタンス属性のみがアクセス可能になります。これは意図的でない場合は非常に混乱を招く可能性があります。
次のコードを考えてみましょう。
class Foo(object):
def __init__(self, lst):
self.lst = lst
def sum(self):
self.sum = sum(self.lst)
return self.sum
f = Foo([1,2,3])
print(f.sum())
print(f.sum())
このコードの下部で、同一の呼び出しを 2 回行います。最初の呼び出しは正常に動作しますが、2 回目は例外が発生します。
これは、最初に検索したときに、クラスf.sum
内にメソッドが見つかるからです。メソッドは問題なく呼び出すことができます。問題は、メソッドが計算結果 ( 内の要素の合計) を、同じく という名前のインスタンス属性に割り当てるFoo
ことから生じます。これにより、メソッドがビューから非表示になります。sum
self.lst
sum
sum
f.sum()
2 回目の呼び出しで を検索するとf.sum
、予期されたメソッドではなく、整数 を含むインスタンス属性が見つかります6
。整数は呼び出し可能ではないため、例外が発生します。
もちろん、解決策はメソッドと属性に同じ名前を使用しないことです。上記のコードは非常に単純な例です。より複雑なコードでこのようなことが原因で発生するバグは、見つけるのがはるかに困難になる可能性があります。
よく知らないオブジェクトに属性を追加するコードを記述する場合は、一般的な名前を避けるように注意する必要があります。mixin クラスを記述する場合は、属性名の先頭に 2 つのアンダースコアを使用して、まさにこのような状況のために設計された Python の名前マングリングをトリガーすることを検討してください。
補足: ドキュメントで区別しようとしているのは、データ記述子と非データ記述子の間である可能性もあります。メソッドは最も一般的な非データ記述子なので、メソッドを「メソッド属性」と呼ぶのはある程度意味があるかもしれません (特に、データ記述子に対応する名前である「データ属性」と対照的に)。ただし、この用語がより広く使用されているとは知りません。2 種類の記述子の重要な違いは、データ記述子 ( などproperty
) は処理されることです。前にインスタンス辞書は通常のインスタンス変数に対してチェックされます。上で述べたように、メソッドのような非データ記述子は、後インスタンス ディクショナリがチェックされるため、インスタンスに保存されているデータによってシャドウされる可能性があります。