• Python实例方法、类方法与静态方法


    在 Python 中,实例方法(instance method),类方法(class method)与静态方法(static method)经常容易混淆。本文通过代码例子来说明它们的区别。

    实例方法

    Python 的实例方法用得最多,也最常见。我们先来看 Python 的实例方法。

    class Kls(object):
        def __init__(self, data):
            self.data = data
    
        def printd(self):
            print(self.data)
    
    
    ik1 = Kls('leo')
    ik2 = Kls('lee')
    
    ik1.printd()
    ik2.printd()

     输出:

    leo
    lee

    上述例子中,printd 为一个实例方法。实例方法第一个参数为self,当使用ik1.printd()调用实例方法时,实例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 并不需要传递类或者实例,因此,既可以使用类也可以使用实例来调用静态方法

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

    我们用代码说明实例方法,类方法,静态方法的区别。注意下述代码中方法fooclass_foostatic_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时只需要一个参数。fooik进行了绑定,因此,当我们打印ik.foo时,会看到以下输出:

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

    当调用ik.class_foo时,由于class_foo是类方法,因此,class_fooKls进行了绑定(而不是跟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>

    概括来说,是否与类或者实例进行绑定,这就是实例方法,类方法,静态方法的区别。

  • 相关阅读:
    C# 实现 Aop [Emit动态生成代理类方式]
    分享一些最近在看的电子书
    Can't connect to your phone. Disconnect it, restart it, then try connecting again
    07,Windows Phone后台代理
    .NET 性能测试工具 性能计数器
    windows 8 metro 开发学习资源链接
    08,Windows Phone 本地存储
    06,Windows Phone 8程序的生命周期
    .NET 性能测试工具 事件跟踪器(ETW)
    LitJSONjson 和net 的完美组合用法
  • 原文地址:https://www.cnblogs.com/sunny0824/p/13676192.html
Copyright © 2020-2023  润新知