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 在他的回答中所述,方法是描述符并设置为类属性。

如果您通过实例访问方法,则实例将作为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"

不可访问(实际上它在任何地方都不存在),因为它被方法覆盖test;当一个class语句被执行时,它的命名空间在被传递给它的元类之前被收集到一个字典中,后面的名字会覆盖前面的名字。

于 2012-10-18T07:19:41.850 回答
2

如何调用
类属性, Exam.test

你不能因为在执行时def test(self)名称test被绑定到类中的方法并且对的引用"class var"丢失了。

实例属性 test_o.test-->“好”

你已经这样做了。

方法 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 回答