下面的类方法有什么区别?

是不是一个是静态的,另一个不是?

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()

当前回答

当调用类成员时,Python自动使用对象引用作为第一个形参。变量self实际上没有任何意义,它只是一种编码约定。如果你愿意,可以叫它滴水怪。也就是说,对method_two的调用将引发TypeError,因为Python会自动尝试将一个参数(对其父对象的引用)传递给一个定义为没有参数的方法。

为了让它工作,你可以把这个附加到你的类定义:

method_two = staticmethod(method_two)

或者您可以使用@staticmethod函数装饰器。

其他回答

一旦你了解了描述符系统的基础知识,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>

希望这能解释清楚。

绑定方法=实例方法

解绑定方法=静态方法。

未绑定的方法

未绑定方法是尚未绑定到任何特定类实例的方法。

绑定的方法

绑定方法是绑定到类的特定实例的方法。

正如这里的文档所述,self可以指不同的东西,这取决于函数是绑定的、未绑定的还是静态的。

看看下面的例子:

class MyClass:    
    def some_method(self):
        return self  # For the sake of the example

>>> MyClass().some_method()
<__main__.MyClass object at 0x10e8e43a0># This can also be written as:>>> obj = MyClass()

>>> obj.some_method()
<__main__.MyClass object at 0x10ea12bb0>

# Bound method call:
>>> obj.some_method(10)
TypeError: some_method() takes 1 positional argument but 2 were given

# WHY IT DIDN'T WORK?
# obj.some_method(10) bound call translated as
# MyClass.some_method(obj, 10) unbound method and it takes 2 
# arguments now instead of 1 

# ----- USING THE UNBOUND METHOD ------
>>> MyClass.some_method(10)
10

由于我们在上次调用中没有使用类实例- obj -,我们可以说它看起来像一个静态方法。

如果是这样,MyClass.some_method(10)调用和使用@staticmethod装饰器修饰的静态函数调用之间的区别是什么?

通过使用装饰器,可以显式地明确使用该方法,而无需首先为其创建实例。通常情况下,人们不会期望在没有实例的情况下使用类成员方法,访问它们可能会导致错误,这取决于方法的结构。

此外,通过添加@staticmethod装饰器,我们也可以通过对象进行访问。

class MyClass:    
    def some_method(self):
        return self    

    @staticmethod
    def some_static_method(number):
        return number

>>> MyClass.some_static_method(10)   # without an instance
10
>>> MyClass().some_static_method(10)   # Calling through an instance
10

你不能用实例方法来做上面的例子。你可以在第一个中存活下来(就像我们之前做的那样),但是第二个将被翻译成一个未绑定的调用MyClass。some_method(obj, 10),它将引发TypeError,因为实例方法接受一个参数,而您无意中试图传递两个参数。

然后,你可能会说,“如果我可以通过实例和类MyClass调用静态方法。some_static_method和MyClass()。Some_static_method应该是相同的方法。”是的!

The second one won't work because when you call it like that python internally tries to call it with the a_test instance as the first argument, but your method_two doesn't accept any arguments, so it wont work, you'll get a runtime error. If you want the equivalent of a static method you can use a class method. There's much less need for class methods in Python than static methods in languages like Java or C#. Most often the best solution is to use a method in the module, outside a class definition, those work more efficiently than class methods.

这是一个错误。

首先,第一行应该是这样的(注意大写)

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)