python变量无需创建赋值_你不知道的Python特性,其实可以解决很多问题!

e6184fac-6b13-eb11-8da9-e4434bdf6706.png

本文会通过一些实例来介绍Python 的一些特性,每个实例都会解决具体的问题和难题。

  • 创建有意义的名称和使用变量
  • 使用大整数和小整数
  • 在浮点数、小数和分数之间选择
  • 在真除法和floor 除法之间选择

floor 除法就是向下取整除法。向上取整除法是ceiling。

创建有意义的名称和使用变量

如何确保程序易于理解呢?要编写富有表现力的代码,一个核心要素就是使用有意义的名称。但什么是有意义的呢?在本实例中,我们将回顾一些创建有意义的Python名称的通用规则。

我们还将介绍Python 的一些不同形式的赋值语句,如用同一条语句为多个变量赋值。

一、准备工作

创建名称的核心问题是:被命名的是什么?

对于软件,我们需要一个描述被命名对象的名称。显然,像x 这样的名称不是很有描述性,它似乎并不指向实际的事物。模糊的非描述性名称在一些程序设计中很常见,令人十分痛苦。当使用它们时,无助于其他人理解我们的程序。描述性名称则一目了然。

在命名时,区分解决方案域和问题域(真正想要解决的问题)也很重要。解决方案域包括Python、操作系统和互联网的技术细节。不需要深入的解释,任何人在阅读代码时都可以看到解决方案。然而,问题域可能因技术细节而变得模糊。我们的任务是使问题清晰可见,而精心挑选的名称将对此有所帮助。

二、实战演练

首先看看如何命名,然后再学习如何为对象分配名称。

1. 明智地选择名称

在纯技术层面上,Python 名称必须以字母开头。它们可以包括任意数量的字母、数字和下划线。因为Python 3 基于Unicode,所以字母不限于拉丁字母。虽然通常使用拉丁字母A~Z,但这不是必须遵循的规定。

当创建一个描述性变量时,我们需要创建既具体又能表达程序中事物之间关系的名称。一种广泛使用的命名技巧就是创建“从特殊到一般”这种风格的长名称。

选择名称的步骤如下。

(1) 名称的最后一部分是事物的广义概要。有时候,仅此一部分就能满足命名的需要,靠上下文提供其余的信息。稍后将介绍一些典型的广义概要的类别。

(2) 在应用程序或问题域周围使用前缀限定名称。

(3) 如有必要,使用更精确和专用的前缀,以阐明它与其他类、模块、包、函数和其他对象的区别。对前缀有疑问时,回想一下域名的工作原理。例如,mail.google.com 这个名称表明了从特殊到一般的三个级别。三个级别的命名并不罕见,我们经常采用这种命名方法。

(4) 根据在Python 中的使用方法来命名。需要命名的事物有三大类,如下所示。

  • 类:类的名称能够概述类中的所有对象。这些名称通常使用大驼峰命名法(Capitalized-CamelCase)。类名的第一个字母大写,强调它是一个类,而不是类的实例。类通常是一个通用的概念,很少用于描述有形的事物。
  • 对象:对象的名称通常使用蛇底命名法(snake_case)。名称全部小写,单词之间使用多个下划线连接。在Python 中,一切皆是对象,包括变量、函数、模块、包、参数、对象的属性、类的方法等。
  • 脚本和模块文件:这些文件是Python 看到的真正的操作系统资源。因此,文件名应遵循Python对象的约定,使用字母、下划线并以 .py 扩展名结尾。单从技术上说,你可天马行空地设置文件名。但是,不遵循Python 规则的文件名可能难以用作模块或包的名称。

如何选择名称中广义类别的那一部分呢?通用类别取决于讨论的是事物还是事物的属性。虽然世界上有很多事物,但我们仍然可以创建一些有用的广义分类,例如文档、企业、地点、程序、产品、过程、人、资产、规则、条件、植物、动物、矿物等。

然后可以用修饰语来限定这些名称:

FinalStatusDocument

ReceivedInventoryItemName

第一个示例是Document 类,我们通过添加一个前缀对其进行了略微的限定,即StatusDocument,又通过将其命名为FinalStatusDocument 来进一步限定。 第二个示例是Name 类,我们通过详细说明它是一个ReceivedInventoryItemName 来对其进行限定。该示例需要一个4 个级别的名称来阐明。

