Python-built-in method supplement, exception handling

table of Contents

One, new method

Two, __len__ method

Three, __eq__ method

Four, __hash__ method

 Five, __eq__ and __hash__ application

Official explanation

Six, exception handling

1. What is an exception

2. Types of abnormalities

3. Exception handling

4. The significance of exception handling

 5. Catch exceptions

5.1 Catch all exceptions

5.2 Catch the specified exception

5.3 Catching multiple exceptions

5.4 Else in exception

5.5 finally in exception

5.6 Raise actively triggers exceptions

5.7 Use the traceback module to view exceptions

6, assert

7, custom exception

7.1 Two ways to customize exceptions

7.2. How to manually throw an exception: raise

7.3. Catch exceptions manually thrown by users

8. When to use the exception


One, new method

__init__()Is the initialization method, the __new__()method is the construction method, to create a new object

When the object is __init__()instantiated, the __new__()method is called before the initialization is called

__new__()Must have a return value, return the instantiated instance

def __new__(cls, *args, **kwargs):

example

# -*- coding: utf-8 -*-

class Foo(object):
    def __init__(self,name):
        self.name=name

    def __new__(cls, *args, **kwargs):
        obj=super(Foo, cls).__new__(cls) #利用object的__new__方法创建新的空对象
        obj.__init__(*args,**kwargs)
        return obj

f=Foo('nike') 
print(f.name)
print(f.__dict__)

Two, __len__ method

If a class behaves like a list, to get how many elements there are, you have to use  __len__() functions.

Called by len(object)

class Student():
    def __init__(self,*args):
        self.names = args
​
    def __len__(self):
        return len(self.names)
​
s = Student("nick","jack","pony")
print(len(s)) #用len直接调用__len__方法
from collections import namedtuple

Card = namedtuple("Card",["rank","suit"]) #这里相当于创建了一个名为Card的类,后面的列表里是类的类属性,没有函数属性
                                          #
class FranchDeck:
    ranks = [str(n) for n in range(2,11)] + list('JQKA')
    suits = ['红心','方板','梅花','黑桃']

    def __init__(self):
        self._cards = [(rank,suit) for rank in FranchDeck.ranks for suit in FranchDeck.suits] #这里是一个列表生成式,
        #将第一个for循环里的值赋值给rank,将第二个for循环里的值赋给suit,这个类只要一实例化就自动生成了一副除了没有大小王的牌
        #每张牌都是用元组来表示的
    def __len__(self):
        return len(self._cards) # choice()方法依赖__len__(self)

    def __getitem__(self, item):
        return self._cards[item]

    def __setitem__(self, key, value):
        self._cards[key] = value

deck = FranchDeck()  #这里相当于创建了一副牌
print(deck[0]) #打印第一张牌
print(deck[2:5]) #打印第2-4张牌
from random import choice,shuffle
print(choice(deck))  #随机抽取一张牌
shuffle(deck) #洗牌
print("洗牌后的第一张",deck[0]) #打印第一张牌

Three, __eq__method

__eq__(slef,other) , To determine whether the self object is equal to the other object, use == or is to call this method.

class Foo:
​
    def __init__(self,name):
        self.name = name
​
    def __eq__(self, other):
        if self.name == other.name:  #判断如果对象的name属性相等就返回True
            return True
        else:
            return False
​
obj1 = Foo("nick")
obj2 = Foo("nicholas")
print(obj1 is obj2)

Fourth, the __hash__method

Get the hash value of an object. Generally speaking, the hash value of the object is generated based on the memory address of the object, but the overriding __hash__method can customize the hash value of the object.

class Foo:
​
    def __init__(self,name,age):
        self.name = name
        self.age = age
​
    def __hash__(self):
        return hash(self.name+str(self.age)) #这里基于对象的两个属性返回hash值
​
​
obj1 = Foo("nick",18)  #注意hash的对象不能是整数
obj2 = Foo("nick",18)
print(hash(obj1))
print(hash(obj2))

