32

名前が同じ場合、Pythonはクラス属性、インスタンス属性、およびメソッドをどのように区別しますか?

class Exam(object):

    test = "class var"

    def __init__(self, n):
        self.test = n

    def test(self):
        print "method : ",self.test

test_o = Exam("Fine")

print dir(test_o)

print Exam.test
print test_o.test
test_o.test()

出力:

['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__',    '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'test']
<unbound method load.test>
Fine
Traceback (most recent call last):
  File "example.py", line 32, in <module>
    test_o.test()
TypeError: 'str' object is not callable

呼び方

  1. クラス属性、 Exam.test--><unbound method load.test>出力はメソッドを示します
  2. インスタンス属性 test_o.test -->"Fine"
  3. メソッド test_o.test()-->TypeError: 'str' object is not callable
4

4 に答える 4

26

クラス属性は、クラスを介してアクセスできます。

YourClass.clsattribute

またはインスタンスを介して (インスタンスがクラス属性を上書きしていない場合):

instance.clsattribute

ecatmur が answer で述べているように、メソッドは記述子であり、クラス属性として設定されます。

インスタンスを介してメソッドにアクセスする場合、インスタンスはselfパラメーターとして記述子に渡されます。クラスからメソッドを呼び出す場合は、インスタンスを最初の引数として明示的に渡す必要があります。したがって、これらは同等です:

instance.method()
MyClass.method(instance)

インスタンス属性とメソッドに同じ名前を使用すると、インスタンスを介してメソッドが非表示になりますが、メソッドはクラスを介して引き続き使用できます。

#python3
>>> class C:
...     def __init__(self):
...         self.a = 1
...     def a(self):
...         print('hello')
... 
>>> C.a
<function a at 0x7f2c46ce3c88>
>>> instance = C()
>>> instance.a
1
>>> C.a(instance)
hello

結論: インスタンスの属性とメソッドに同じ名前を付けないでください。意味のある名前を付けることでこれを回避します。メソッドはアクションなので、通常は動詞または文を使用します。属性はデータなので、名詞/形容詞を使用します。これにより、メソッドと属性の両方に同じ名前を使用することを回避できます。

メソッドはそれを完全にオーバーライドするため、メソッドと同じ名前のクラス属性を持つことはできないことに注意してください(最終的に、メソッドは呼び出し可能で、クラスのインスタンスを最初の属性として自動的に受け取る単なるクラス属性です)。 .

于 2012-10-18T07:31:32.903 に答える
3

あなたは書ける

Exam.test(test_o)

また

Exam.test.__get__(test_o)()

後者の場合、メソッドがバインドされたメソッドに変換する記述子<unbound method load.test>であるという事実を使用しているため、単一の括弧で呼び出すことができます。

と書くtest_o.test()と、Python はメソッドを呼び出そうとしていることを知りません。オブジェクトにインスタンス データ メンバーとしてインストールされている関数または呼び出し可能なオブジェクトを呼び出そうとしている可能性があります。代わりにtest、最初にオブジェクト、次にそのクラスで属性を検索しますが、属性がオブジェクトに存在するため、クラスのメソッドを非表示にします。

クラスメンバー

test = "class var"

メソッドによって上書きされるため、アクセスできません (実際にはどこにも存在しません) testclassステートメントが実行されると、その名前空間はメタクラスに渡される前に dict に収集され、後の名前は前の名前を上書きします。

于 2012-10-18T07:19:41.850 に答える
2


クラス属性の 呼び出し方、Exam.test

def test(self)実行時に名前testがクラス内のメソッドにバインドされ、への参照"class var"が失われるため、できません。

インスタンス属性 test_o.test→「Fine」

あなたはすでにそれをしました。

方法 test_o.test()

self.test = n名前testを実行すると、インスタンス内のオブジェクト参照にバインドさnれ、インスタンス内のメソッドへの参照が失われるため、そのように呼び出すことはできません。

ただし、他の回答で指摘されているように、クラスでメソッドを呼び出してインスタンスを渡すことができます。Exam.test(test_o)

于 2016-10-12T22:41:34.917 に答える
1

メソッドをクラス メソッドとして呼び出し、インスタンスを渡すことができます。

Exam.test(test_o)

または、使用したくない場合Exam

type(test_o).test(test_o)
于 2012-10-18T07:20:05.407 に答える