web-dev-qa-db-ja.com

python:クラス属性、インスタンス属性、メソッドがすべて同じ名前の場合はどうなりますか?

名前が同じ場合、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_
27
naren

クラス属性には、クラスからアクセスできます。

YourClass.clsattribute

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

instance.clsattribute

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

インスタンスを介してメソッドにアクセスする場合、インスタンスは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

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

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

23
Bakuriu

あなたは書ける

_Exam.test(test_o)
_

または

_Exam.test.__get__(test_o)()
_

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

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

クラスのメンバー

_test = "class var"
_

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

3
ecatmur

電話のかけ方
クラス属性、_Exam.test_

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

インスタンス属性_test_o.test_-> "Fine"

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

メソッドtest_o.test()

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

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

1
Goyo

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

Exam.test(test_o)

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

type(test_o).test(test_o)
1
Fedor Gogolev