Note that there are two usage scenarios for the magic method __hash__:

(1) Called by the built-in function hash()

(2) The hash operation of a set of hash type on its own members: set(), frozenset([ iterable ]), dict(**kwarg)

 Five, __eq__ and __hash__ application

1. Only __eq__ is used in the first half of the following code, because there is no hashable set involved, there is no hash involved

2. If the custom class overrides the __eq__() method and does not override the __hash__() method, then this class cannot be used as an element of a hash collection (this hashable collections refers to set, frozenset and dict)

For example, the hash collection is all objects, and only __eq__ is defined. If __hash__ is not defined, an error will be reported


class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
 
    # def __hash__(self):
    #     print(self.name, '使用了__hash__方法')
    #     return hash(self.name)
 
    def __eq__(self, other):
        print(self.name, '使用了__eq__方法')
        return self.__dict__ == other.__dict__
 
 
person1 = Person('zs', 20)
person2 = Person('ls', 20)
person3 = Person('ww', 30)
person4 = Person('zs', 20)
 
print(person1 == person4)
print(person2 == person3)

set1 = {person1, person2, person3, person4}
print(set1)

输出:
zs 使用了__eq__方法
True
ls 使用了__eq__方法
False
Traceback (most recent call last):
  File "D:/self_study/python_study/class_study/python——内置方法.py", line 88, in <module>
    set1 = {person1, person2, person3, person4}
TypeError: unhashable type: 'Person'

This is actually because after rewriting the __eq__() method, __hash__ is assigned to None by default (as mentioned later in the document), just like a list. Such as the following test:

class A:
    def __eq__(self, other):
        pass 
a = A()
 
print(a.__hash__)  
hash(a)
输出: 
None 
TypeError: unhashable type: 'A'

3. If the custom class overrides the __hash__() method and does not override the __eq__() method

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
 
    def __hash__(self):
        print(self.name, '使用了__hash__方法')
        return hash(self.name)
 
    # def __eq__(self, other):
    #     print(self.name, '使用了__eq__方法')
    #     return self.__dict__ == other.__dict__
 
 
person1 = Person('zs', 20)
person2 = Person('ls', 20)
person3 = Person('ww', 30)
person4 = Person('zs', 20)
 
 
set1 = {person1, person2, person3, person4}
print(set1)

No error is reported, but it does not meet the requirements-we think that person1 and person4 are the same person, but they are both added to the collection, which violates the concept of collection:

zs 使用了__hash__方法
ls 使用了__hash__方法
ww 使用了__hash__方法
zs 使用了__hash__方法
{<__main__.Person object at 0x0000000000719CF8>,
 <__main__.Person object at 0x00000000007192E8>, 
 <__main__.Person object at 0x0000000000719CC0>,
 <__main__.Person object at 0x0000000000719320>}

There is no person4 in our expectation. Why is there person4 here? And the hash(name) of person1 and person4 are the same, why is it added to the set at the end? The main reason is that when the hash values ​​are found to be the same, __eq__ is needed to make the next judgment. We rewrite __hash__ but not __eq__. The default __eq__ of object is called, and the default __eq__ compares the address of the object. The address of person1 and person4 are different, so the last person4 is added to the collection.

4. The custom class overrides the __hash__() method and __eq__() method

Hashed collections require the elements of the collection to achieve the __eq__sum __hash__, and these two methods can be used as a vivid analogy: a
hash collection is a lot of buckets, but only one ball can be placed in each bucket.

__hash__The function of the function is to find the position of the bucket, which number is the bucket in the end.
__eq__The function of the function is that when there is already a ball in the bucket, but another ball comes, it claims that it should also be put into the bucket (the __hash__function tells it the position of the bucket), and the two sides are in a stalemate, then you have to use the __eq__function To judge whether the two balls are equal, if it is judged to be equal, then the ball should not be put into the bucket later, and the hash set maintains the status quo.

