Python3 学习 第八章 异常 ---20230811

#!usr/bin/env python  
# -*- coding:utf-8 _*-
""" 
@author:AI
@file: lecture8.py 
@time: 2023/08/04 
"""

# 第八章 异常

# case1----十六进制
# number = int(input("Please Input a Number:"))
# # 获取每一个数
# num = number[::-1]
# str1 = '0123456789ABCDEF'
# result = 0
#
# for i in range(0,len(num)):
#     result += (str1.index(num[i])*(16**i))
# print(int(result))


# number = input("Please Input a Number:")
# # 将输入数字进行逆序排列
# num = number[::-1]
# result = 0
#
# for i in range(0,len(num)):
#     result += int(num[i])*(16**i)
# print(int(result))

# num = input()
# num = num[::-1]
# str1 = '0123456789ABCDEF'
# result = 0
# for i in range(0, len(num)):
#     result += (str1.index(num[i]))*(16**i)
# print(int(result))

# 编写计算机程序时,通常能够区分正常和异常(不正常)情况。异常事件可能是错误(如试
# 图除以零),也可能是通常不会发生的事情。为处理这些异常事件,可在每个可能发生这些事件
# 的地方都使用条件语句。例如,对于每个除法运算,都检查除数是否为零。然而,这样做不仅效
# 率低下、缺乏灵活性,还可能导致程序难以卒读。你可能很想忽略这些异常事件,希望它们不会
# 发生,但Python提供功能强大的替代解决方案——异常处理机制。
# 在本章中,你将学习如何创建和引发异常,以及各种异常处理方式。

# 8.1 异常是什么
# Python使用异常对象来表示异常状态,并在遇到错误时引发异常。异常对象未被处理(或捕
# 获)时,程序将终止并显示一条错误消息(traceback)。
# >>> 1 / 0
# Traceback (most recent call last):
#  File "<stdin>", line 1, in ?
# ZeroDivisionError: integer division or modulo by zero
# 如果异常只能用来显示错误消息,就没多大意思了。但事实上,每个异常都是某个类(这里
# 是ZeroDivisionError)的实例。你能以各种方式引发和捕获这些实例,从而逮住错误并采取措施,
# 而不是放任整个程序失败。

# 8.2 让事情沿你指定的轨道出错
# 正如你看到的,出现问题时,将自动引发异常。先来看看如何自主地引发异常,还有如何创建异常,然后再学习如何处理这些异常。

# 8.2.1 raise 语句
# 要引发异常,可使用raise语句,并将一个类(必须是Exception的子类)或实例作为参数。
# 将类作为参数时,将自动创建一个实例。下面的示例使用的是内置异常类Exception:
# >>> raise Exception
# Traceback (most recent call last):
#  File "<stdin>", line 1, in ?
# Exception
# >>> raise Exception('hyperdrive overload')
# Traceback (most recent call last):
#  File "<stdin>", line 1, in ?
# Exception: hyperdrive overload
# 在第一个示例(raise Exception)中,引发的是通用异常,没有指出出现了什么错误。在第
# 二个示例中,添加了错误消息hyperdrive overload。

# 有很多内置的异常类,表8-1描述了最重要的几个。在“Python库参考手册”的Built-in
# Exceptions一节,可找到有关所有内置异常类的描述。这些异常类都可用于raise语句中。
# >>> raise ArithmeticError
# Traceback (most recent call last):
#  File "<stdin>", line 1, in ?
# ArithmeticError

# 表8-1 一些内置的异常类
# 类 名                      描 述
# Exception                 几乎所有的异常类都是从它派生而来的
# AttributeError            引用属性或给它赋值失败时引发
# OSError                   操作系统不能执行指定的任务(如打开文件)时引发,有多个子类
# IndexError                使用序列中不存在的索引时引发,为LookupError的子类
# KeyError                  使用映射中不存在的键时引发,为LookupError的子类
# NameError                 找不到名称(变量)时引发
# SyntaxError               代码不正确时引发
# TypeError                 将内置操作或函数用于类型不正确的对象时引发
# ValueError                将内置操作或函数用于这样的对象时引发:其类型正确但包含的值不合适
# ZeroDivisionError         在除法或求模运算的第二个参数为零时引发

