python中类方法的两大装饰器

在本文中,我将试图解释什么是staticmethod和classmethod,和什么区别它们之间。staticmethod并且classmethod都使用装饰器将方法定义为staticmethod或classmethod

静态类和方法

在class中大多数的方法是实例方法,即将实例作为第一个参数传递给方法。

下面是一个基础类的实例:

class Kls(object):
    def __init__(self, data):
        self.data = data

    def printd(self):
        print(self.data)

ik1 = Kls('arun')
ik2 = Kls('seema')

ik1.printd()
ik2.printd()

输出结果:

arun
seema

python中类方法的两大装饰器_第1张图片
然后看一下代码和示例图片:

  • 1,2参数传递给方法.
  • 3 self参数指向当前实例自身.
  • 4 我们不需要传递实例自身给方法,

Python解释器自己会做这些操作的.如果现在我们想写一些仅仅与类交互而不是和实例交互的方法会怎么样呢? 我们可以在类外面写一个简单的方法来做这些,但是这样做就扩散了类代码的关系到类定义的外面. 如果像下面这样写就会导致以后代码维护的困难:

def get_no_of_instances(cls_obj):
    return cls_obj.no_inst
class Kls(object):
    no_inst = 0
    def __init__(self):
        Kls.no_inst = Kls.no_inst + 1
ik1 = Kls()
ik2 = Kls()
print(get_no_of_instances(Kls))

输出:

2

@classmethod

简言之,该装饰器修饰的方法是对类中的元素进行操作。而不是对实例进行操作的。

如果我们想获得实例的数量,我们所要做的就是如下所示:

def iget_no_of_instance(ins_obj):
    return ins_obj.__class__.no_inst

class Kls(object):
    no_inst = 0

    def __init__(self):
    Kls.no_inst = Kls.no_inst + 1

ik1 = Kls()
ik2 = Kls()
print iget_no_of_instance(ik1)

使用@classmethod之后的代码

class Kls(object):
    no_inst = 0

    def __init__(self):
        Kls.no_inst = Kls.no_inst + 1

    @classmethod
    def get_no_of_instance(cls_obj):
        return cls_obj.no_inst

ik1 = Kls()
ik2 = Kls()

print ik1.get_no_of_instance()
print Kls.get_no_of_instance()

好处:
无论我们从实例还是类中调用方法,它将该类作为第一个参数传递

@staticmethod

通常有一些与类相关的功能,但不需要类或任何实例来做一些工作。也许像设置环境变量,改变另一个类中的属性等等。在这种情况下,我们也可以使用一个函数,但是这样做也会扩展相关的代码,以后可能导致维护问题

IND = 'ON'

def checkind():
    return (IND == 'ON')

class Kls(object):
    def __init__(self,data):
        self.data = data

    def do_reset(self):
        if checkind():
            print('Reset done for:', self.data)

    def set_db(self):
        if checkind():
            self.db = 'new db connection'
            print('DB connection made for:',self.data)

ik1 = Kls(12)
ik1.do_reset()
ik1.set_db()

使用@staticmethod的代码

IND = 'ON'

class Kls(object):
    def __init__(self, data):
        self.data = data

    @staticmethod
    def checkind():
        return (IND == 'ON')

    def do_reset(self):
        if self.checkind():
            print('Reset done for:', self.data)

    def set_db(self):
        if self.checkind():
            self.db = 'New db connection'
        print('DB connection made for: ', self.data)

ik1 = Kls(12)
ik1.do_reset()
ik1.set_db()

@staticmethod 和 @classmethod 的不同

class Kls(object):
    def __init__(self, data):
        self.data = data

    def printd(self):
        print(self.data)

    @staticmethod
        def smethod(*arg):
            print('Static:', arg)

    @classmethod
        def cmethod(*arg):
            print('Class:', arg)
>>> ik = Kls(23)
>>> ik.printd()     # 实例调用其属性或者方法
23
>>> ik.smethod()
Static: ()
>>> ik.cmethod()
Class: (<class '__main__.Kls'>,)
>>> Kls.printd()     #printd()是实例方法,故使用类直接调用会报错
TypeError: unbound method printd() must be called with Kls instance as first argument (got nothing instead)
>>> Kls.smethod()    # 静态类方法,没有传递任何参数
Static: ()
>>> Kls.cmethod()     # 类方法,第一个参数是该类
Class: (<class '__main__.Kls'>,)

python中类方法的两大装饰器_第2张图片

总结:
@staticmethod

  • 在调用时,不需要实例化(创建类的对象),直接使用类名调用。
  • 可以不传递参数

@classmethod

  • 第一个参数传递的必须是类
  • 对类中的对象操作。

参考链接

http://pythoncentral.io/difference-between-staticmethod-and-classmethod-in-python/

你可能感兴趣的:(……【python】)