当前位置: 移动技术网 > IT编程>脚本编程>Python > python super()和classmethod

python super()和classmethod

2019年04月30日  | 移动技术网IT编程  | 我要评论

小说文学网,中国车震网,养生保健小常识

python super()和classmethod,@(python)。

super(type, obj)

子类中定义了同父类同名的函数后,需要显示调用父类函数时,可以通过 super,也可以直接通过父类名,建议使用 super,比如在初始化函数中调用父类初始化方法,尤其在多重继承的情况下
看看例子:

#!/usr/bin/env python
# coding=utf-8

class a:
    def __init__(self):
        print("enter a")
        super(a, self).__init__()
        print("leave a")

class b:
    def __init__(self):
        print("enter b")
        #super(b, self).__init__()
        print("leave b")

class ca(a):
    def __init__(self):
        print("enter ca")
        super(ca,self).__init__()
        print("leave ca")


class caa(ca, a):
    def __init__(self):
        print("enter caa")
        super(caa,self).__init__()
        print("leave caa")

class cb(b):
    def __init__(self):
        print("enter cb")
        b.__init__(self)
        print("leave cb")


class cbb(cb, b):
    def __init__(self):
        print("enter cbb")
        cb.__init__(self)
        b.__init__(self)
        print("leave cbb")


if __name__ == "__main__":
    print("- new object caa")
    caa = caa()
    print("- new object cbb")
    cbb = cbb()

上述列子中,两组类关系:
caa->ca->a 采用 super 调用父类函数
cbb->cb->b 直接通过父类名调用其行数

对比运行结果

lcd@ubuntu:~/learn/python$ python3 supper_class.py 
- new object caa
enter caa
enter ca
enter a
leave a
leave ca
leave caa
- new object cbb
enter cbb
enter cb
enter b   
leave b
leave cb
enter b   -->重复调用了
leave b
leave cbb

可以看到,使用super, python 不止保证继承时按顺序调用父类初始化,而且保证每一个类不被重复调用。

classsmethod

python 有三种方式定义类方法:
如下面例子类 a 定义的三个方法,
* 常规方式定义了 foo,同对象实例绑定,通过对象调用的时候,会通过隐式 self 参数传递类对象实例子;如果直接通过类调用,需要显示传递类实例;
* @classmethod 方式定义了 class_foo 方法,同类绑定,可以直接通过类名可以直接调用,调用时通过 cls 隐式参数传递类对象。
* @staticmethod 方式定义的方法和普通函数一样,没有绑定对象,没有传递隐式参,可以通过类实例或者类调用。(属于类的函数,但是不需要访问类,通过后续子类覆盖,更好地组织代码)

#!/usr/bin/env python
# coding=utf-8
# by orientlu

class a(object):
    def __init__(self):
        print("a init")
        super().__init__()

    def foo(self, x):
        '''绑定对象'''
        print("a exec foo (%s, %d)" %(self, x))

    @classmethod
    def class_foo(cls, x):
        '''绑定类'''
        print("exec class_foo (%s, %d)" %(cls, x))

    @staticmethod
    def static_foo(x):
        '''没有绑定类,对象'''
        print("exec static_foo (%d)" %(x))

class b(object):
    def foo(self, x):
        '''绑定对象'''
        print("exec foo (%s, %d)" %(self, x))

    @classmethod
    def test_class_foo(cls, x):
        '''绑定类'''
        print("exec test_class_foo -2- (%s, %d)" %(cls, x))

    def test_class_foo(self, x):
        '''后面方法覆盖前面的同名方法'''
        print("exec test_class_foo -1- (%s, %d)" %(self, x))


class aa(a):
    def __init__(self):
        print("aa int")

    def foo(self, x):
        '''覆盖了父类函数'''
        print("aa exec foo (%s, %d)" %(self, x))


class c(aa):
    def __init__(self):
        '''子类定义了方法覆盖了父类,通过super调用到父类函数'''
        super().__init__()
        print("c init")

    def c_fun1(self):
        '''子类没有定义的函数,直接调用父类函数'''
        self.foo(1)

if __name__ == "__main__":

    print("***********************************")
    print("-------")
    a = a()
    a.foo(1)
    a.class_foo(1)
    a.static_foo(1)

    print("-------")
    a.foo(a, 1)
    a.class_foo(1)
    a.static_foo(1)

    print("***********************************")
    b = b()
    b.test_class_foo(1)
    # 以下调用出错,因为classmethod被后面的函数所覆盖了
    #b.test_class_foo(1)
    # 实际存在是后面定义的函数
    b.test_class_foo(b, 1)

    print("***********************************")
    c = c()
    c.c_fun1()

上述代码在 python3 环境下运行的输出 :

***********************************
-------
a init
a exec foo (<__main__.a object at 0x7f6af4c36ac8>, 1)
exec class_foo (, 1)
exec static_foo (1)
-------
a exec foo (<__main__.a object at 0x7f6af4c36ac8>, 1)
exec class_foo (, 1)
exec static_foo (1)
***********************************
exec test_class_foo -1- (<__main__.b object at 0x7f6af4c36b38>, 1)
exec test_class_foo -1- (<__main__.b object at 0x7f6af4c36b38>, 1)
***********************************
aa int
c init
aa exec foo (<__main__.c object at 0x7f6af4c36b70>, 1)

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网