Python 中的方法、静态方法(static method)和类方法(class method)

英文原文: 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)
时间: 2024-11-05 03:39:20

Python 中的方法、静态方法(static method)和类方法(class method)的相关文章

Java中主类中定义方法加static和不加static的区别

Java中主类中定义方法加static和不加static的区别(前者可以省略类名直接在主方法调用,后者必须先实例化后用实例调用) 知识点:1.Getter and Setter 的应用 2.局部变量与成员变量(也可叫做全局变量) 3.Static关键字的用法 a.成员变量被static修饰后的所有类的共享属性 b.方法被static修饰之后,在本类内调用的类名省略问题;以及不用Static,即使在本类内也必须先实例化 4.This关键字的用法 this:是当前类的对象引用.简单的记,它就代表当前

Python中strip方法的妙用

[开胃小菜] 当提到python中strip方法,想必凡接触过python的同行都知道它主要用来切除空格.有以下两种方法来实现. 方法一:用内置函数 #<python> if __name__ == '__main__': str = ' Hello world ' print '[%s]' %str.strip() #</python> 方法二:调用string模块中方法 #<python> import string if __name__ == '__main__

Python中__init__方法

注意1.__init__并不相当于C#中的构造函数,执行它的时候,实例已构造出来了. 1 2 3 4 5 class A(object):     def __init__(self,name):         self.name=name     def getName(self):         return 'A '+self.name 当我们执行 1 a=A('hello') 时,可以理解为 1 2 a=object.__new__(A) A.__init__(a,'hello')

python 中特殊方法简写方式

##python 中特殊方法简写方式 class Test: __call__ = lambda *args: args[1] * 2 #这里需要注意lambda的参数 会默认将实例self 加进去 __str__ = lambda self: 'that`s useful...%s' % self.__class__.__name__ t = Test() print(t) print(t(10)) 原文地址:https://www.cnblogs.com/alplf123/p/1029388

Python中__new__()方法的使用和实例化

new()是在新式类中新出现的方法,它作用在构造方法init()建造实例之前,可以这么理解,在Python 中存在于类里面的构造方法init()负责将类的实例化,而在init()调用之前,new()决定是否要使用该init()方法,因为new()可以调用其他类的构造方法或者直接返回别的对象来作为本类 的实例. 如果将类比喻为工厂,那么init()方法则是该工厂的生产工人,init()方法接受的初始化参 数则是生产所需原料,init()方法会按照方法中的语句负责将原料加工成实例以供工厂出货.而 n

Java基础(42):Java中主类中定义方法加static和不加static的区别(前者可以省略类名直接在祝方法调用,后者必须先实例化后用实例调用)

1 package lsg.ap.april4th2; 2 /* 3 知识点:1.Getter and Setter 的应用 4 2.局部变量与成员变量(也可叫做全局变量) 5 3.Static关键字的用法 6 a.成员变量被static修饰后的所有类的共享属性 7 b.方法被static修饰之后,在本类内调用的类名省略问题;以及不用Static,即使在本类内也必须先实例化 8 4.This关键字的用法 9 this:是当前类的对象引用.简单的记,它就代表当前类的一个对象. 10 11 注意:谁

python中defaultdict方法的使用

默认值可以很方便 众所周知,在Python中如果访问字典中不存在的键,会引发KeyError异常(JavaScript中如果对象中不存在某个属性,则返回undefined).但是有时候,字典中的每个键都存在默认值是非常方便的.例如下面的例子: strings = ('puppy', 'kitten', 'puppy', 'puppy', 'weasel', 'puppy', 'kitten', 'puppy') counts = {} for kw in strings: counts[kw]

python中__unicode__方法的使用

python中__unicode__(self):方法: __unicode()方法告诉python如何实现对象的unicode表示.如以下数据模型:class Host(models.Model):    id = models.AutoField(primary_key=True)    ip = models.CharField('IP地址', max_length=16, blank=True, null=True)    name = models.CharField('主机名称',

[小知识]Python中__call__方法 @ Python

python中的__call__方法可以把class当做函数调用.例程如下: #coding=utf-8 class A(object): def __init__(self, x): self.x = x def __call__(self, y): return self.x * y C = A(10) #C这个instance可以当做函数来调用 print C(5) # 50