美文网首页程序员
python super()和classmethod

python super()和classmethod

作者: orientlu | 来源:发表于2017-06-16 00:05 被阅读263次

    @(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 (<class '__main__.A'>, 1)
    exec static_foo (1)
    -------
    A exec foo (<__main__.A object at 0x7f6af4c36ac8>, 1)
    exec class_foo (<class '__main__.A'>, 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)
    

    相关文章

      网友评论

        本文标题:python super()和classmethod

        本文链接:https://www.haomeiwen.com/subject/dqhpqxtx.html