python实例方法(instance method)类方法(class method)和静态方法(static method)区分


声明:本文章参考: https://blog.csdn.net/lihao21/article/details/79762681

实例方法

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

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


ik1 = Kls('leo')
ik2 = Kls('lee')

ik1.myPrint()
ik2.myPrint()

<<<leo
<<<lee

上述例子中,myPrint为一个实例方法。实例方法第一个参数为self,当使用ik1.myPrint()调用实例方法时,实例ik1会传递给self参数,这样self参数就可以引用当前正在调用实例方法的实例。利用实例方法的这个特性,上述代码正确输出了两个实例的成员数据.。

类方法

python中的类方法需要@classmethod来定义,如下:

class Kls(object):
    num_inst = 0

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

    @classmethod
    def get_no_of_instance(cls):
        return cls.num_inst


ik1 = Kls()
ik2 = Kls()

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


<<<2
<<<2

在上述例子中,我们需要统计类Kls实例的个数,因此定义了一个类变量num_inst来存放实例个数。通过装饰器@classmethod的使用,方法get_no_of_instance被定义成一个类方法。在调用类方法时,Python 会将类(class Kls)传递给cls,这样在get_no_of_instance内部就可以引用类变量num_inst。
由于在调用类方法时,只需要将类型本身传递给类方法,因此,既可以通过类也可以通过实例来调用类方法。

静态方法

在开发中,我们常常需要定义一些方法,这些方法跟类有关,但在实现时并不需要引用类或者实例,例如,设置环境变量,修改另一个类的变量,等。这个时候,我们可以使用静态方法。
Python 使用装饰器@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: %s' % self.data)

    def set_db(self):
        if self.checkind():
            print('DB connection made for: %s' % self.data)


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


<<<Reset done for: 24 
<<<DB connection made for: 24

在代码中,我们定义了一个全局变量IND,由于IND跟类Kls相关,所以我们将方法checkind放置在类Kls中定义。方法checkind只需检查IND的值,而不需要引用类或者实例,因此,我们将方法checkind定义为静态方法。
对于静态方法,Python 并不需要传递类或者实例,因此,既可以使用类也可以使用实例来调用静态方法。

实例方法,类方法与静态方法的区别

我们用代码说明实例方法,类方法,静态方法的区别。注意下述代码中方法foo,class_foo,static_foo的定义以及使用。

class Kls(object):
    def foo(self, x):
        print('executing foo(%s,%s)' % (self, x))

    @classmethod
    def class_foo(cls,x):
        print('executing class_foo(%s,%s)' % (cls,x))

    @staticmethod
    def static_foo(x):
        print('executing static_foo(%s)' % x)


ik = Kls()

# 实例方法
ik.foo(1)
print(ik.foo)
print('==========================================')

# 类方法
ik.class_foo(1)
Kls.class_foo(1)
print(ik.class_foo)
print('==========================================')

# 静态方法
ik.static_foo(1)
Kls.static_foo('hi')
print(ik.static_foo)

输出

executing foo(<__main__.Kls object at 0x0551E190>,1)
<bound method Kls.foo of <__main__.Kls object at 0x0551E190>>
==========================================
executing class_foo(<class '__main__.Kls'>,1)
executing class_foo(<class '__main__.Kls'>,1)
<bound method type.class_foo of <class '__main__.Kls'>>
==========================================
executing static_foo(1)
executing static_foo(hi)
<function static_foo at 0x055238B0>

对于实例方法,调用时会把实例ik作为第一个参数传递给self参数。因此,调用ik.foo(1)时输出了实例ik的地址。

对于类方法,调用时会把类Kls作为第一个参数传递给cls参数。因此,调用ik.class_foo(1)时输出了Kls类型信息。
前面提到,可以通过类也可以通过实例来调用类方法,在上述代码中,我们再一次进行了验证。

对于静态方法,调用时并不需要传递类或者实例。其实,静态方法很像我们在类外定义的函数,只不过静态方法可以通过类或者实例来调用而已。

值得注意的是,在上述例子中,foo只是个函数,但当调用ik.foo的时候我们得到的是一个已经跟实例ik绑定的函数。调用foo时需要两个参数,但调用ik.foo时只需要一个参数。foo跟ik进行了绑定,因此,当我们打印ik.foo时,会看到以下输出:

<bound method Kls.foo of <__main__.Kls object at 0x0551E190>>

当调用ik.class_foo时,由于class_foo是类方法,因此,class_foo跟Kls进行了绑定(而不是跟ik绑定)。当我们打印ik.class_foo时,输出:

<bound method type.class_foo of <class '__main__.Kls'>>

当调用ik.static_foo时,静态方法并不会与类或者实例绑定,因此,打印ik.static_foo(或者Kls.static_foo)时输出:

<function static_foo at 0x055238B0>

因此区别于实例方法和类方法,静态方法即不能使用实例(self)的数据,也不能使用类(cls)的数据
概括来说,是否与类或者实例进行绑定,这就是实例方法,类方法,静态方法的区别。

场景使用说明

参考https://blog.csdn.net/caroline_wendy/article/details/23383995
成员函数(实例方法):解决和对象绑定的问题
类函数(@classmethod类方法):关注类中的共同管理的数据,也可实现类中调用方法,如构造重载
静态函数(@staticmethod静态方法):处理与这个类逻辑相关的业务,如验证数据等
举例如下:(实现日期的输出显示、数据转换、数据验证)

# -*- coding: utf-8 -*-
 
#eclipse pydev, python 3.3
#by C.L.Wang
 
class Date(object):
 
    day = 0
    month = 0
    year = 0
 
    def __init__(self, day=0, month=0, year=0):
        self.day = day
        self.month = month
        self.year = year
        
    def display(self):
        return "{0}*{1}*{2}".format(self.day, self.month, self.year)
    
    @classmethod
    def from_string(cls, date_as_string):
        day, month, year = map(int, date_as_string.split('-'))
        date1 = cls(day, month, year)
        return date1
    
    @staticmethod
    def is_date_valid(date_as_string):
        day, month, year = map(int, date_as_string.split('-'))
        return day <= 31 and month <= 12 and year <= 3999
    
date1 = Date('12', '11', '2014')
date2 = Date.from_string('11-13-2014')
print(date1.display())
print(date2.display())
print(date2.is_date_valid('11-13-2014'))
print(Date.is_date_valid('11-13-2014'))

<<<12*11*2014
<<<11*13*2014
<<<False
<<<False
  • 4
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值