class Foo:
    def __init__(self, item):
        self.item = item

    def __eq__(self, other):
        print('使用了equal函数的对象的id',id(self))
        if isinstance(other, self.__class__):
            return self.__dict__ == other.__dict__
        else:
            return False
    def __hash__(self):
        print('f'+str(self.item)+'使用了hash函数')
        return hash(self.item)       
f1 = Foo(1)
f2 = Foo(2)
f3 = Foo(3)
fset = set([f1, f2, f3])
print(fset)
print()
f = Foo(3)
fset.add(f)
print('f3的id:',id(f3))
print('f的id:',id(f))
fset.remove(f)
print(fset)

operation result:

f1使用了hash函数
f2使用了hash函数
f3使用了hash函数
{<__main__.Foo object at 0x00000203EB7EB630>, <__main__.Foo object at 0x00000203EB987358>, <__main__.Foo object at 0x00000203EB987390>}

f3使用了hash函数
使用了equal函数的对象的id 2215860794256
f3的id: 2215860794256
f的id: 2215860797392
使用了equal函数的对象的id 2215860794256
{<__main__.Foo object at 0x00000203EB7EB630>, <__main__.Foo object at 0x00000203EB987358>}

It can be seen that when f1, f2, and f3 are added to the set, the __hash__function will be called every time .
Since the _ __hash__function I defined is return hash(self.item), the position of the bucket found by f and f3 is the same position, because their items are the same. When fset.add(f) is executed, f will call its own __hash__function to find the location of the bucket to which f belongs. But this time the bucket has another ball, so you have to spend this time __eq__to determine whether two objects are equal, you can see from the output, is already subject to call __eq__to and subsequent object to be compared (see object id ).
Here, if it is the delete operation fset.remove(Foo(3)), the principle is the same. First use the hash to find the position of the bucket. If there is a ball in the bucket, judge whether the two balls are equal, and if they are equal, put the ball in the bucket Throw it away.

Official explanation

When the hash function is called for the hashable set (set, frozenset, dict), it should return an int value. The only requirement is that if two objects are judged to be equal, then their hash values ​​should also be equal. When comparing two objects for equality, the members of the object are used for comparison. It is recommended to put the members into the original ancestor, and then get the hash value of the original ancestor for comparison.

When the class does not define the __eq__() method, then it should not define the __hash__() method. If it defines the __eq__() method, but does not define the __hash__() method, then the instance of this class cannot be used in the hashable collection. If a class defines a mutable object (this should mean that one of the members of the class is a mutable object), and the __eq__() method is implemented, then this class should not implement the  hash () method, because it can be hashed The implementation of the object requires that the hash value of the key is unchanged (if the hash value of an object changes, it will be placed in the wrong hash bucket)

There are default __eq__ and __hash__ methods in user-defined classes; with it, all object instances are unequal (unless they are compared with themselves), when x == y is compared with This equivalent hash(x) == hash(y).

Six, exception handling

1. What is an exception

An exception is a signal that an error occurs when the program is running (when an error occurs in the program, an exception will be generated, if the program does not handle it, the exception will be thrown, and the running of the program will also be terminated)

There are two types of errors : grammatical errors and logical errors

Syntax errors are punctuation errors in some codes, etc. There are many kinds of logic errors.

#TypeError:int类型不可迭代
for i in 3:
    pass
     
#ValueError
num=input(">>: ") #输入hello
int(num)
​
#NameError
aaa
​
#IndexError
l=['egon','aa']
l[3]
​
#KeyError
dic={'name':'egon'}
dic['age']
​
#AttributeError
class Foo:pass
Foo.x
​
#ZeroDivisionError:无法完成计算
res1=1/0
res2=1+'str'

2. Types of abnormalities

Common exceptions

AttributeError 试图访问一个对象没有的属性,比如foo.x,但是foo没有属性x

IOError 输入/输出异常;基本上是无法打开文件

ImportError 无法引入模块或包;基本上是路径问题或名称错误

IndentationError 语法错误(的子类) ;代码没有正确对齐

IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5]

KeyError 试图访问字典里不存在的键