# 8.2.2 自定义的异常类
# 虽然内置异常涉及的范围很广,能够满足很多需求,但有时你可能想自己创建异常类。例如,
# 在前面的超光速推进装置过载(hyperdrive overload)示例中,使用专用的HyperdriveError类来
# 表示超光速推进装置的错误状态不是更自然吗?好像提供了错误消息就足够了,但在8.3节你将
# 看到,可基于异常所属的类选择性地处理异常。因此,如果你要使用特殊的错误处理代码对超光
# 速推进装置错误进行处理,就必须有一个专门用于表示这些异常的类。
# 那么如何创建异常类呢?就像创建其他类一样,但务必直接或间接地继承Exception(这意
# 味着从任何内置异常类派生都可以)。因此,自定义异常类的代码类似于下面这样:
# class SomeCustomException(Exception): pass
# 工作量真的不大。(当然,如果你愿意,也可在自定义异常类中添加方法。)

# 8.3 捕获异常
# 前面说过,异常比较有趣的地方是可对其进行处理,通常称之为捕获异常。为此,可使用
# try/except语句。假设你创建了一个程序,让用户输入两个数,再将它们相除,如下所示:

# x = int(input('Enter the first number: '))
# y = int(input('Enter the second number: '))
# print(x / y)

# 这个程序运行正常,直到用户输入的第二个数为零。
# Enter the first number: 10
# Enter the second number: 0
# Traceback (most recent call last):
#  File "exceptions.py", line 3, in ?
#  print(x / y)
# ZeroDivisionError: integer division or modulo by zero

# 为捕获这种异常并对错误进行处理(这里只是打印一条对用户更友好的错误消息),可像下面这样重写这个程序:
# try:
#  x = int(input('Enter the first number: '))
#  y = int(input('Enter the second number: '))
#  print(x / y)
# except ZeroDivisionError:
#  print("The second number can't be zero!")

# 使用一条if语句来检查y的值好像简单些,就本例而言,这可能也是更佳的解决方案。然而,
# 如果这个程序执行的除法运算更多,则每个除法运算都需要一条if语句,而使用try/except的话只需要一个错误处理程序。

# 注意    异常从函数向外传播到调用函数的地方。如果在这里也没有被捕获,异常将向程序的最
# 顶层传播。这意味着你可使用try/except来捕获他人所编写函数引发的异常。有关这方面的详细信息,请参阅8.4节。

# 8.3.1 不用提供参数
# 捕获异常后,如果要重新引发它(即继续向上传播),可调用raise且不提供任何参数(也可显式地提供捕获到的异常,参见8.3.4节)。

# 为说明这很有用,来看一个能够“抑制”异常ZeroDivisionError的计算器类。如果启用了这
# 种功能,计算器将打印一条错误消息,而不让异常继续传播。在与用户交互的会话中使用这个计
# 算器时,抑制异常很有用;但在程序内部使用时,引发异常是更佳的选择(此时应关闭“抑制”
# 功能)。下面是这样一个类的代码:

# class MuffledCalculator:
#     muffled = False
#     def calc(self, expr):
#         try:
#             return eval(expr)
#         except ZeroDivisionError:
#             if self.muffled:
#                 print('Division by zero is illegal')
#             else:
#                 raise

# 注意 发生除零行为时,如果启用了“抑制”功能,方法calc将(隐式地)返回None。换而言
# 之,如果启用了“抑制”功能,就不应依赖返回值。

# 下面的示例演示了这个类的用法(包括启用和关闭了抑制功能的情形):
# >>> calculator = MuffledCalculator()
# >>> calculator.calc('10 / 2')
# 5.0
# >>> calculator.calc('10 / 0') # 关闭了抑制功能
# Traceback (most recent call last): File "<stdin>", line 1, in ?
#  File "MuffledCalculator.py", line 6, in calc
#  return eval(expr)
#  File "<string>", line 0, in ?
# ZeroDivisionError: integer division or modulo by zero
# >>> calculator.muffled = True
# >>> calculator.calc('10 / 0')
# Division by zero is illegal

