web-dev-qa-db-ja.com

データ属性とメソッド属性の違い

メソッド属性とデータ属性とは何ですか?それらとそれらの共通点との違いは何ですか?

私はpython 2.7.9( https://docs.python.org/2/tutorial/classes.html#random-remarks )を読んでいて、突然両方が理解するのは難しいです。

18
Leandros López

属性は、ドット構文を使用して別のオブジェクトで検索される変数です:_obj.attribute_。 Pythonが設計されている方法では、属性ルックアップはさまざまなことを行うことができます。そして、何が起こっているのか本当に理解していない場合、これはバグにつながる可能性があります(これはあなたがリンクしたドキュメントです)警告します)。

最も基本的な問題は、属性ルックアップがオブジェクトのインスタンスディクショナリに格納されている値を見つけるか、オブジェクトのクラス(または継承が行われている場合は基本クラス)から何かを見つけることができるということです。メソッドはクラスに格納された関数ですが、通常はインスタンスで検索して使用します(メソッドを「バインド」し、メソッドが呼び出されたときに最初の引数としてオブジェクトを挿入します)。

チェックの正確なシーケンスは少し複雑です(プロセス全体を 別の質問への回答 で説明しました)が、最も基本的なレベルでは、インスタンス属性は通常、クラス属性よりも優先されます。

同じ名前のインスタンス属性とクラス属性の両方が存在する場合、通常はインスタンス属性のみにアクセスできます。意図しない場合、これは非常に混乱する可能性があります。

次のコードを検討してください。

_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つの同じ呼び出しを行います。前者は問題なく動作しますが、後者は例外を発生させます。

これは、最初に_f.sum_を検索したときに、Fooクラスにメソッドが見つかったためです。問題なくメソッドを呼び出すことができます。問題は、sumメソッドがその計算結果(_self.lst_の要素の合計)をsumという名前のインスタンス属性に割り当てることです。これにより、sumメソッドが非表示になります。

2番目のf.sum()呼び出しが_f.sum_を検索すると、期待されるメソッドではなく、整数_6_を含むインスタンス属性が見つかります。整数は呼び出すことができないため、例外が発生します。

もちろん、解決策は、メソッドと属性に同じ名前を使用しないことです。上記のコードはかなり簡単な例です。より複雑なコードでこの種のことによって引き起こされるバグは、理解するのがはるかに難しい場合があります。

あまり知らないオブジェクトに属性を追加するコードを書いている場合は、一般的な名前を避けるように注意する必要があります。ミックスインクラスを作成している場合は、属性名に2つの先行アンダースコアを使用して、Pythonの名前マングリングをトリガーすることを検討してください。これは、まさにこのような状況向けに設計されています。

27
Blckknght

属性とは、オブジェクトにバインドされているより良いWordがないことを意味します。たとえば、次のようになります。

class Dog:
    def __init__(self):
        self.name = "Rufus"

    def bark(self):
        print "Woof Woof!"

この場合、data属性は名前であり、これは単にDogのインスタンスにバインドされる値です。メソッド属性については、アクションであるのでそれほど値ではないので、1つの答えはbarkメソッドです。英語のままです。データ属性は、そのとおりです。データであり、単なるプロパティです。メソッドはプロシージャ、アクションであり、これがまさにメソッド属性です。

9
Malik Brahimi

これが質問に対する簡単な説明です。これは、属性とメソッドの違いを理解するのに役立ちました。

クラスは、特性を共有する多くのオブジェクトを構築する方法に関する一連の指示または青写真のようなものです。

オブジェクトは、クラス定義によって提供される仕様に従って構築されたデータ型です。

属性は値(特性)です。属性は、オブジェクト内に格納される変数と考えてください。

メソッドは一連の指示です。メソッドは、オブジェクトに関連付けられた関数です。親クラス定義に含まれる関数は、そのクラスのオブジェクトから呼び出すことができます。

これがお役に立てば幸いです。

3
Joey Grimm

属性は基本的にあなたができることすべてですinstance.attribute_nameあり。たとえば、

class Hello(object):
    def __init__(self, Word):
        self.Word = Word

    def greet(self):
        print "Hello: "+self.Word

__init__greetおよびWordはすべて属性です。メソッドは、(たとえば、self.func = lambda x:x * xを実行するのとは対照的に)クラススコープでdefを使用して宣言されたものであると思います。この場合、バインドされたメソッドとバインドされていないメソッドなどに入ります。重要な部分は、あなたがinstance.method_nameバインドされたメソッドが返されます。このメソッドを呼び出すと、最初の引数としてインスタンスを指定して元のメソッドが呼び出されます。

また、そのセクションのいくつかを読んだ後、彼らの言葉遣いはやや紛らわしい/誤りです。たとえば、「データ属性は同じ名前のメソッド属性をオーバーライドする」と言います。これは、私が知る限り、同じ名前のインスタンス属性がクラス属性をオーバーライドするために配置した方がよいでしょう。これを次のように拡張した場合の例から、

class Hello(object):
    greeting = "Hello: "
    def __init__(self, Word):
        self.Word = Word

    def greet(self):
        print self.greeting+self.Word

次に、次のことができます。

>>> a = Hello("world")
>>> a.greeting = "Goodbye "
>>> a.greet()
"Goodbye world"

これは、greetingのインスタンス属性を、greetingのclass属性の上に置くためです。クラスで定義されたメソッド(通常の方法)はクラス属性であるため、インスタンス属性(データなど)によってオーバーライドされます。

2
CrazyCasta

属性は、メソッドがオブジェクトに作用してそれを変更する間、オブジェクトを記述します。

0
Robai