KeyboardInterrupt Ctrl+C被按下

NameError 使用一个还未被赋予对象的变量

SyntaxError Python代码非法,代码不能编译,语法错误

TypeError 传入对象类型与要求的不符合

UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量,

导致你以为正在访问它

ValueError 传入一个调用者不期望的值,即使值的类型是正确的

 All exceptions

BaseException  # 所有异常的基类
 +-- SystemExit  # 解释器请求退出
 +-- KeyboardInterrupt  # 用户中断执行(通常是输入^C)
 +-- GeneratorExit  # 生成器(generator)发生异常来通知退出
 +-- Exception  # 常规异常的基类
      +-- StopIteration  # 迭代器没有更多的值
      +-- StopAsyncIteration  # 必须通过异步迭代器对象的__anext__()方法引发以停止迭代
      +-- ArithmeticError  # 各种算术错误引发的内置异常的基类
      |    +-- FloatingPointError  # 浮点计算错误
      |    +-- OverflowError  # 数值运算结果太大无法表示
      |    +-- ZeroDivisionError  # 除(或取模)零 (所有数据类型)
      +-- AssertionError  # 当assert语句失败时引发
      +-- AttributeError  # 属性引用或赋值失败
      +-- BufferError  # 无法执行与缓冲区相关的操作时引发
      +-- EOFError  # 当input()函数在没有读取任何数据的情况下达到文件结束条件(EOF)时引发
      +-- ImportError  # 导入模块/对象失败
      |    +-- ModuleNotFoundError  # 无法找到模块或在在sys.modules中找到None
      +-- LookupError  # 映射或序列上使用的键或索引无效时引发的异常的基类
      |    +-- IndexError  # 序列中没有此索引(index)
      |    +-- KeyError  # 映射中没有这个键
      +-- MemoryError  # 内存溢出错误(对于Python 解释器不是致命的)
      +-- NameError  # 未声明/初始化对象 (没有属性)
      |    +-- UnboundLocalError  # 访问未初始化的本地变量
      +-- OSError  # 操作系统错误,EnvironmentError,IOError,WindowsError,socket.error,select.error和mmap.error已合并到OSError中,构造函数可能返回子类
      |    +-- BlockingIOError  # 操作将阻塞对象(e.g. socket)设置为非阻塞操作
      |    +-- ChildProcessError  # 在子进程上的操作失败
      |    +-- ConnectionError  # 与连接相关的异常的基类
      |    |    +-- BrokenPipeError  # 另一端关闭时尝试写入管道或试图在已关闭写入的套接字上写入
      |    |    +-- ConnectionAbortedError  # 连接尝试被对等方中止
      |    |    +-- ConnectionRefusedError  # 连接尝试被对等方拒绝
      |    |    +-- ConnectionResetError    # 连接由对等方重置
      |    +-- FileExistsError  # 创建已存在的文件或目录
      |    +-- FileNotFoundError  # 请求不存在的文件或目录
      |    +-- InterruptedError  # 系统调用被输入信号中断
      |    +-- IsADirectoryError  # 在目录上请求文件操作(例如 os.remove())
      |    +-- NotADirectoryError  # 在不是目录的事物上请求目录操作(例如 os.listdir())
      |    +-- PermissionError  # 尝试在没有足够访问权限的情况下运行操作
      |    +-- ProcessLookupError  # 给定进程不存在
      |    +-- TimeoutError  # 系统函数在系统级别超时
      +-- ReferenceError  # weakref.proxy()函数创建的弱引用试图访问已经垃圾回收了的对象
      +-- RuntimeError  # 在检测到不属于任何其他类别的错误时触发
      |    +-- NotImplementedError  # 在用户定义的基类中,抽象方法要求派生类重写该方法或者正在开发的类指示仍然需要添加实际实现
      |    +-- RecursionError  # 解释器检测到超出最大递归深度
      +-- SyntaxError  # Python 语法错误
      |    +-- IndentationError  # 缩进错误
      |         +-- TabError  # Tab和空格混用
      +-- SystemError  # 解释器发现内部错误
      +-- TypeError  # 操作或函数应用于不适当类型的对象
      +-- ValueError  # 操作或函数接收到具有正确类型但值不合适的参数
      |    +-- UnicodeError  # 发生与Unicode相关的编码或解码错误
      |         +-- UnicodeDecodeError  # Unicode解码错误
      |         +-- UnicodeEncodeError  # Unicode编码错误
      |         +-- UnicodeTranslateError  # Unicode转码错误
      +-- Warning  # 警告的基类
           +-- DeprecationWarning  # 有关已弃用功能的警告的基类
           +-- PendingDeprecationWarning  # 有关不推荐使用功能的警告的基类
           +-- RuntimeWarning  # 有关可疑的运行时行为的警告的基类
           +-- SyntaxWarning  # 关于可疑语法警告的基类
           +-- UserWarning  # 用户代码生成警告的基类
           +-- FutureWarning  # 有关已弃用功能的警告的基类
           +-- ImportWarning  # 关于模块导入时可能出错的警告的基类
           +-- UnicodeWarning  # 与Unicode相关的警告的基类
           +-- BytesWarning  # 与bytes和bytearray相关的警告的基类
           +-- ResourceWarning  # 与资源使用相关的警告的基类。被默认警告过滤器忽略。

 For detailed instructions, please refer to: https://docs.python.org/3/library/exceptions.html#base-classes

 