# 如你所见,关闭抑制功能时,捕获了异常ZeroDivisionError,但继续向上传播它。
# 如果无法处理异常,在except子句中使用不带参数的raise通常是不错的选择,但有时你可
# 能想引发别的异常。在这种情况下,导致进入except子句的异常将被作为异常上下文存储起来,
# 并出现在最终的错误消息中,如下所示:

# >>> try:
# ... 1/0
# ... except ZeroDivisionError:
# ... raise ValueError
# ...
# Traceback (most recent call last):
#  File "<stdin>", line 2, in <module>
# ZeroDivisionError: division by zero
# 在处理上述异常时,引发了另一个异常:
# Traceback (most recent call last):
#  File "<stdin>", line 4, in <module>
# ValueError
# 你可使用raise ... from ...语句来提供自己的异常上下文,也可使用None来禁用上下文。

# >>> try:
# ... 1/0
# ... except ZeroDivisionError:
# ... raise ValueError from None
# ...
# Traceback (most recent call last):
#  File "<stdin>", line 4, in <module>
# ValueError

# 8.3.2 多个 except 子句
# 如果你运行前一节的程序,并在提示时输入一个非数字值,将引发另一种异常。
# Enter the first number: 10
# Enter the second number: "Hello, world!"
# Traceback (most recent call last):
#  File "exceptions.py", line 4, in ?
#  print(x / y)
# TypeError: unsupported operand type(s) for /: 'int' and 'str'

# 由于该程序中的except子句只捕获ZeroDivisionError异常,这种异常将成为漏网之鱼,导致
# 程序终止。为同时捕获这种异常,可在try/except语句中再添加一个except子句。

# try:
#  x = int(input('Enter the first number: '))
#  y = int(input('Enter the second number: '))
#  print(x / y)
# except ZeroDivisionError:
#  print("The second number can't be zero!")
# except TypeError:
#  print("That wasn't a number, was it?")

# 现在使用if语句来处理将更加困难。如何检查一个值能否用于除法运算呢?方法有很多,但
# 最佳的方法无疑是尝试将两个值相除,看看是否可行。
# 另外,注意到异常处理并不会导致代码混乱,而添加大量的if语句来检查各种可能的错误状
# 态将导致代码的可读性极差。

# 8.3.3 一箭双雕
# 如果要使用一个except子句捕获多种异常,可在一个元组中指定这些异常,如下所示:
# try:
#  x = int(input('Enter the first number: '))
#  y = int(input('Enter the second number: '))
#  print(x / y)
# except (ZeroDivisionError, TypeError, NameError):
#  print('Your numbers were bogus ...')

# 在上述代码中,如果用户输入字符串、其他非数字值或输入的第二个数为零,都将打印同样
# 的错误消息。当然,仅仅打印错误消息帮助不大。另一种解决方案是不断地要求用户输入数字,
# 直到能够执行除法运算为止,8.3.6节将介绍如何这样做。
# 在except子句中,异常两边的圆括号很重要。一种常见的错误是省略这些括号,这可能导致
# 你不想要的结果,其中的原因请参阅下一节。

# 8.3.4 捕获对象
# 要在except子句中访问异常对象本身,可使用两个而不是一个参数。(请注意,即便是在你
# 捕获多个异常时,也只向except提供了一个参数——一个元组。)需要让程序继续运行并记录错
# 误(可能只是向用户显示)时,这很有用。下面的示例程序打印发生的异常并继续运行:

# try:
#  x = int(input('Enter the first number: '))
#  y = int(input('Enter the second number: '))
#  print(x / y)
# except (ZeroDivisionError, TypeError) as e:
#  print(e)
# 在这个小程序中,except子句也捕获两种异常,但由于你同时显式地捕获了对象本身,因此
# 可将其打印出来,让用户知道发生了什么情况。8.3.6节将介绍这种技术的另一种更有用的用途。

