最近在python的代码中,使用装饰器的功能以后,遇到了一个有意思的错误,记录下与大家分享一下,希望大家不会犯同样的错误。

大致代码如下:

fn_list = {}def decrator(fn):fn_list[fn.__name__] = fn@decrator
def print_test(index):print(index)return 'success'@decrator
class TestClass(object):def __init__(self):super(TestClass, self).__init__()print("finish init func")ouput_result = fn_list['print_test']('1234')
print(ouput_result)
test_instance = fn_list['TestClass']()

运行的时候,在创建TestClass的对象的时候,报错如下:

in __init__

super() argument 1 must be type, not None

检查代码的时候,先查看了fn_list[‘TestClass’]确实指向了对应的类,不是None。

在__init__函数中,输出self,发现是对应类的对象,然后输出TestClass,发现是None。

但是调用同样用装饰器装饰的print_test没有发生问题。

其实问题就出在装饰器函数上,装饰器的作用其实就是在对象(例如函数,类)定义的时候 改变这个对象后续调用过程中的行为,又不改变这个对象内部代码。

以装饰某一个函数为例子,比如装饰器是decrator函数,装饰在print_test函数,那么在函数print_test定义的时候(此时函数print_test不被调用),首先调用了一次print_test = decorator(print_test),对于print_test的函数进行定义。那么,此时指向print_test对象的指针,已经被替换成了指向decorator(print_test)的指针。这里需要注意的是,此时print_test函数已经被覆盖成了新的函数decorator(print_test),即调用decorator函数,并将print_test作为参数传入,得到的返回值,即print_test = decorator(print_test)。

详细的了解了装饰器的工作机制,就不难理解上述问题的出现了。

首先,为什么调用print_test会有正确的结果,这个是因为在装饰器中,保存了print_test的调用入口,并且是通过这个入口调用的(ouput_result = fn_list['print_test']('1234')

)。但是,如果直接调用print_test('1234'),会出错。

其次,创建对象为什么会报错。这个是因为,创建对象调用,从保留的正确入口进行了调用(fn_list['TestClass']()),但是,在类初始化的__init__函数中,调用super的时候,是用的函数名称TestClass进行直接调用的,这个时候,其实TestClass已经在定义的时候,因为调用TestClass = decorator(TestClass) 而变成了None(decorator没有显式指定返回值,所以为默认返回值None),这样就产生了最终的这个错综离奇的报错。

太长不看系列:

装饰器原理,对于用装饰器修饰的函数定义:

@decorator

def func():

pass

在定义时,先调用了func = decorator(func),对于func进行了定义的修改。

由于decorator在我的代码中没有显式定义返回值,则使用的默认返回值None。

于是所有被装饰的函数和类,都被设置为None的变量。

修改办法

def decrator(fn):fn_list[fn.__name__] = fnreturn fn

