英文原文: https://julien.danjou.info/blog/2013/guide-python-static-class-abstract-methods
翻译出处: http://python.jobbole.com/81595/
一、How methods work in Python
方法就是一个函数、以类的属性被存储。可以通过如下的形式进行声明和访问:
In [1]: class Pizza(object): ...: def __init__(self,size): ...: self.size = size ...: def get_size(self): ...: return self.size ...: In [2]: Pizza.get_size Out[2]: <unbound method Pizza.get_size>
以上的执行结果告诉我们,类Pizza 的属性get_size 是一个未绑定的方法。是什么意思呢? 将在下面的尝试得到答案。
In [3]: Pizza.get_size() --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-3-65dcef60aa06> in <module>() ----> 1 Pizza.get_size() TypeError: unbound method get_size() must be called with Pizza instance as first argument (got nothing instead)
上面的结果告诉我们,想要调用类Pizza的属性get_size,需要一个Pizza 的实例。而从get_size 的方法中也可以看出,第一个参数为一个Pizza的实例
In [4]: Pizza.get_size(Pizza(42)) Out[4]: 42
OK,以上我们可以真正的去使用类Pizza 的属性get_size 了。 而现实生活中,我们通常这样使用:
In [5]: pizza = Pizza(42) # 声明一个Pizza 的实例 In [6]: pizza.get_size() # 通过声明的实例pizza 调用 get_size 方法 Out[6]: 42
二、Static methods
什么时静态方法? 我感觉还是英文原汁原味的更地道
Static methods are a special case of methods. Sometimes, you‘ll write code that belongs to a class, but that doesn‘t use the object itself at all.
静态方法是一类特殊的方法。有时,你想写一些属于类的代码,但又不会去使用和这个类任何相关的东西。
Example:
In [1]: class Pizza(object): ...: @staticmethod ...: def mix_ingredients(x,y): ...: return x + y ...: def cook(self): ...: return self.mix_ingredients(self.cheese,self.vegetables)
在以上的例子中,书写一个非静态的方法同样也可以工作。但是需要对函数mix_ingredients 传递一个self 参数,但这个参数时完全使用不到的。在这里使用到了装饰器 @staticmethod 。它给我们带来了
如下的几点好处:
Python 可以直接使用静态方法,而避免了去实例化一个对象。实例化对象需要消耗资源的,静态方法避免了这一切。
可读性更好了,看到@staticmethod 后,我们就可以知道此方法是对立的,不需要依赖类的实例。
In [3]: Pizza().cook is Pizza().cook Out[3]: False In [4]: Pizza().mix_ingredients is Pizza.mix_ingredients Out[4]: True In [5]: Pizza().mix_ingredients is Pizza().mix_ingredients Out[5]: True In [6]:
从上面的执行结果也可以看出,静态方法即可以被类调用,同样类的实例也可以调用,只是这样会耗用更多的资源而已(看起来不专业。哈哈)
三、Class methods
what are class methods? Class methods are methods that are not bound to an object, but to… a class!
什么时类方法,类方法不是绑定到类的实例上去的,而是绑定到类上去的.
In [1]: class Pizza(object): ...: radius = 42 ...: @classmethod ...: def get_radius(cls): ...: return cls.radius ...: In [2]: Pizza.get_radius Out[2]: <bound method type.get_radius of <class ‘__main__.Pizza‘>> In [3]: Pizza().get_radius Out[3]: <bound method type.get_radius of <class ‘__main__.Pizza‘>> In [4]: Pizza.get_radius() Out[4]: 42
无论什么情况下,get_radius 都是绑定到 类 Pizza 上的。
那这个类方法,到底有什么用呢? 我们在什么时候才会去用它呢? 我想这才是我想去关心的。
(1)、工厂方法:它用于创建类的实例,例如一些预处理。如果使用@staticmethod代替,那我们不得不硬编码Pizza类名在函数中,这使得任何继承Pizza的类都不能使用我们这个工厂方法给它自己用。
class Pizza(object): def __init__(self, ingredients): self.ingredients = ingredients @classmethod def from_fridge(cls, fridge): return cls(fridge.get_cheese() + fridge.get_vegetables())
(2)、调用静态类:如果你把一个静态方法拆分成多个静态方法,除非你使用类方法,否则你还是得硬编码类名。使用这种方式声明方法,Pizza类名明永远都不会在被直接引用,继承和方法覆盖都可以完美的工作。
class Pizza(object): def __init__(self, radius, height): self.radius = radius self.height = height @staticmethod def compute_area(radius): return math.pi * (radius ** 2) @classmethod def compute_volume(cls, height, radius): return height * cls.compute_area(radius) def get_volume(self): return self.compute_volume(self.height, self.radius)