Python 中Super的使用(二)

1.如何使用super

一开始照着示例代码去用super的时候,觉得这个东西很简单,就像其他的单继承机制的语言中的super一样好用,好理解。可是,当你试着混合诸如bound super  object,与unbound super object,metaclass,proxy object,descriptor,MRO,multiple inheritance 这样的概念一起来理解的时候,脑子就会变大,感觉这个东西后面的机制好复杂,一时半会真的很难弄清楚。

看了别人写的一些东西之后,尤其是是看了一个Michele Simionato(估计是Python领域一个大牛级别的人物)的三篇文章之后,对这个super才有了一点了解。附上,三篇文章的链接。

Things to Know About Python Super [1 of 3]

Things to Know About Python Super [2 of 3]

Things to Know About Python Super [3 of 3]

没错,作者从头到尾一直在吐槽,吐槽不同版本关于super的bug,指出一些设计的用例使用错误的情况。这其实,也是一个好的学习方式,学习别人发现的错误,自己尽量避免使用。

在交互终端,输入help(super)可以得到部分关于super的部分信息。

class super(object)
|  super() -> same as super(__class__, <first argument>)
|  super(type) -> unbound super object
|  super(type, obj) -> bound super object; requires isinstance(obj, type)
|  super(type, type2) -> bound super object; requires issubclass(type2, type)。

四中用法,个人感觉,第一种用法最为方便与安全,编译器会根据不同的情况自动的添加两个参数,在完全可以替代第三和第四两种,第二种方法,文档没有说明用例,有人说是用在其他类内做属性用的,暂时不是很理解。

requires isinstance(obj, type),obj,不一定是它的直接实例,子类的实例也可以,只有这样,obj不变,type参数一直变化(顺着type(obj)

.mro的顺序),才可能按照mro的顺序把所有祖先类中的方法调用一遍。

issubclass(type2, type)。type2与type可以一样。这种方法主要是用在调用祖先类的classmethod。

super对象充当的是”代理”对象,它的初始化信息,必然需要传入要代理的对象(type,obj)相关的信息,因为super要计算mro中下个祖先类),type来计算mro,obj作为祖先类方法的self参数。

至于,绑定和非绑定的super对象,可以借用java中的上转型对象来理解。

非绑定,得到的super对象,效果等同于祖先类,绑定的super对象,可以看做派生类的对象往上转型成祖先类的对象,super().属性名,或者super().属性名(),不一定调用的是计算出来的祖先类的方法,它还是在沿着mro搜索,调用搜索到的第一个方法或者属性。至于如何通过返回绑定的方法对象,可能是通过MethodType利用obj,以及搜索到的祖先类的方法对象,直接生成一个绑定的方法对象,(

PyObject* PyMethod_New(PyObject *func, PyObject *self)

Return value: New reference.

Return a new method object, with func being any callable object and self the instance the method should be bound. func is the function that will be called when the method is called. self must not be NULL.

),根据这个文档,我觉得这个推测应该是合理的。

class A():
    def fun(self):
        print("AAAAA")

class B(A):
    pass

class C(B):
    pass
cc = C()
print("Print cc", cc)
fun = super(C, cc).fun
fun()
print("print the object bounded to fun method\n", fun.__self__)

运行结果:

Print cc <__main__.C object at 0x00C0F5B0>
AAAAA
print the object bounded to fun method
 <__main__.C object at 0x00C0F5B0>

2.super的常见问题

1.调用的时候尽量不要使用,super(type(self), self),这会陷入无限递归之中。

2.参数传递问题,重写方法的时候,尽量用*args 与**kwargs

3.祖先类中的一些特性,比如【】运算,比如重写了__getattr__,但是super对象不能使用,毕竟只是个代理对象,不能完全实现祖先对象的全部功能。

时间: 2024-10-25 00:12:52

Python 中Super的使用(二)的相关文章

python中super出现的TypeError: must be type, not classobj 原因及解决