一次错综离奇的super调用的None参数super() argument 1 must be type, not None相关推荐

  1. java super父类的父类_java super关键字,super访问父类成员详解

    之情给大家介绍了一下super调用父类构造方法方面的内容,下面要接着给大家介绍的就是super访问父类成员方面的内容,分别对super调用成员属性以及super调用成员方法做了详细介绍. 在子类的成员 ...

  2. python3 推荐使用super调用base类方法

    from:https://python3-cookbook.readthedocs.io/zh_CN/latest/c08/p07_calling_method_on_parent_class.htm ...

  3. 【Kotlin】Kotlin 类的继承 三 ( super 关键字使用 | super@ 外部调用父类方法 | 子类选择性调用 父类 / 接口 方法 super )

    文章目录 I . 子类调用父类总结 II . 子类调用父类方法 ( super ) III . 子类内部类调用父类方法 ( super@ ) IV . 子类选择调用不同的 父类 / 接口方法 ( su ...

  4. 子类super调用父类函数,该函数中调用的函数是父类还子类呢

    如图所示: 子类对象通过super()函数调用父类的run函数,然后直接调用了子类的demo函数,而没有调用父类的函数:猜想通过super调用父类,但self仍然代表是子类本身: 再看一例: 从这里说 ...

  5. python实现父类继承_Python多继承用super调用父类方法?

    python的super传递:python多重继承的super调用父类的兄弟类 - 30天尝试新事情​30daydo.com 如果要调用父类的父类,可以直接用类名(类名需要在mro里面) # 多重继承 ...

  6. 在子类中调用父类的方法super

    1.没有super之前,在子类里面需要父类里面的逻辑,但是我们是通过派生(自己定义了一个init,增加了一条line) class vehichle:#定义一个交通工具的类Country=" ...

  7. python super 多重继承_解决python super()调用多重继承函数的问题

    当类间继承关系很简单时,super()的使用很简单. class A(object): def __init__(self): print('a') class B(A): def __init__( ...

  8. 什么是super?如何使用super调用超类构造函数?

    从之前的文章中分享过的一些知识,从Box派生的类并没有体现出它们的实际上是多么有效和强大.例如,BoxWeight构造函数明确的初始化了Box( )的width.height和depth成员. 这些重 ...

  9. java super父类方法_java super关键字,super调用父类构造方法详解

    因为子类不可以继承父类的构造方法,所以,想要调用父类的构造方法的话,那么就可以使用得到super关键字下面的话就来对这个方面做一下详细的讲解. super关键字能够用来访问父类的构造方法.普通方法和属 ...

  10. Java super关键字:super调用父类的构造方法、利用super访问父类成员

    由于子类不能继承父类的构造方法,因此,要调用父类的构造方法,必须在子类的构造方法体的第一行使用 super() 方法.该方法会调用父类相应的构造方法来完成子类对象的初始化工作. 在以下情况下需要使用 ...

最新文章

  1. 大成郡亮相乐居春季房展精装户型16500元
  2. nboot,eboot和uboot
  3. UNITY ET 框架
  4. Excel是计算机应用软件,计算机应用软件Excel 2003教学计划
  5. a标签连接空标签的方法
  6. C4C里产品主数据和销售组织数据维护的相互作用和相互影响
  7. 中国这10条逆天公路,火爆外网,你都认识多少?
  8. php 判断ajax访问,PHP里判断是否Ajax请求
  9. vmware虚拟机里的服务器自动关闭,让VirtualBox虚拟机在主机关闭时自动关闭或保存状态VBoxVmService...
  10. Star Schema完全参考手册读书笔记三
  11. delphi 检测网络是否连通_WebRTC:连接建立过程的网络穿透
  12. html flex上下居中,CSS3 Flex实现元素的水平居中和垂直居中
  13. 《硅谷钢铁侠》与埃隆.马斯克
  14. 树莓派+aria2+yaaw搭建下载机
  15. PSP开发简明教程(2)
  16. c++调用静态函数的方法
  17. Android直播软件开发中接入腾讯IM大概流程是怎样的
  18. python数据结构之单链表
  19. 二维数组名取地址加一
  20. Android 学习笔记-时间_日期_记时器_倒计时器

热门文章

  1. 计算机桌面个性化怎样设置方法,桌面文件夹图标个性化【设置方法】
  2. 汽车金融大变局:狂奔过后,一地鸡毛
  3. python学而思和猿辅导哪个好_学而思和猿辅导哪个好,说说我的评价
  4. Rundll32.exe的小理解
  5. 子目录和子域名哪个好?子目录和子域名如何利用seo优化?
  6. Flixel横板游戏制作教程(十一)—JetPack(飞行背包)
  7. lstm优点缺点_LSTM和易失性时间序列:优点和缺点
  8. 宠物动物有什么计算机专业岗位,宠物医院前台岗位职责
  9. javaScript常用案例
  10. python获取北京时间_python获取标准北京时间的方法