以下类方法有什么区别?
是一个是静态而另一个不是?
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()
Run Code Online (Sandbox Code Playgroud)
Tor*_*rek 407
在Python中,绑定和未绑定方法之间存在区别.
基本上,调用成员函数(如method_one),绑定函数
a_test.method_one()
Run Code Online (Sandbox Code Playgroud)
被翻译成
Test.method_one(a_test)
Run Code Online (Sandbox Code Playgroud)
即对未绑定方法的调用.因此,对您的版本的调用method_two将失败TypeError
>>> a_test = Test()
>>> a_test.method_two()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: method_two() takes no arguments (1 given)
Run Code Online (Sandbox Code Playgroud)
您可以使用装饰器更改方法的行为
class Test(object):
def method_one(self):
print "Called method_one"
@staticmethod
def method_two():
print "Called method two"
Run Code Online (Sandbox Code Playgroud)
装饰器告诉内置的默认元类type(类的类,参见这个问题)不创建绑定方法method_two.
现在,您可以直接在实例或类上调用静态方法:
>>> a_test = Test()
>>> a_test.method_one()
Called method_one
>>> a_test.method_two()
Called method_two
>>> Test.method_two()
Called method_two
Run Code Online (Sandbox Code Playgroud)
Arm*_*her 189
一旦理解了描述符系统的基础知识,Python中的方法就变得非常非常简单.想象一下以下课程:
class C(object):
def foo(self):
pass
Run Code Online (Sandbox Code Playgroud)
现在让我们看一下shell中的那个类:
>>> C.foo
<unbound method C.foo>
>>> C.__dict__['foo']
<function foo at 0x17d05b0>
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,如果您访问foo该类的属性,则会返回一个未绑定的方法,但是在类存储(dict)中有一个函数.为什么?这样做的原因是你的类的类实现了一个__getattribute__解析描述符.听起来很复杂,但事实并非如此. C.foo在这种特殊情况下大致相当于此代码:
>>> C.__dict__['foo'].__get__(None, C)
<unbound method C.foo>
Run Code Online (Sandbox Code Playgroud)
那是因为函数有一个__get__使它们成为描述符的方法.如果你有一个类的实例几乎相同,那None就是类实例:
>>> c = C()
>>> C.__dict__['foo'].__get__(c, C)
<bound method C.foo of <__main__.C object at 0x17bd4d0>>
Run Code Online (Sandbox Code Playgroud)
现在为什么Python会这样做?因为方法对象将函数的第一个参数绑定到类的实例.这就是自我的来源.现在,有时你不希望你的类将函数作为一个方法,这就是staticmethod发挥作用的地方:
class C(object):
@staticmethod
def foo():
pass
Run Code Online (Sandbox Code Playgroud)
该staticmethod装饰包装类,并实现虚拟__get__返回的包裹功能功能,而不是作为一种方法:
>>> C.__dict__['foo'].__get__(None, C)
<function foo at 0x17d0c30>
Run Code Online (Sandbox Code Playgroud)
希望能够解释它.
Jus*_*iey 11
当您调用类成员时,Python会自动使用对象的引用作为第一个参数.变量self实际上没有任何意义,它只是一种编码约定.gargaloo如果你愿意,你可以打电话给它.也就是说,调用method_two会引发一个TypeError,因为Python会自动尝试将参数(对其父对象的引用)传递给定义为没有参数的方法.
要实际使其工作,您可以将其附加到您的类定义:
method_two = staticmethod(method_two)
Run Code Online (Sandbox Code Playgroud)
或者你可以使用@staticmethod 函数装饰器.
kzh*_*kzh 11
>>> 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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
145124 次 |
| 最近记录: |