• python中的super怎么用?


    面向对象有这个强大特点和作用, 著名的三大特点:封装, 继承, 多态

    这篇博客写的是super()的简单理解和使用

    今天在读restframework的源码的时候, 发现源码中使用了super, 依以此为入口, 重写了django的as_view()

    在代码执行的过程中既执行了自己的as_view()有执行了django的as_view()

    super()能做什么?

    之前的理解就是, 使用super()可以在子类中调用父类的方法或属性, 可能你会说, 子类本来就可以调用父类中所有非私有的属性或方法,

    而我现在说的是, 当子类中实现了某个方法, 父类中也有这个方法, 当你调用这个方法时, 既想执行子类的又想执行父类的, 在这种情况下

    就可以使用super()

    super()怎么用的

    class A(object):
        def __init__(self, name, age):
            self.name = name
            self.age = age
            print("class A")
    
    
    class B(A):
        def __init__(self, name, age):
            super().__init__(name, age)
            print("class B")
    
    
    class C(B):
        def __init__(self, name, age):
            # 方式一
            super().__init__(name, age)
            # 相当于 super(C, self).__init__(name, age)
            # 默认是从当前类的父类开始往上找__init__()
    
            # 方式二
            # 指定从当前类的某个父类中开始往上找
            super(B, self).__init__(name, age)
            print("class C")
    
    
    c = C("sath", 37)

    定义了三个类, 继承关系为 C 继承 B 继承 A

    定C类进行实例化的时候, 要先执行__init__()[__new__先不说], 

    C类中有__init__()方法, 所以就会执行C类中的__init__()

    但是在C类自己的__init__()中却使用了super(). 并且是   点.__init__()

    这就表示要去执行父类的__init()方法

    super()有两中使用方法

    方法一

    super().__init__()

    默认执行当前类的父类中的方法, 并且将当前类的实例对象self传了进去

    其实就相当于super(C, self).__init__()

    父类中的__init__(self), 中的self就是super()传进去的self, 

    方法二

    super(B, self)>__init__()

    其实和方法一一样, 就是指定的父类不一样了, 你可以指定执行那个父类的__init__()

    前提是必须是当前这个类的父类

    这样执行的执行的话, 参数就会灵活很多

    restframework中对super()的应用实例

    先来看一下源码

    @classmethod
        def as_view(cls, **initkwargs):
            if isinstance(getattr(cls, 'queryset', None), models.query.QuerySet):
                def force_evaluation():
                    raise RuntimeError(
                        'Do not evaluate the `.queryset` attribute directly, '
                        'as the result will be cached and reused between requests. '
                        'Use `.all()` or call `.get_queryset()` instead.'
                    )
                cls.queryset._fetch_all = force_evaluation
    
            view = super(APIView, cls).as_view(**initkwargs)
            super().__init__()
            view.cls = cls
            view.initkwargs = initkwargs
    
            return csrf_exempt(view)

    现在就来看这行代码 view = super(APIView, cls).as_view(**initkwargs)

    写了一个CBV, 视图继承了APIView

    当请求进来之后, 进行路由匹配然后调用视图函数, CBV会执行as_view()

    我是的路由是这样式的

    url(r'^auth/', views.AuthView.as_view())

    AuthView就是视图类, 继承了APIView, 当调用as_view()时, 先去自己的类中找as_view, 发现没有, 然后去父类中找

    上面的as_view()代码就是APIViwe类中的as_view(), APIView其实也继承了View

    发现as_view()是一个类方法, 怪不得在路由中使用类去调用呢, 这个样就能得到视图类的类空间了

    因为在View中需要用视图类, 然后对视图类进行了实例化, 通过这个实例在加上反射获取和用户请求方式同名的函数并执行

    上面就是super()在restframework中的应用

  • 相关阅读:
    资源限制
    垃圾收集器
    GC日志
    happens-before
    maven相互依赖导致无法编译成功
    LVM-逻辑卷常用命令和示意图
    取消RAID5
    扩展RAID5的容量
    模拟RAID5损坏
    创建RAID5
  • 原文地址:https://www.cnblogs.com/594504110python/p/10181538.html
Copyright © 2020-2023  润新知