Python:普通成员函数、类成员函数、静态函数

Python:普通成员函数、类成员函数、静态函数

Python 中的类也是一个普通对象,如果需要直接使用这个类,例如将类作为参数传递到其他函数中,又希望在实例化这个类之前就能提供某些功能,那么最简单的办法就是使用 classmethod 和 staticmethod。这两者的区别在于在存在类的继承的情况下对多态的支持不同。所以本质上来说,面向对象中实例方法有哪些作用,classmethod 也就有哪些作用,只是这个面向的“对象”是类本身而已。C++ 中的 static method 只有命名空间的作用,而 Python 中不管是 classmethod 还是 staticmethod 都有 OOP(面向对象的程序设计,Object Oriented Programming)、多态上的意义。

class Foo:
    def plain_func(self): # 普通方法
        print("plain_func")

    @classmethod
    def class_func(cls):  # 类方法
        print("class_func")

    @staticmethod
    def static_func():    # 静态方法
        print("static_func")

# 必须实例化进行调用
foo = Foo()
foo.plain_func()
# 可通过类名进行调用
Foo.class_func()
Foo.static_func()

1、普通成员函数

普通成员函数是最一般的方法,从调用方式来看,普通函数只能在类的实例中被调用,而后两者可以通过类名进行调用。

class Kls(object):
    def __init__(self, data):
        self.data = data
    def printd(self):
        print(self.data)
ik1 = Kls('arun')
ik2 = Kls('seema')
>>> ik1.printd()
arun
>>> ik2.printd()
seema

 

2、类成员函数(classmethod)

classmethod 增加了一个 cls 参数,它引用了一个类实例。cls 类似于类中其他函数的 self 参数,例如 __init__(self),只不过 self 代表创建的实例对象,而 cls 代表类本身。classmethod 可以用于写一个只在类中运行而不在实例中运行的方法,直接通过类进行调用不管这个方法是从实例调用还是从类调用,它都用第一个参数把类传递过来对类的用户可见的功能可使用 classmethod。

好处:

  • 方法可以判断出自己是通过基类被调用,还是通过某个子类被调用;
  • 通过子类调用时,方法可以返回子类的实例而非基类的实例;
  • 通过子类调用时,方法可以调用子类的其他 classmethod。
# 扩散了类代码的关系到类定义的外面,以后难以维护代码
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


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) # 从实例调用
2


# 使用 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() # 从实例调用
2
>>> print Kls.get_no_of_instance() # 从类调用
2

 

3、静态函数(staticmethod)

staticmethod 用于跟类有关系的功能但在运行时又不需要实例和类参与的情况,比如更改环境变量或者修改其他类的属性等。在通过类调用时,staticmethod 与 classmethod 对于调用者来说是不可区分的。

好处:

  • 调用时返回的是一个真正的函数,而且每次调用时返回同一个实例(classmethod 则会对基类和子类返回不同的 bound method 实例)
# 同样会扩散类内部的代码,造成维护困难
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()
Reset done for: 12
>>> ik1.set_db()
DB connection made for: 12


# 使用 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()
Reset done for: 12
>>> ik1.set_db()
DB connection made for: 12

 

classmethod 与 staticmethod

这两个方法的用法是类似的,在大多数情况下,classmethod 也可以通过 staticmethod 代替,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()
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 中的 classmethod 和 staticmethod 有什么具体用途?

  • 8
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值