# 8.3.5 一网打尽
# 即使程序处理了好几种异常,还是可能有一些漏网之鱼。例如,对于前面执行除法运算的程
# 序,如果用户在提示时不输入任何内容就按回车键,将出现一条错误消息,还有一些相关问题出
# 在什么地方的信息(栈跟踪),如下所示:
# Traceback (most recent call last):
#  ...
# ValueError: invalid literal for int() with base 10: ''
# 这种异常未被try/except语句捕获,这理所当然,因为你没有预测到这种问题,也没有采取
# 相应的措施。在这些情况下,与其使用并非要捕获这些异常的try/except语句将它们隐藏起来,
# 还不如让程序马上崩溃,因为这样你就知道什么地方出了问题。
# 然而,如果你就是要使用一段代码捕获所有的异常,只需在except语句中不指定任何异常类
# 即可。
# try:
#  x = int(input('Enter the first number: '))
#  y = int(input('Enter the second number: '))
#  print(x / y)
# except:
#  print('Something wrong happened ...')
# 现在,用户想怎么做都可以。
# Enter the first number: "This" is *completely* illegal 123
# Something wrong happened ...
# 像这样捕获所有的异常很危险,因为这不仅会隐藏你有心理准备的错误,还会隐藏你没有考
# 虑过的错误。这还将捕获用户使用Ctrl + C终止执行的企图、调用函数sys.exit来终止执行的企图
# 等。在大多数情况下,更好的选择是使用except Exception as e并对异常对象进行检查。这样做
# 将让不是从Exception派生而来的为数不多的异常成为漏网之鱼,其中包括SystemExit和
# KeyboardInterrupt,因为它们是从BaseException(Exception的超类)派生而来的。

# 8.3.6 万事大吉时
# 在有些情况下,在没有出现异常时执行一个代码块很有用。为此,可像条件语句和循环一样,
# 给try/except语句添加一个else子句。
# try:
#  print('A simple task')
# except:
#  print('What? Something went wrong?')
# else:
#  print('Ah ... It went as planned.')
# 如果你运行这些代码,输出将如下:
# A simple task
# Ah ... It went as planned.
# 通过使用else子句,可实现8.3.3节所说的循环。
# while True:
#  try:
#  x = int(input('Enter the first number: '))
#  y = int(input('Enter the second number: '))
#  value = x / y
#  print('x / y is', value)
#  except:
#  print('Invalid input. Please try again.')
#  else:
#  break
# 在这里,仅当没有引发异常时,才会跳出循环(这是由else子句中的break语句实现的)。换
# 而言之,只要出现错误,程序就会要求用户提供新的输入。下面是这些代码的运行情况:
# Enter the first number: 1
# Enter the second number: 0
# Invalid input. Please try again.
# Enter the first number: 'foo'
# Enter the second number: 'bar'
# Invalid input. Please try again.
# Enter the first number: baz
# Invalid input. Please try again.
# Enter the first number: 10
# Enter the second number: 2
# x / y is 5
# 前面说过,一种更佳的替代方案是使用空的except子句来捕获所有属于类Exception(或其子
# 类)的异常。你不能完全确定这将捕获所有的异常,因为try/except语句中的代码可能使用旧式
# 的字符串异常或引发并非从Exception派生而来的异常。然而,如果使用except Exception as e,
# 就可利用8.3.4节介绍的技巧在这个小型除法程序中打印更有用的错误消息。
# while True:
#  try:
#  x = int(input('Enter the first number: '))
#  y = int(input('Enter the second number: '))
#  value = x / y
#  print('x / y is', value)
#  except Exception as e:
#  print('Invalid input:', e)
#  print('Please try again')
#  else:
#  break
# 下面是这个程序的运行情况:
# Enter the first number: 1
# Enter the second number: 0
# Invalid input: integer division or modulo by zero
# Please try again
# Enter the first number: 'x' Enter the second number: 'y'
# Invalid input: unsupported operand type(s) for /: 'str' and 'str'
# Please try again
# Enter the first number: quuux
# Invalid input: name 'quuux' is not defined
# Please try again
# Enter the first number: 10
# Enter the second number: 2
# x / y is 5

