python super()和classmethod
程序员文章站
2023-11-19 16:25:16
python super()和classmethod,@(python)。
super(type, obj)
子类中定义了同父类同名的函数后,需要显示调用父类函数时,可以通过...
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)