对象通常具有特性(property)或者属性(attribute)。它们应当是完整名称的一部分,可以根据其表示的信息类型进行分解,如数量、代码、标识符、名称、文本、日期、时间、日期时间、图片、视频、声音、图形、值、速率、百分比、尺寸等。

命名的思路就是把狭义、详细的描述放在最前面,把宽泛的信息放在最后:

measured_height_value

estimated_weight_value

scheduled_delivery_date

location_code

在第一个示例中,height 限定了更一般的表示术语value,而measured_height_value 做了进一步限定。通过这个名称,可以思考一下其他与hight 相关的变体。类似的思想也适用于weight_value、delivery_date 和location_code。这些名称都有一个或者两个限定前缀。

需要避免的情况

切勿使用经过编码的前缀或后缀去描述详细的技术信息。不要使用f_measured_height_value 这样的名称,其中f 可能指的是浮点数。这种命名方法通常被称为匈牙利命名法(Hungarian Notation)。像measured_height_value 这样的变量可以是任意数字类型,Python 会做所有必要的转换。技术性修饰对于代码阅读者并没有多大帮助,因为类型说明可能造成误导甚至错误。

不要浪费太多的精力使名称看起来属于哪个类别。不要使用SpadesCardSuit、ClubsCardSuit 这样的名称。Python 有许多种命名空间,包括包、模块和类,命名空间对象会把相关的名称收集起来。如果将这些名称添加到CardSuit 类中,就可以使用CardSuit.Spades,以类作为命名空间来区分其他相似的名称。

2. 为对象分配名称

Python 没有使用静态变量定义。当把名称分配给对象时,就会创建变量。把对象看作处理过程的核心非常重要,变量有点像标识对象的标签。使用基本赋值语句的方法如下。

(1) 创建对象。在许多示例中,对象以字面量的形式创建。我们使用355 或113 作为Python 中整数对象的字面量表示,也可以使用FireBrick 表示字符串,或使用(178,34,34)表示元组。

(2) 编写如下类型的语句:变量 = 对象。例如:

>>> circumference_diameter_ratio = 355/113>>> target_color_name = 'FireBrick'>>> target_color_rgb = (178, 34, 34)

我们创建了一些对象并把它们赋值给了变量。第一个对象是数值计算的结果,接下来的两个对象是简单的字面量。对象通常由包含函数或类的表达式创建。

上面的基本赋值语句并不是唯一的赋值方式,还可以使用链式赋值的方式,将一个对象分配给多个变量,例如:

>>> target_color_name = first_color_name = 'FireBrick'

上例为同一个字符串对象创建了两个名称。可以通过检查Python 使用的内部ID 值来确认这两个对象是否为同一个对象:

>>> id(target_color_name) == id(first_color_name)True

结果表明,这两个对象的内部ID 值是相同的。

相等测试使用==,简单赋值使用=。

随后介绍数字和集合时将会说明结合运算符进行赋值的方法。例如:

>>> total_count = 0>>> total_count += 5>>> total_count += 6>>> total_count11

我们通过运算符进行了增量赋值。total_count + = 5 与total_count = total_count + 5是等价的。增量赋值的优点在于简化了表达式。

三、工作原理

本实例创建名称的方法遵循如下模式:狭义的、更具体的限定符放在前面,更宽泛的、不太特定的类别放在最后。这种方法遵守用于域名和电子邮件地址的通用约定。

例如,域名mail.google.com 包括特定的服务、更通用的企业和最后的非常通用的域,这遵循了从窄到宽的原则。

又如,service@packtpub.com 以具体的用户名开始,然后是更通用的企业,最后是非常通用的域。甚至用户名(PacktPub)也是一个具有两部分的名称,包括限定的企业名称(Packt),以及更广泛的行业[Pub,“Publishing”(出版)的简写,而不是“Public House”(酒吧)的简写]。

赋值语句是为对象命名的唯一途径。

四、补充内容

我们将在所有实例中使用描述性名称。

Tip:没有遵循这种模式的现有软件应当保持现状。一般而言,最好与遗留软件保持一致,而不是强加新规则,即使新规则更好。