# 8.3.7 最后
# 最后,还有finally子句,可用于在发生异常时执行清理工作。这个子句是与try子句配套的。
# x = None
# try:
#  x = 1 / 0
# finally:
#  print('Cleaning up ...')
#  del x
# 在上述示例中,不管try子句中发生什么异常,都将执行finally子句。为何在try子句之前
# 初始化x呢?因为如果不这样做,ZeroDivisionError将导致根本没有机会给它赋值,进而导致在
# finally子句中对其执行del时引发未捕获的异常。
# 如果运行这个程序,它将在执行清理工作后崩溃。
# Cleaning up ...
# Traceback (most recent call last):
#  File "C:\python\div.py", line 4, in ?
#  x = 1 / 0
# ZeroDivisionError: integer division or modulo by zero
# 虽然使用del来删除变量是相当愚蠢的清理措施,但finally子句非常适合用于确保文件或网
# 络套接字等得以关闭,这将在第14章详细介绍。
# 也可在一条语句中同时包含try、except、finally和else(或其中的3个)。
# try:
#  1 / 0
# except NameError:
#  print("Unknown variable")
# else:
#  print("That went well!")
# finally:
#  print("Cleaning up.")

# 8.4 异常和函数
# 异常和函数有着天然的联系。如果不处理函数中引发的异常,它将向上传播到调用函数的地
# 方。如果在那里也未得到处理,异常将继续传播,直至到达主程序(全局作用域)。如果主程序
# 中也没有异常处理程序,程序将终止并显示栈跟踪消息。来看一个示例:
# >>> def faulty():
# ... raise Exception('Something is wrong')
# ...
# >>> def ignore_exception():
# ... faulty()
# ...
# >>> def handle_exception():
# ... try:
# ... faulty()
# ... except:
# ... print('Exception handled')
# ...
# >>> ignore_exception()
# Traceback (most recent call last):
#  File '<stdin>', line 1, in ?
#  File '<stdin>', line 2, in ignore_exception
#  File '<stdin>', line 2, in faulty
# Exception: Something is wrong
# >>> handle_exception()
# Exception handled
# 如你所见,faulty中引发的异常依次从faulty和ignore_exception向外传播,最终导致显示
# 一条栈跟踪消息。调用handle_exception时,异常最终传播到handle_exception,并被这里的
# try/except语句处理。

# 8.5 异常之禅
# 异常处理并不是很复杂。如果你知道代码可能引发某种异常,且不希望出现这种异常时程序
# 终止并显示栈跟踪消息,可添加必要的try/except或try/finally语句(或结合使用)来处理它。
# 有时候,可使用条件语句来达成异常处理实现的目标,但这样编写出来的代码可能不那么自
# 然,可读性也没那么高。另一方面,有些任务使用if/else完成时看似很自然,但实际上使用
# try/except来完成要好得多。下面来看两个示例。
# 假设有一个字典,你要在指定的键存在时打印与之相关联的值,否则什么都不做。实现这种
# 功能的代码可能类似于下面这样:
# def describe_person(person):
#  print('Description of', person['name'])
#  print('Age:', person['age'])
#  if 'occupation' in person:
#  print('Occupation:', person['occupation'])
# 如果你调用这个函数,并向它提供一个包含姓名Throatwobbler Mangrove和年龄42(但不包
# 含职业)的字典,输出将如下:
# Description of Throatwobbler Mangrove
# Age: 42
# 如果你在这个字典中添加职业camper,输出将如下:
# Description of Throatwobbler Mangrove
# Age: 42
# Occupation: camper
# 这段代码很直观,但效率不高(虽然这里的重点是代码简洁),因为它必须两次查找
# 'occupation'键:一次检查这个键是否存在(在条件中),另一次获取这个键关联的值,以便将
# 其打印出来。下面是另一种解决方案:
# def describe_person(person):
#  print('Description of', person['name'])
#  print('Age:', person['age'])
#  try:
#  print('Occupation:', person['occupation'])
#  except KeyError: pass
# 在这里,函数直接假设存在'occupation'键。如果这种假设正确,就能省点事:直接获取并
# 打印值,而无需检查这个键是否存在。如果这个键不存在,将引发KeyError异常,而except子句
# 将捕获这个异常。
# 你可能发现,检查对象是否包含特定的属性时,try/except也很有用。例如,假设你要检查
# 一个对象是否包含属性write,可使用类似于下面的代码:
# try:
#  obj.write
# except AttributeError:
#  print('The object is not writeable')
# else:
#  print('The object is writeable')
# 在这里,try子句只是访问属性write,而没有使用它来做任何事情。如果引发了AttributeError
# 异常,说明对象没有属性write,否则就说明有这个属性。这种解决方案可替代7.2.9节介绍的使
# 用getattr的解决方案,而且更自然。具体使用哪种解决方案,在很大程度上取决于个人喜好。
# 请注意,这里在效率方面的提高并不大(实际上是微乎其微)。一般而言,除非程序存在性能
# 方面的问题,否则不应过多考虑这样的优化。关键是在很多情况下,相比于使用if/else,使用
# try/except语句更自然,也更符合Python的风格。因此你应养成尽可能使用try/except语句的习惯①。

