Discuss / Python / APIError中super(APIError, self).__init__(message)是否有必要?

APIError中super(APIError, self).__init__(message)是否有必要?

Topic source

郭子淳gzc

#1 Created at ... [Delete] [Delete and Lock User]

廖老师,您好!我在编写APIError类时与您的源代码有点出入,就是我没有写 super(APIError, self).init(message),不过raise起来都正常

您的源码

class APIError(Exception):
    '''
    the base APIError which contains error(required), data(optional) and message(optional).
    '''
    def __init__(self, error, data='', message=''):
        super(APIError, self).__init__(message)
        self.error = error
        self.data = data
        self.message = message

之后我查阅了些资料

David Beazley的Python Cookbook一书中的解释是

''' If you are going to define a new exception that overrides the init() method of Exception, make sure you always call Exception.init()with all of the passed arguments.

This might look a little weird, but the default behavior of Exceptionis to accept all arguments passed and to store them in the .args attribute as a tuple. Various other libraries and parts of Python expect all exceptions to have the .args attribute, so if you skip this step, you might find that your new exception doesn’t behave quite right in certain contexts. ''' 也就是怕其他代码用到exception的args属性

之后我编了一小段代码测试了一下

class MyError(Exception):
    def __init__(self, message, hh):
        self.message = message
        self.hh = hh
I=MyError('my bad','ff')
print(dir(I))

发现MyError实例有args属性,并没有出现Python Cookbook一书中所说的状况。

那么,super(APIError, self).init(message)存在的意义是什么呢?

期待廖老师的回复,谢谢!!

郭子淳gzc

#2 Created at ... [Delete] [Delete and Lock User]

先自问自答下

class APIError(Exception):
    def __init__(self, error, data='', message=''):
        pass

class APIValueError(APIError):
    def __init__(self, field, message='kk'):
        super().__init__('Value: invalid', field, message)

a=APIError('Error', 'name','haha')
print(a)
print(a.args)

b=APIValueError('name', 'haha')
print(b)
print(b.args)

结果 C:\Python34\python.exe C:/Users/gzc/PycharmProjects/untitled/api_error.py ('Error', 'name', 'haha') ('Error', 'name', 'haha') ('name', 'haha') ('name', 'haha')

Process finished with exit code 0

class APIError(Exception):
    def __init__(self, error, data='', message=''):
        super().__init__(error, data, message)

class APIValueError(APIError):
    def __init__(self, field, message='kk'):
        super().__init__('Value: invalid', field, message)

a=APIError('Error', 'name','haha')
print(a)
print(a.args)

b=APIValueError('name', 'haha')
print(b)
print(b.args)

结果 C:\Python34\python.exe C:/Users/gzc/PycharmProjects/untitled/api_error.py ('Error', 'name', 'haha') ('Error', 'name', 'haha') ('Value: invalid', 'name', 'haha') ('Value: invalid', 'name', 'haha')

Process finished with exit code 0

无法找到Exception的源码,所以大胆猜测:

a. Exception的init中有将init(self, )中参数存入args的操作 b. Exception中有将APIError( ) APIValueError( )参数自动存入args的方法 c. a中的操作结果会覆盖b中方法的结果

这些也就APIError中super(APIError, self).init(message)存在的必要

不知道这样理解是否正确,期待廖老师回复,谢谢。

PS:有方法可以看到 python built-in module 的源码吗? 这样这可以看到 Exception类的源码了。

sly759

#3 Created at ... [Delete] [Delete and Lock User]

debug 跑的时候就可以进去看到了


  • 1

Reply