下面的类方法有什么区别?
是不是一个是静态的,另一个不是?
class Test(object):
def method_one(self):
print "Called method_one"
def method_two():
print "Called method_two"
a_test = Test()
a_test.method_one()
a_test.method_two()
下面的类方法有什么区别?
是不是一个是静态的,另一个不是?
class Test(object):
def method_one(self):
print "Called method_one"
def method_two():
print "Called method_two"
a_test = Test()
a_test.method_one()
a_test.method_two()
当前回答
这是一个错误。
首先,第一行应该是这样的(注意大写)
class Test(object):
当你调用一个类的方法时,它将自己作为第一个参数(因此命名为self), method_two会给出这个错误
>>> a.method_two()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: method_two() takes no arguments (1 given)
其他回答
>>> class Class(object):
... def __init__(self):
... self.i = 0
... def instance_method(self):
... self.i += 1
... print self.i
... c = 0
... @classmethod
... def class_method(cls):
... cls.c += 1
... print cls.c
... @staticmethod
... def static_method(s):
... s += 1
... print s
...
>>> a = Class()
>>> a.class_method()
1
>>> Class.class_method() # The class shares this value across instances
2
>>> a.instance_method()
1
>>> Class.instance_method() # The class cannot use an instance method
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unbound method instance_method() must be called with Class instance as first argument (got nothing instead)
>>> Class.instance_method(a)
2
>>> b = 0
>>> a.static_method(b)
1
>>> a.static_method(a.c) # Static method does not have direct access to
>>> # class or instance properties.
3
>>> Class.c # a.c above was passed by value and not by reference.
2
>>> a.c
2
>>> a.c = 5 # The connection between the instance
>>> Class.c # and its class is weak as seen here.
2
>>> Class.class_method()
3
>>> a.c
5
一旦你了解了描述符系统的基础知识,Python中的方法就非常非常简单了。想象一下下面的类:
class C(object):
def foo(self):
pass
现在让我们来看看shell中的类:
>>> C.foo
<unbound method C.foo>
>>> C.__dict__['foo']
<function foo at 0x17d05b0>
正如你所看到的,如果你访问类上的foo属性,你会得到一个未绑定的方法,然而在类存储(dict)中有一个函数。为什么?这样做的原因是类的类实现了解析描述符的__getattribute__。听起来很复杂,但事实并非如此。在这种特殊情况下,C.foo大致相当于下面的代码:
>>> C.__dict__['foo'].__get__(None, C)
<unbound method C.foo>
这是因为函数有__get__方法,使它们成为描述符。如果你有一个类的实例,它几乎是一样的,只是None是类实例:
>>> c = C()
>>> C.__dict__['foo'].__get__(c, C)
<bound method C.foo of <__main__.C object at 0x17bd4d0>>
为什么Python要这么做呢?因为方法对象将函数的第一个形参绑定到类的实例。这就是自我的来源。有时候你不希望你的类把一个函数变成一个方法,这时就需要用到staticmethod了:
class C(object):
@staticmethod
def foo():
pass
staticmethod装饰器包装了你的类,并实现了一个虚拟__get__,它将被包装的函数作为函数而不是方法返回:
>>> C.__dict__['foo'].__get__(None, C)
<function foo at 0x17d0c30>
希望这能解释清楚。
请阅读Guido First Class的文档,清楚地解释了Unbound, Bound方法是如何诞生的。
对method_two的调用将抛出一个异常,表示不接受self参数,Python运行时将自动传递给它。
如果你想在Python类中创建一个静态方法,用staticmethod装饰器来装饰它。
Class Test(Object):
@staticmethod
def method_two():
print "Called method_two"
Test.method_two()
method_two的定义无效。当你调用method_two时,你会得到TypeError: method_two()接受0个位置参数,但1个是由解释器给出的。
当您像a_test.method_two()那样调用实例方法时,它是一个有界函数。它自动接受指向Test实例的self作为第一个参数。通过self参数,实例方法可以自由地访问和修改同一对象上的属性。