# 8.6 不那么异常的情况
# 如果你只想发出警告,指出情况偏离了正轨,可使用模块warnings中的函数warn。
# >>> from warnings import warn
# >>> warn("I've got a bad feeling about this.")
# __main__:1: UserWarning: I've got a bad feeling about this.
# >>>
# 警告只显示一次。如果再次运行最后一行代码,什么事情都不会发生。
# 如果其他代码在使用你的模块,可使用模块warnings中的函数filterwarnings来抑制你发出
# 的警告(或特定类型的警告),并指定要采取的措施,如"error"或"ignore"。
# >>> from warnings import filterwarnings
# >>> filterwarnings("ignore")
# >>> warn("Anyone out there?")
# >>> filterwarnings("error")
# >>> warn("Something is very wrong!")
# Traceback (most recent call last):
#  File "<stdin>", line 1, in <module>
# UserWarning: Something is very wrong!
# 如你所见,引发的异常为UserWarning。发出警告时,可指定将引发的异常(即警告类别),
# 但必须是Warning的子类。如果将警告转换为错误,将使用你指定的异常。另外,还可根据异常
# 来过滤掉特定类型的警告。
# >>> filterwarnings("error")
# >>> warn("This function is really old...", DeprecationWarning)
# Traceback (most recent call last):
#  File "<stdin>", line 1, in <module>
# DeprecationWarning: This function is really old...
# >>> filterwarnings("ignore", category=DeprecationWarning)
# >>> warn("Another deprecation warning.", DeprecationWarning)
# >>> warn("Something else.")
# Traceback (most recent call last):
#  File "<stdin>", line 1, in <module>
# UserWarning: Something else.
# 除上述基本用途外,模块warnings还提供了一些高级功能。如果你对此感兴趣,请参阅库参考手册。

# 8.7 小结
# 本章介绍了如下重要主题。
#  异常对象:异常情况(如发生错误)是用异常对象表示的。对于异常情况,有多种处理
# 方式;如果忽略,将导致程序终止。
#  引发异常:可使用raise语句来引发异常。它将一个异常类或异常实例作为参数,但你也
# 可提供两个参数(异常和错误消息)。如果在except子句中调用raise时没有提供任何参数,
# 它将重新引发该子句捕获的异常。
#  自定义的异常类:你可通过从Exception派生来创建自定义的异常。
#  捕获异常:要捕获异常,可在try语句中使用except子句。在except子句中,如果没有指
# 定异常类,将捕获所有的异常。你可指定多个异常类,方法是将它们放在元组中。如果
# 向except提供两个参数,第二个参数将关联到异常对象。在同一条try/except语句中,可
# 包含多个except子句,以便对不同的异常采取不同的措施。
#  else子句:除except子句外,你还可使用else子句,它在主try块没有引发异常时执行。
#  finally:要确保代码块(如清理代码)无论是否引发异常都将执行,可使用try/finally,
# 并将代码块放在finally子句中。
#  异常和函数:在函数中引发异常时,异常将传播到调用函数的地方(对方法来说亦如此)。
#  警告:警告类似于异常,但(通常)只打印一条错误消息。你可指定警告类别,它们是
# Warning的子类。

# 8.7.1 本章介绍的新函数
# 函 数                                                       描 述
# warnings.filterwarnings(action,category=Warning, ...)     用于过滤警告
# warnings.warn(message, category=None)                     用于发出警告











































  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

weixin_44119674

觉得有帮助,鼓励下吧

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值