几乎每个示例都涉及变量赋值。变量赋值是有状态的面向对象编程的核心。

五、延伸阅读

描述性命名是一个正在研讨的主题,涉及两个方面——语法和语义。Python 语法的设想起始于著名的PEP-8(Python Enhancement Proposal number 8)。PEP-8 建议使用CamelCase 和snake_case 命名风格。

此外,务必进行以下操作:

>>> import this

这有助于领悟Python 的设计哲学。

有关语义的信息,请参阅遗留的UDEF 和NIEM 命名和设计规则标准(http://www.opengroup.org/udefinfo/AboutTheUDEF.pdf)。有关元数据和命名的详细信息,请参阅ISO11179(https://en.wikipedia.org/wiki/ISO/IEC_11179)。

使用大整数和小整数

许多编程语言区分整数、字节和长整数,有些编程语言还存在有符号整数和无符号整数的区别。如何将这些概念与Python 联系起来呢?

答案是“不需要”。Python 以统一的方式处理所有类型的整数。对于Python,从几个字节到数百位的巨大数字,都是整数。

一、准备工作

假设我们需要计算一些非常大的数字,例如,计算一副52 张的扑克牌的排列数。52! = 52 × 51×50 × … × 2 × 1,这是一个非常大的数字。可以在Python 中实现这个运算吗?

二、实战演练

别担心!Python 表现得好像有一个通用的整数类型,涵盖了所有整数,从几个字节到填满所有内存的整数。正确使用整数的步骤如下。

(1) 写下你需要的数字,比如一些小数字:355,113。实际上,数字的大小没有上限。

(2) 创建一个非常小的值——单个字节,如下所示:

>>> 22

或者使用十六进制:

>>> 0xff255

后面的实例中将讨论只含有一个值的字节序列:

>>> b'xfe'b'xfe'

严格说来,这不是一个整数。它有一个前缀b',这表明它是一个一字节序列(1-byte sequence)。

(3) 通过计算创建一个很大的数字。例如:

>>> 2 ** 2048323...656

该数字有617 个数位,这里并没有完全显示。

三、工作原理

Python 内部使用两种数字,两者之间的转换是无缝且自动的。

对于较小的数字,Python 通常使用4 字节或8 字节的整数值。细节隐藏在CPython 的内核中,并依赖于构建Python 的C 编译器。

对于超出sys.maxsize 的较大数字,Python 将其切换到大整数——数字(digit)序列。在这种情况下,一位数字通常意味着30 位(bit)的值。

一副52张的扑克牌有多少种排列方法?答案是52! ≈ 8 ×10^67。我们将使用math 模块的factorial函数计算这个大整数,如下所示:

>>> import math>>> math.factorial(52)80658175170943878571660636856403766975289505440883277824000000000000

这些巨大的数字工作得非常完美!

计算52! 的第一部分(从52 × 51 × 50 × …一直到约42)可以完全使用较小的整数来执行。在此之后,其余的计算必须切换到大整数。我们看不到切换过程,只能看到结果。

通过下面的示例可以了解整数内部的一些细节。

>>> import sys>>> import math>>> math.log(sys.maxsize, 2)63.0>>> sys.int_infosys.int_info(bits_per_digit = 30, sizeof_digit = 4)

sys.maxsize 的值是小整数中的最大值。我们通过计算以2 为底的对数来说明这个数字需要多

少位。

通过计算可知,Python 使用63 位值来表示小整数。小整数的范围是从-2^64 到2^63-1。在此范围之外,使用大整数。

通过sys.int_info 的值可知,大整数是使用30 位的数字序列,每个数字占用4 字节。

像52! 这样比较大的值,由8 个上述30 位的数字组成。一个数字需要30 位来表示可能有些令人困惑。以用10 个符号表示十进制(base 10)的数字为例,我们需要2**30 个不同的符号来表示这些大数字的每位数。

涉及多个大整数值的计算可能会消耗相当大的内存空间。小数字怎么办呢? Python 如何跟踪大量的小数字,如1 和0?

对于常用的数字(-5 到256),Python 实际上创建了一个私有的对象池来优化内存管理。你可以在检查整数对象的id()值时得到验证。

>>> id(1)4297537952>>> id(2)4297537984>>> a = 1 + 1>>> id(a)4297537984

我们显示了整数1 和整数2 的内部id。当计算a 的值时,结果对象与对象池中的整数2 对象是同一个对象。

当你练习这个示例时,id()值可能跟示例不同。但是,在每次使用值2 时,将使用相同的对象。在我的笔记本电脑上,对象2 的id 等于4297537984。这种机制避免了在内存里大量存放对象2 的副本。

这里有个小技巧,可以看出一个数字到底有多大。

>>> len(str(2 ** 2048))617

通过一个计算得到的数字创建一个字符串,然后查询字符串的长度。结果表明,这个数字有617个数位。

四、补充知识

Python 提供了一组丰富的算术运算符:+、- 、*、/、//、%和**。/和//用于除法,**将执行幂运算。

对于位处理,还有其他一些运算符,比如&、^、|、<>。这些运算符在整数的内部二进制表示上逐位操作。它们分别计算二进制与二进制异或二进制或左移右移

虽然这些运算符也同样适用于大整数,但是逐位操作对于大整数来说并没有实际意义。一些二进制文件和网络协议会要查看数据的单个字节中的位。

可以通过bin()函数查看应用这些运算符的运行结果。示例如下:

>>> xor = 0b0011 ^ 0b0101>>> bin(xor)'0b110'

先使用0b0011 和0b0101 作为两个位串。这有助于准确说明数字的二进制表示。然后将异或(^)运算符应用于这两个位序列。最后使用bin()函数查看位串形式的结果。可以通过结果仔细观察各个位,了解操作符的实际功能。

可以把一个字节分解为若干部分。假设我们要将最左边的2 个位与其他6 个位分开,其中一种方法是使用位操作(bit-fiddling)表达式,例如:

>>> composite_byte = 0b01101100>>> bottom_6_mask = 0b00111111>>> bin(composite_byte >> 6)'0b1'>>> bin(composite_byte & bottom_6_mask)'0b101100'

这里先定义了一个composite_byte,其中最高有效的2 位为01,最低有效的6 位为101100。再使用>>移位运算符将composite_byte 的值右移6 个位置,去除最低有效位并保留2 个最高有效位。然后使用&运算符和掩码来进行操作。掩码中值为1 的位,在结果中保留对应位置的值;掩码中值为0 的位,结果中对应位置的值被设置为0。

五、延伸阅读

关于整数操作的详细信息,请参阅https://www.python.org/dev/peps/pep-0237/。

在浮点数、小数和分数之间选择

Python 提供了多种处理有理数和无理数近似值的方法。3 种基本选择如下:

 浮点数

 小数

 分数

有这么多种选择,那么怎样选择才合适呢?

一、准备工作

确定我们的核心数学期望值很重要。如果不确定已拥有的数据类型或者想要得到的结果,真的不应该开始编码。我们需要退一步,用铅笔和纸来演算一下。

除了整数,在数学中涉及的数字还有3 种。

(1) 货币:如美元、美分或欧元。货币通常具有固定的小数位数。另外还有很多舍入规则,例如,可以用这些规则确定 $2.95 的7.25% 是多少美分。

货币的最小单位一般为0.01 元

(2) 有理数或分数:使用美制单位的英尺和英寸,或在烹饪中使用杯和盎司进行测量时,经常需要使用分数。把一个8 人量的食谱缩减为5 人量时,要用5/8 作为缩放因子进行分数运算。如何将这种方法应用到2/3 杯米,并得到适用于厨房量具的测量值呢?

(3) 无理数:包括所有其他类型的计算。必须注意,数字计算机只能逼近这些无理数,而我们偶尔会看到近似值的一些奇怪现象。浮点近似值运算非常快,但有时会出现截断问题。

当计算涉及前两种数字时,应当避免使用浮点数。

二、实战演练

本实例将分别讨论这3 种数字。首先讨论货币值计算。然后讨论有理数计算,以及无理数或浮点数计算。最后讨论这些类型之间的显式转换。

1. 货币值计算

在处理货币值时,应当坚持使用decimal 模块。如果使用Python 内置的浮点数,将会遇到数字的舍入和截断问题。

(1) 为了处理货币值,首先从decimal 模块导入Decimal 类。

>>> from decimal import Decimal

(2) 从字符串或整数创建Decimal 对象。

>>> from decimal import Decimal>>> tax_rate = Decimal('7.25')/ Decimal(100)>>> purchase_amount = Decimal('2.95')>>> tax_rate * purchase_amountDecimal('0.213875')

tax_rate 由两个Decimal 对象构建,其中一个基于字符串,另一个基于整数。我们可以直接使用Decimal('0.0725'),而不显式地执行除法。

结果稍微大于$0.21,因为我们计算出了小数位的全部数字。

(3) 如果通过浮点数创建Decimal 对象,那么将得到异常的浮点近似值。应当避免混用 Decimal和float。为了舍入到最近的便士(penny),创建一个penny 对象。

>>> penny = Decimal('0.01')

(4) 使用penny 对象量化数据。

>>> total_amount = purchase_amount + tax_rate * purchase_amount>>> total_amount.quantize(penny)Decimal('3.16')

上述示例演示了如何使用默认的ROUND_HALF_EVEN 舍入规则。

舍入规则有很多种,Decimal 模块提供了所有舍入规则。例如:

>>> import decimal>>> total_amount.quantize(penny, decimal.ROUND_UP)Decimal('3.17')

本示例显示了使用另一种不同的舍入规则的结果。

2. 分数计算

当计算中含有精确分数值时,可以使用fractions 模块。该模块提供了便于使用的有理数。处理分数的流程如下。

(1) 从fractions 模块导入Fraction 类。

>>> from fractions import Fraction

(2) 由字符串、整数或整数对创建Fraction 对象。如果由浮点数创建Fraction 对象,可能会遇到浮点近似值的异常现象。当分母是2 的幂时,一切正常。

>>> from fractions import Fraction>>> sugar_cups = Fraction('2.5')>>> scale_factor = Fraction(5/8)>>> sugar_cups * scale_factorFraction(25, 16)

我们从字符串2.5 创建了第一个分数,从浮点计算5/8 创建了第二个分数。因为分母是2 的幂,所以计算结果非常准确。

25/16——结果是一个看起来很复杂的分数,那么它的最简分数是多少呢?

>>> Fraction(24, 16)Fraction(3, 2)

结果表明,我们使用大约一杯半的米就可以完成5 人量的食谱。

3. 浮点近似值

Python 的内置浮点(float)类型能够表示各种各样的值。对于是否使用浮点值,选择的关键在于浮点值通常涉及近似值。在某些情况下,特别是在做涉及2 的幂的除法时,结果是一个精确的分数。

在其他情况下,浮点值和分数值之间可能存在细小的差异,这反映了浮点数的实现与无理数的数学理想之间的差异。

(1) 要使用浮点数,经常需要舍入值来使它们看起来合理。所有浮点计算的结果都是近似值。

>>>(19/155) * (155/19)0.9999999999999999

(2) 上面的值在数学上应该为1。由于float 使用的是近似值,所以结果并不精确。虽然这个结果与1 相差不多,但仍然错了。当进行适当的舍入时,这个值会更有意义。

>>> answer =(19/155) * (155/19)>>> round(answer, 3)1.0

(3) 认识误差项。在本例中,我们知道确切的答案,所以可以将计算结果与已知的正确答案进行比较。下面的示例给出的通用误差项适用于所有浮点数。

>>> 1-answer1.1102230246251565e-16

对于大多数浮点误差,典型值约为10^16。Python 有一些聪明的规则,有时通过自动舍入隐藏这个错误。但是,对于本示例,错误并没有隐藏。

这是一个非常重要的推论。

Tip:不要比较浮点值是否完全相等。

在浮点数之间使用精确的==测试时,如果近似值相差一个位,代码就会出现问题。

4. 数字的类型转换

可以使用float()函数从其他类型的值创建一个float 值。例如:

>>> float(total_amount)3.163875>>> float(sugar_cups * scale_factor)1.5625

在第一个示例中,我们将Decimal 值转换为float 值。在第二个示例中,我们将Fraction 值转换为float 值。

正如刚刚看到的,我们永远不想将float 转换为Decimal 或Fraction:

>>> Fraction(19/155)Fraction(8832866365939553, 72057594037927936)>>> Decimal(19/155)Decimal('0.12258064516129031640279123394066118635237216949462890625')

在第一个示例中,我们在整数之间进行计算,创建了一个具有已知截断问题的float 值。当我们从截断的float 值创建一个Fraction 时,得到的是一些暴露了截断问题的数字。

类似地,第二个示例从float 创建了 Decimal 值。

三、工作原理

对于数字类型,Python 提供了多种运算符:+、-、*、/、//、%和**。这些运算符用于加法、减法、乘法、真除法、截断除法、取模和幂运算。

Python 擅长各种数字类型之间的转换。我们可以混合使用整数(int)和浮点数(float),整数将被转换为浮点数,以提供最准确的答案。类似地,还可以混合使用整数(int)和分数(Fraction),结果将是分数(Fractions)。我们也可以混合使用整数(int)和小数( Decimal)。但是,不能随便混合使用小数( Decimal)与浮点数(float),或小数( Decimal)与分数(Fraction),在这样操作之前,需要进行显式转换。

必须注意的是,float 值是真正的近似值。虽然Python 语法允许将数字写为小数值,但它们在Python 内部并不是按小数处理的。

我们可以使用普通的十进制数值在Python 中编写如下值:

>>> 8.066e + 678.066e + 67

在内部使用的实际值将包含上述十进制值的一个二进制近似值。

该示例(8.066e + 67)中的内部值为:

>>> 6737037547376141/2 ** 53 * 2 ** 2268.066e + 67

分子是一个大数字,6737037547376141;分母总是2^53。由于分母是固定的,因而所得到的分数只能有53 位有意义的数据。由于53 位之外的位不可用,因此值可能会被截断。这导致了我们的理想化抽象和实际数字之间的微小差异。指数(2^226)需要将分数缩放到适当的范围。

在数学上,即6737037547376141 * 2^226/2^53。

可以使用math.frexp()查看数字的内部细节:

>>> import math>>> math.frexp(8.066E + 67)(0.7479614202861186, 226)

结果的两个部分分别称为尾数(mantissa)和指数(exponent)。如果将尾数乘以2^53,那么将得到一个整数,这个整数是二进制分数的分子。

前面提到的误差项与该值非常地匹配:10^16 ≈ 2^53。

与内置的float 不同,Fraction 是两个整数值的精确比率。正如前边所示,Python 中的整数可能非常大。我们可以创建包含具有大量数位的整数的比率,并且不受固定分母的限制。

类似地,Decimal 值基于非常大的整数值和用于确定小数点位置的缩放因子。这些数字可以是巨大的,不会有特殊的表示问题。

为什么要使用浮点数?原因有两个

并不是所有可计算的数字都可以表示为分数。这就是数学家引入(或者可能是发现)无理数的原因。内置的float 类型与无理数的数学抽象非常接近。例如,像√2 这样的值就不能表示为分数。

此外,浮点值运算非常快。

四、补充知识

Python 的math 模块包含许多用于处理浮点值的专用函数。该模块包括了常用的函数,如平方根、对数和各种三角函数,还包括其他一些函数,如伽玛函数、阶乘函数和高斯误差函数。

math 模块也包含了一些可以精确计算浮点数的函数。例如,math.fsum()函数将比内置sum()函数更加周密地计算浮点和。math.fsum()函数很少出现近似值问题。

还可以使用math.isclose()函数比较两个浮点值是否接近相等:

>>> (19/155)*(155/19) == 1.0False>>> math.isclose((19/155)*(155/19), 1)True

该函数提供了一种正确比较浮点数的方法。

Python 还提供了复数数据类型。复数由实部和虚部组成。在Python 中,3.14 + 2.78j 代表复数 3.14 + 2.78√-1。Python可以在浮点数和复数之间进行轻松的转换。Python提供了一组常用的复数运算符。

为了更好地支持复数,Python 内置了cmath 包。例如,cmath.sqrt()函数将返回一个复数值,而不是在求负数的平方根时抛出异常。示例如下:

>>> math.sqrt(-2)Traceback (most recent call last):File "
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值