3. Exception handling

The python interpreter detects an error and triggers an exception (also allows the programmer to trigger an exception by himself)

The programmer writes a specific code specifically to catch this exception (this code has nothing to do with program logic, but is related to exception handling)

If the capture is successful, then enter another processing branch, execute the logic you customized for it, so that the program will not crash, this is exception handling

 

4. The significance of exception handling

The python parser executes the program, and when an error is detected, an exception is triggered. After the exception is triggered and is not handled, the program terminates at the current exception, and the following code will not run, so you must provide an exception handling Mechanism to enhance the robustness and fault tolerance of your program.

 5. Catch exceptions

When an exception occurs, we need to catch the exception and then deal with it accordingly. Python's exception capture commonly used try...except... structure, put the statements that may cause errors in the try module, and use except to handle exceptions. Each try must correspond to at least one except. In addition, keywords related to python exceptions mainly include:

Keyword Keyword description
try/except Catch the exception and handle it
pass Ignore exception
as Define exception instance (except MyError as e)
else If the statement in try does not raise an exception, the statement in else is executed
finally The code that is executed regardless of whether an exception occurs
raise     Throw/throw an exception

There are many ways to capture exceptions, which are discussed separately below

5.1 Catch all exceptions

Including keyboard interrupt and program exit request ( you cannot exit the program with sys.exit() because the exception is caught ), so use it with caution.

try:
     被检测的代码块
except 异常类型:
     try中一旦检测到异常,就执行这个位置的逻辑

. 5 .2 capture the specified exception

try:
    f = open("file-not-exists", "r")
except IOError as e:
    print("open exception: %s: %s" %(e.errno, e.strerror))

Universal exception:

Among the exceptions of python, there is a universal exception: Exception, which can catch any exception. It is a double-edged sword, with pros and cons, we have to use it according to the situation

  If the effect you want is that no matter what exceptions appear, we discard them uniformly, or use the same piece of code logic to deal with them, then only one Exception is enough.

  If the effect you want is that we need to customize different processing logic for different exceptions, then we need to use multiple branches. We can use multi-branch + universal exception to handle exceptions. Use multi-branch to first handle some expected error types, and some unexpected error types should be caught by the final universal exception. It should be noted that the universal exception must be placed at the end, otherwise it will be meaningless

5.3 Catching multiple exceptions

There are two ways to catch multiple exceptions. The first is that one except handles multiple exceptions at the same time, without distinguishing priority:

try:
     <语句>
except (<异常名1>, <异常名2>, ...):
      print('异常说明')

The second one is prioritized:

l1 = [('电脑',16998),('鼠标',59),('手机',8998)]
while 1:
    for key,value in enumerate(l1,1):
        print(key,value[0])
    try:
        num = input('>>>')
        price = l1[int(num)-1][1]
    except ValueError:
        print('请输入一个数字')
    except IndexError:
        print('请输入一个有效数字')
#这样通过异常处理可以使得代码更人性化,用户体验感更好。

The rules of this kind of exception handling syntax are:

  • Execute the statement under try, if an exception is raised, the execution process will jump to the first except statement.
  • If the exception defined in the first except matches the thrown exception, the statement in the except is executed.
  • If the thrown exception does not match the first except, it will search for the second except, and there is no limit to the number of exceptions that can be written.
  • If all the excepts do not match, the exception will be passed to the next highest-level try code that calls this code.

5.4 Else in exception

If you want to do other things after judging that there are no exceptions, you can use the following else statement.

try:
    for i in range(10):
        int(i)
except IndexError as e:
    print(e)
else:
    print('***********')   #***********   执行了此处
    #当try语句中的代码没有异常,被完整地执行完,就执行else中的代码

5.5 finally in exception

The try...finally... statement will execute the final code regardless of whether an exception occurs.

def dealwith_file():
    try:
        f = open('file',encoding='utf-8')
        for line in f:
            int(line)
        return True
    except Exception as e:
        print(e)
        return False
    finally:
        '''不管try语句中的代码是否报错,都会执行finally分支中的代码'''
        '''去完成一些连接操作的收尾工作'''
        print('finally 被执行了')
        f.close()
ret = dealwith_file()
print(ret)

5.6 Raise actively triggers exceptions

You can use the raise statement to trigger an exception yourself. The syntax format of raise is as follows:

raise [Exception [, args [, traceback]]]

Exception in the statement is the type of exception (for example, ValueError), and the parameter is an abnormal parameter value. This parameter is optional. If not provided, the abnormal parameter is "None". The last parameter is to track the exception object, which is also optional (rarely used in practice).

Look at an example:

def not_zero(num):
    try:
        if num == 0:
            raise ValueError('参数错误')
        return num
    except Exception as e:
        print(e)

not_zero(0)

5.7 Use the traceback module to view exceptions

When an exception occurs, Python can "remember" the exception raised and the current state of the program. Python also maintains a traceback object, which contains information about the function call stack when the exception occurs. Remember that exceptions may be raised in a series of deeply nested function calls. When the program calls each function, Python will insert the function name at the beginning of the "function call stack". Once the exception is raised, Python will search for a corresponding exception handler. If there is no exception handler in the current function, the current function will terminate its execution, and Python will search for the calling function of the current function, and so on, until a matching exception handler is found, or Python reaches the main program. This process of finding the appropriate exception handler is called "stack unwinding" (StackUnwinding). On the one hand, the interpreter maintains information related to the functions placed on the stack, and on the other hand, it also maintains information related to functions that have been "disassembled" from the stack.

The format is as follows:

try:
    block
except:
    traceback.print_exc()

Give a chestnut:

try:
    1/0
except Exception as e:
    print(e)

If we write this way, the program will only report the "division by zero" error, but we don't know which file, function or line the error is.

The traceback module is used below, the official reference document: https://docs.python.org/2/library/traceback.html

import traceback
 
try:
    1/0
except Exception as e:
    traceback.print_exc()

This will help us trace back to the point of error:

Traceback (most recent call last):
  File "E:/PycharmProjects/ProxyPool-master/proxypool/test.py", line 4, in <module>
    1/0
ZeroDivisionError: division by zero

In addition, what is the difference between traceback.print_exc() and traceback.format_exc()?

The difference is that format_exc() returns a string, and print_exc() directly prints it out. That is, traceback.print_exc() has the same effect as print(traceback.format_exc()). print_exc() can also accept file parameters and write directly to a file. For example, you can write the relevant information to the tb.txt file as follows.

