python中的顶层函数 python置顶窗口( 二 )


True
显然 , 该对象仍然有一个引用存在,只要你愿意你还是可以把它找回来 。
在Python3中 , 依附在类上的函数不再当作是未绑定的方法,而是把它当作一个简单地函数,如果有必要它会绑定到一个对象身上去,原则依然和Python2保持一致 , 但是模块更简洁:
Python
class Pizza(object):
...def __init__(self, size):
...self.size = size
...def get_size(self):
...return self.size
...
Pizza.get_size
function Pizza.get_size at 0x7f307f984dd0
静态方法
静态方法是一类特殊的方法,有时你可能需要写一个属于这个类的方法,但是这些代码完全不会使用到实例对象本身,例如:
Python
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不再需要为Pizza对象实例初始化一个绑定方法,绑定方法同样是对象,但是创建他们需要成本,而静态方法就可以避免这些 。
Python
Pizza().cook is Pizza().cook
False
Pizza().mix_ingredients is Pizza.mix_ingredients
True
Pizza().mix_ingredients is Pizza().mix_ingredients
True
可读性更好的代码,看到@staticmethod我们就知道这个方法并不需要依赖对象本身的状态 。
可以在子类中被覆盖 , 如果是把mix_ingredients作为模块的顶层函数,那么继承自Pizza的子类就没法改变pizza的mix_ingredients了如果不覆盖cook的话 。
类方法
话虽如此,什么是类方法呢?类方法不是绑定到对象上 , 而是绑定在类上的方法 。
Python
class Pizza(object):
...radius = 42
...@classmethod
...def get_radius(cls):
...return cls.radius
...
Pizza.get_radius
bound method type.get_radius of class '__main__.Pizza'
Pizza().get_radius
bound method type.get_radius of class '__main__.Pizza'
Pizza.get_radius is Pizza().get_radius
True
Pizza.get_radius()
42
无论你用哪种方式访问这个方法,它总是绑定到了这个类身上 , 它的第一个参数是这个类本身(记?。豪嘁彩嵌韵螅?。
什么时候使用这种方法呢?类方法通常在以下两种场景是非常有用的:
工厂方法:它用于创建类的实例,例如一些预处理 。如果使用@staticmethod代替,那我们不得不硬编码Pizza类名在函数中,这使得任何继承Pizza的类都不能使用我们这个工厂方法给它自己用 。
Python
class Pizza(object):
def __init__(self, ingredients):
self.ingredients = ingredients
@classmethod
def from_fridge(cls, fridge):
return cls(fridge.get_cheese() + fridge.get_vegetables())
调用静态类:如果你把一个静态方法拆分成多个静态方法,除非你使用类方法,否则你还是得硬编码类名 。使用这种方式声明方法,Pizza类名明永远都不会在被直接引用 , 继承和方法覆盖都可以完美的工作 。
Python
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)
抽象方法

推荐阅读