执行一下代码,出现错误,TypeError: must be type, not classobj class A():    def __init__(self):        print("Enter A")        print("Leave A") class B(A):    def __init__(self):        print("Enter B")        super(B, self).__init__()  

python中super().__init__和类名.__init__的区别

super().__init__相对于类名.__init__,在单继承上用法基本无差 但在多继承上有区别,super方法能保证每个父类的方法只会执行一次,而使用类名的方法会导致方法被执行多次 多继承时,使用super方法,对父类的传参数,应该是由于python中super的算法导致的原因,必须把参数全部传递,否则会报错 单继承时,使用super方法,则不能全部传递,只能传父类方法所需的参数,否则会报错 多继承时,相对于使用类名.__init__方法,要把每个父类全部写一遍, 而使用super方法

python中常用的模块二

一.序列化 指:在我们存储数据的时候,需要对我们的对象进行处理,把对象处理成方便存储和传输的数据格式,这个就是序列化, 不同的序列化结果不同,但目的是一样的,都是为了存储和传输. 一,pickle.可以将我们python中的任意数据类型转化成bytes并写入到文件中. 同样也可以把文件中写好的bytes转换回我们的python的数据.这个过程被称为序列化 import pickle class Cat: def __init__(self, name, age): self.name = nam

Python学习-38.Python中的正则表达式(二)

在Python中,正则表达式还有较其他编程语言有特色的地方.那就是支持松散正则表达式了. 在某些情况,正则表达式会写得十分的长,这时候,维护就成问题了.而松散正则表达式就是解决这一问题的办法. 用上一次分组的代码作为例子: 1 import re 2 userinput = input("please input test string:") 3 m = re.match(r'(\d{3,4})-(\d{8})',userinput) 4 if m: 5 print('区号:' + m

python中的文本(二)

本文主要记录和总结本人在阅读<Python标准库>一书,文本这一章节的学习和理解. 其实在Python中,使用文本这样的一些方法是特别常用的一件事.在一般的情况下,都会使用String这样的一个类,应该算是Python中最基础的一个标准类了. 1.3.6 用组解析匹配 match.groups()会按照表达式中与字符串匹配的组的顺序返回一个字符串序列. 使用group()可以得到某个组的匹配. #组解析 text='This is a text -- with punctuation.' pr

python中super关键字的用法

class A: def __init__(self):    print "enter A"    print "leave A" class B(A): def __init__(self):    print "enter B"    A.__init__(self)   # old method    print "leave B" >>> b = B() enter B enter A leave

Python中super()的使用(一)

1.super被引入的初衷 super()通常是被说成super函数,其实它是一个内置的类,是在Python2.2中新增加的,super()实例化一个super对象,这个super对象充当一个访问代理的角色,它帮助子类的对象访问父类,祖父类以及所有祖先类中被方法(尤其是访问那些被子类重写的方法). 在super类没有出现以前,如果要在子类方法中去调用父类的方法,必须显式的使用父类的类名,用一种非绑定的方式去调用.如下例子(所有例子程序均在Python3.4下实现)所示: class A(): d

python中super的使用

转自:http://python.jobbole.com/86787/ super() 的入门使用 在类的继承中,如果重定义某个方法,该方法会覆盖父类的同名方法,但有时,我们希望能同时实现父类的功能,这时,我们就需要调用父类的方法了,可通过使用 super 来实现,比如: class Animal(object): def __init__(self, name): self.name = name def greet(self): print 'Hello, I am %s.' % self.

python中super()方法的解释

在学习 Python 类的时候,会碰见类中有 __init__() 这样一个函数,其实它就是 Python 的构造方法. 构造方法类似于类似 init() 这种初始化方法,来初始化新创建对象的状态,在一个对象创建后会立即调用,比如像实例化一个类: f = FooBar() f.init()#手动初始化 使用构造方法就能让它简化成如下形式:对象创建后自动调用魔法方法__init__(),对对象进行初始化操作 f = FooBar() 在明白了构造方法之后,来点进阶的问题,那就是父类的构造方法中的初