traceback.print_exc(file=open('tb.txt','w+'))

6, assert

Assert assertion is to declare that its boolean value must be true, and if an exception occurs, it means that the expression is false. It can be understood that the assert statement is raise-if-not, which is used to test the expression. If the return value is false, an exception will be triggered.

The exception parameter of assert is actually to add string information after the assertion expression to explain the assertion and better know what went wrong. The format is as follows:
assert expression [, arguments]
assert expression [, arguments]

assert len(lists) >=5,'The number of list elements is less than 5'

assert 2==1,'2 is not equal to 1'

Remarks: Format: assert condition, the error message when the condition is false, the result is raise an AssertionError

7, custom exception

7.1 Two ways to customize exceptions

# 方式一
class MYERROR(Exception):
​
    def __init__(self):
        self.err = "自定义异常"
​
    def __str__(self):
        return self.err
​
e = MYERROR()
raise MYERROR
​
#方式二
class MYERROR2(BaseException):
​
    def __init__(self,msg):
        self.msg = msg
    #继承BaseException类不再需要__str__方法,BaseException中已经实现了
try:
    raise MYERROR2("自定义异常")
except Exception as e:
    print("-----")
    print(e)

7.2. How to manually throw an exception: raise

The system's own exceptions will be automatically thrown as long as they are triggered, such as NameError, but user-defined exceptions need to be thrown by the user himself.
The only parameter of raise specifies the exception to be raised. It must be an exception instance or an exception class (that is, a subclass of Exception). Most of the exception names end with "Error", so the actual naming should be the same as the standard exception naming.

 

#1.用户自定义异常类型
class TooLongExceptin(Exception):
    "this is user's Exception for check the length of name "
    def __init__(self,leng):
        self.leng = leng
    def __str__(self):
        print("姓名长度是"+str(self.leng)+",超过长度了")
 
#2.手动抛出用户自定义类型异常
def name_Test():
        name = input("enter your naem:")
        if len(name)>4:
            raise TooLongExceptin(len(name))  #抛出异常很简单,使用raise即可,但是没有处理,即捕捉
        else :
            print(name)
 
#调用函数,执行
name_Test()
-----------------执行时满足条件后抛出一个用户定义的异常如下:--------------------------------------
enter your naem:是打发斯蒂芬
Traceback (most recent call last):
姓名长度是6,超过长度了
  File "D:/pythoyworkspace/file_demo/Class_Demo/extion_demo.py", line 21, in <module>
    name_Test()
__main__.TooLongExceptin: <exception str() failed>

 

7.3. Catch exceptions manually thrown by users

#1. Catch the exception manually thrown by the user, the same way as the system exception

def name_Test():
    try:
        name = input("enter your naem:")
        if len(name) > 4:
            raise TooLongExceptin(len(name))
        else:
            print(name)

    except TooLongExceptin as e_result:  # 这里异常类型是用户自定义的
        print("捕捉到异常了")
        print("打印异常信息:", e_result)

# 调用函数,执行
name_Test()

=========执行结果如下=========
enter your naem:kklklk;l;l
捕捉到异常了
打印异常信息: 姓名长度是10,超过长度了
姓名长度是10,超过长度了
Traceback (most recent call last):
  File "D:/self_study/python_study/class_study/异常.py", line 15, in name_Test
    raise TooLongExceptin(len(name))
__main__.TooLongExceptin: <exception str() failed>

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "D:/self_study/python_study/class_study/异常.py", line 24, in <module>
    name_Test()
  File "D:/self_study/python_study/class_study/异常.py", line 21, in name_Test
    print("打印异常信息:", e_result)
TypeError: __str__ returned non-string (type NoneType)

Process finished with exit code 1

8. When to use the exception

Try...except should be used as little as possible, because adding an exception handling logic to your program will result in poor code readability.

In addition, in exception handling, try...except is added only when some exceptions are unpredictable, and other logic errors should be corrected as much as possible.

Guess you like

Origin blog.csdn.net/zangba9624/article/details/110477262