记录一次腾讯Python岗面试笔试总结python+tkinter仿制win10标准型计算器,Python高级工程师面试题及答案

1.设计思路


计算器分成两个部分——显示和触控。

1.1显示部分

显示部分分为上显示屏和下显示屏。下显示屏是表示每一步计算的数值,**也只显示数值,**上显示屏表示的是计算过程。理论上,下屏应为单行显示,可复制,可通过键盘输入数字及运算符(该功能尚未完成),因此,我们选择的控件应为entry,其功能与text相似,而上屏的作用是显示计算过程,里边的元素不可复制,因此上屏选用的控件为label。我们知道,label不能直接更改数据,所以这里引用了可变追踪对象StringVar(),通过改变这个对象的值来改变label显示的值,同样的下层entry控件也需要这个可变对象,因为我们计算操作是使用鼠标点击按钮来实现计算,而不是通过键盘输入数字来计算。

1.2触控部分

这一部分是整个组件的核心。我们需要对按钮绑定事件,以保证每次点击按钮能触发对应的事件。24个按钮里边无非就4种类型 数字(0~9),运算符(加减乘除等于),算法(求倒数求平方开根号相反数)以及回退操作(删除初始化)。在此,我们必须要设定一些变量保存数据,方便我们计算。我设置了四个变量,factor1,  factor2, operator, last_click用于记录因子1,因子2,运算符,以及上一次点击。为了简化计算我是直接使用了eval函数和pow函数,如果对这两个函数算法的实现思路感兴趣的朋友可以了解一下我这两篇文章。

python pow函数——幂运算 快速幂算法实现思路_lishuaigell的博客-CSDN博客说明python 内置pow函数用于实现幂的运算,在这里我使用的是快速幂算法实现pow函数功能。快速幂快速幂算法本质上基于的是分治思想。优点:其时间复杂度为 O (log₂N), 与暴力遍历时间复杂度O (N)相比效率有了质的提高。待完善之处:指数暂支持输入整数。思路不断将高次幂拆分成低次幂,直到低次幂无法再拆分为止。而此时低次幂的值就显而易见了,就是底数(1次幂)。然后通过最低次幂(1次幂)不断往上求取更高次幂的值,最终得出结果。我以2的10次方为例演示一实现思b路。外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传https://blog.csdn.net/lishuaigell/article/details/122474662

python eval函数——求解字符串表达式 算法实现思路_lishuaigell的博客-CSDN博客说明应对不同情况下的字符串表达式求值,本篇提供双栈和单栈两种解法。当表达式较为简单不存在括号时,可使用单栈求解,其他情况使用双栈。算法一、单栈当表达式不存在括号时,如"3+2*5-4/2"可使用单栈求解。思路我们遍历表达式,每遇到一个运算符就对运算符前面的数字进行相应操作。定义了一个栈,将消除乘除号后的数字添进栈中,最后使用sum方法将栈内元素求和得出最终结果。当遇到"+“号时,将符号前面的数字(称为num)压入栈中当遇到”-“号时,将(-num)压入栈中当遇到”*"外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传https://blog.csdn.net/lishuaigell/article/details/122114239

记住,在这里你必须要知道每个按钮间都不存在互斥现象,千万不要想当然的以为点了这个按钮之后就不会点击那个按钮,你必须要料想所有可能出现的结果。

1.3思路图解

从开始设计窗口到设计按钮框架大致的思路可以用下面的gif表示

你们看一下这个思路图,有些地方我在下面做出了相应的解释。

解释:

看到“删除”的分支语句,删除一个字符指的是删除下显示屏的一个字符。

看到“加减乘除”的分支语句,重显示的意思就是此时下显示屏显示的值是虚值(即运算结果),当下一次输入数字的时候显示的值会被覆盖掉。

记录前面输入的数字:就是获取此时下显示屏的值。因为运算符不会出现在下显示屏,**下显示屏只会记录数字,**每出现一次运算符后将会读取一次数据之后下显示屏会处于重显示状态。

直接开平方: 因为我们计算是读取下显示屏的数据,在读取前下方数据如何改变逻辑上都是行得通的。

我以下方gif为例简单讲一下实现过程。

下方显示屏初始值是0, 输入数字后,如果第一个字符是0则需要将其覆盖,覆盖后下方显示为3。点击乘号后,因子factor1记录下方显示屏的值(3),运算符operator记录此时点击的运算符(*)。上方显示屏显示 因子1和运算符,下方显示屏处于重显示状态。当再次输入数字5的时候,5覆盖掉3的值,下方显示屏显示5,点击运算符+号后,因为因子1存在了,5的值赋值给因子2。然后就使用eval函数对“因子1 运算符 因子2”这个表达式进行求解,将的出来的结果(15)赋值给因子1,上方显示屏继续显示 因子1和运算符,下方显示屏再回到重显示状态。点击6,下方显示为6,再点击等号。用因子2记录下方显示屏的值6,然后再用eval对“因子1 运算符 因子2”表达式进行求解,求解后上方显示计算过程,下方继续处于重显示状态。

看到这里细心的朋友会发现我前面说这些按钮只有四种类型,但是在上方的思路图中却出现了不止四条的分支,也就是出现了不止四种情况,这是为什么呢?我只能说个人习惯吧,一开始设计的时候我就把他们分开了,所以现在写的时候也这么写了,但是存在个别按钮(等号=),不分开我也要将它分开,或许我将它搞得太特别了。至于为什么,在详细步骤那里我再好好跟大伙说说原因。

其实,上方思路图只展示了常规使用计算器的思路,而****只考虑上方几种情况是远远不够的,为保证计算器稳定性我们必须考虑更多情形,即,非常规情况**。**

2.详细步骤


2.1创建窗口对象

首先定义类TkWindows,之后导入tkinter包,在类的init方法里边创建窗口对象,以及设定好尺寸,名称等参数。尺寸的话我根据win10计算器设计的,虽然还是有差别,凑合用吧,设置窗体尺寸和按钮框架显示框架的尺寸我也花了不少时间。设置完尺寸后要设置最大拉伸长度,因为拉伸后那些按钮和框架不会跟着拉伸,还有就是设定窗口名了。

代码如下:

import tkinter

class TkWindows:

def init(self):

创建窗口对象

self.win = tkinter.Tk()

设置窗口宽度,高度以及窗口初始位置 x 为小写字母x 第一个加号后面参数是x轴坐标,第二个参数是y轴坐标

self.win.geometry(“360x460+570+200”)

定义拉伸的最大尺寸

self.win.maxsize(width=360, height=460)

定义窗口名称

self.win.title(“李帅哥的标准型计算器”)

设计思路部分我已经大概提过有哪些变量,哪些控件了,因此先提前在init里边创建好。

初始化数据

self.lower_display = None # 上显示屏

self.upper_display = None # 下显示屏

self.entry = None

self.label = None

self.operator = “” # 运算符

self.factor1 = “”

self.factor2 = “”

self.last_click = “” # 上一次点击

然后进入消息循环

进入消息循环

self.win = tkinter.mainloop()

在主函数调用该类

if name == ‘main’:

TkWindows()

点击运行,就能出现框体了

2.2创建显示框架

定义方法text_frame,创建一个frame框架text_frame,将该框架放置到win窗口中的上部分。

显示屏——双显

def text_frame(self):

text_frame = tkinter.Frame(self.win, width=360, height=190)

text_frame.pack(side=“top”)

frame 第一个参数为要放置的对象,第二个参数是宽度,应与窗口宽度一致,第三个参数是高度。

然后将该方法添加到init里面,就能生成这个框架了。

self.button_frame()

2.3放置显示屏

上显示屏使用的控件是label,下显示屏使用的控件是entry。它们都有一个参数叫textvariable,是用来接收可变对象,说白了就是跟可变对象绑定后,可变对象的值发生改变,显示框的值也发生改变。常见能接收的类型有StringVar() 和 IntVar()。因为我们计算是使用eval函数,里边的表达式是字符串类型的,所以我们的接收类型就使用了StringVar(),其常用的方法有get方法–获取当前显示框的文本,和set方法–设置显示框的值。之后我们会大量使用这两个方法,是不是很简单粗暴?因此在text_frame方法里面添加如下语句。

定义上下层显示屏可变追踪对象用于及时更新数据

self.lower_display = tkinter.StringVar()

self.upper_display = tkinter.StringVar()

设定下层显示的初始值

self.lower_display.set(“0”)

添加完后我们下显示屏默认会显示0,而上显示屏默认显示。

创建上显示屏label

设定上层显示组件, label——可多行显示,不可复制,不可直接通过键盘更改文本内容

self.label = tkinter.Label(text_frame, font=(“loMa”, 14),

textvariable=self.upper_display, bd=0, anchor=“se”, bg=“LightGray”)

  • text_frame: label要放置的对象。我们要把label放置在text_frame框架中。

  • font:字体。里边第一个参数是字体样式,第二个参数是字体大小。

  • textvariable:绑定可变对象。这里我们绑定的是上显示屏,其类型是StringVar()。

  • bd:边框大小。因为我们上下显示屏要看成一个整体,所以不能有边框,这里设置为0。

  • anchor:图形放置的位置。"se"表示东南部。相当于放在右下角了。说到这东西我必须吐槽一下,label明明也有justify属性(对齐方式),我把它修改为向右对齐却一点用都没有还是会居中显示,而entry修改这个属性后又能向右对齐,这给我整无语了。

  • bg:背景色。我为什么用这个颜色呢,因为我win10计算器是在pycharm下打开的,刚好那时候就显示这个色,我就把计算器调成这个颜色了,结果win10计算器颜色会变…想改其他颜色可以参考一下这个老哥@笑待人生原创库 的图片。

另外,要想查看更多tkinter命令可以查阅一下这篇文章。

Python GUI 编程(Tkinter) | 菜鸟教程 | 菜鸟教程")

创建下显示屏entry

设定下层显示组件, entry———单行输入显示,可复制,可直接通过键盘更改文本内容

self.entry = tkinter.Entry(text_frame, font=(“loMa”, 34, “bold”),

textvariable=self.lower_display, bd=0,

cursor=“circle”, justify=“right”, bg=“LightGray”)

这里的参数与label大致相似不再过多解释,在font参数那里多加了“bold”参数,表示加粗字体。下方参数多了个cursor表示鼠标图标,当我们将鼠标放上下显示屏的时候他会变成圆圈。截图截不了鼠标,各位可以自己试下,还是挺好看的。

放置显示屏

创建好显示屏后就要使用布局管理器将他们放入显示框架里面了,使用哪种布局呢?pack?虽然pack很方便,但是这里用不得pack。因为entry没有高度height属性,如果直接使用pack放置的话entry的高度会使用默认高度,很可能达不到你想要的结果。而place布局可以克服这一点,他可以自定义控件初始位置和大小,因此我们选用place布局管理器对上下显示屏进行布局。虽然label有高度属性,但是我们知道,布局管理器在同一容器里面只能使用一种,否则会报错,所以我们就统一使用place布局,并在里边设置起始位置和大小。

设定组件的放置位置及大小, entry没有高度这个属性,而默认高度显示不够美观,因为place布局可以自定义组件的高宽度,所以采用place布局

self.label.place(x=1, y=10, width=359, height=70)

self.entry.place(x=1, y=50, width=359, height=120)

x轴方向稍微空出一个像素会显得柔和些,不会那么突兀。

2.4创建按键框架

定义button_frame方法以及button_frame框架,将其放入到win窗口中的下部分。

按键

def button_frame(self):

button_frame = tkinter.Frame(self.win, width=370, height=270)

button_frame.pack(side=“bottom”)

将方法添加到init里面

self.text_frame()

2.5放置按钮

思路

遍历排列好的按钮字符串,定义行变量和列变量记录该按钮的行列值,列的值每满4个就要清零,行的值就要加一。然后使用grid布局将这些按钮根据此时行列值放置到按钮框架里面。放置的过程同时要绑定事件。事件下一小节会讲,这里就听一下概念就好。

确定按键顺序

我们根据计算器按键的顺序用一个按钮字符串存储起来,因为我们使用了中文字符,有时候一个按键的长度不为1,为了识别长度大于1的情况,我就用了花括号将按钮长度大于1的按钮名括起来。遍历时就能通过识别左右括号来确定里面按钮的值了。而长度为1的按钮直接添加到按钮框架即可。计算器按钮的布局是典型的二维表布局,所以使用grid布局管理器。先初始化变量。

设定计算器按键的顺序, 当按键名称长度大于一时用花括号括起来,方便后续判断

button_str = “%{CE}{清零}{删除}{求倒数}{求平方}{开根号}{除/}789{乘*}456{减-}123{加+}{相反数}0{小数点.}{等于=}”

ind = 0

row = 0

col = 0

length = len(button_str)

按钮放置与事件绑定

定义st变量记录按钮名称,遍历字符串,如果遇到左花括号,则在该位置使用index寻找右花括号的索引值。找离左括号最近的右括号,所以要设置查找的起始索引。找到后右花括号的位置就能使用切片获取按钮的值了,获取完值后索引移动到右花括号的位置(因为执行完一次while索引都会加1,所以就不用移动到下一个按钮的位置)。如果没有花括号则按钮名长度就是1,直接添加即可。

设置完按钮属性后将按钮放入按钮框架中,同时对按钮绑定事件,绑定事件的bind方法里面有两个参数,第一个参数是事件动作,第二个是事件对象。按钮发生相应的事件动作后,将会调用绑定的事件对象(函数)。

常见的事件动作有

  • 点击鼠标左键

  • 点击鼠标右键

  • 按下’A’键('A’可换其他按键)

  •   双击鼠标左键

每次放置后行列值都要发生相应的变化。

while ind < length:

当遇到花括号时(名称长度大于一),按键名为花括号里边的元素

if button_str[ind] == “{”:

找到离该左花括号最近的右花括号

end = button_str.index(‘}’, ind)

st = button_str[ind + 1:end]

指针移动到右花括号位置

ind = end

当名称长度为1时

else:

st = button_str[ind]

设置按钮属性

button = tkinter.Button(button_frame, text=st, font=(“loMa”, 14),

width=8, height=2)

按钮绑定事件click_button_event,当鼠标左键单击按钮时触发该事件

button.bind(“”, self.click_button_event)

使用grid网格布局放置按钮

button.grid(row=row, column=col)

col += 1

每行放置四个按钮, 每满四个换一行

if col >= 4:

row += 1

col = 0

ind += 1

2.6★定义按钮事件

重点来了。因为所有的按钮都绑定了同一个事件,所以计算器的核心算法都在这个事件里面。

先定义按钮事件,事件必须带至少一个参数,这个参数默认名为event。

定义按钮事件

def click_button_event(self, event):

我们可以通过event获取按钮的相关信息如名称,位置等。这里我们必须要获取按键名称才能对各个情况进行判断。

获取当前点击的按钮名称

button_text = event.widget[“text”]

我们由浅入深,先从容易理解的情况开始。

清零

前面我们讲过,计算器其中一个缺陷就是"%“, “CE”, “清零"三个按钮功能等价。因为我不太明白”%”, "CE"的计算逻辑,所以我直接把他俩归并到清零功能上了。(已修复CE情况,CE功能相当于将下显示屏设为0)

我们在计算器进行一些计算后点击清零会发现下显示屏变为0,上显示屏不显示,相当于回到了初始状态,所以点击清零相当于对所有数据进行了初始化。我们就定义一个初始化方法,初始化数据。(该方法在按钮事件里面定义)

对各个数据初始化

def initialize():

self.lower_display.set(“0”)

self.upper_display.set(“”)

self.factor1 = “”

self.factor2 = “”

self.operator = “”

self.last_click = “”

于是第一种情况我们就考虑完成了。

如果点击的按钮名称为清零CE%其中的一个,那么我们就调用初始化方法。(代码已更新)

if button_text in “清零CE%”:

当点击按钮为"CE"时,我们下显示屏清零。但如果上一次点击是等于号的话我们进入一次新运算,要进行初始化。

if button_text == “CE” and self.last_click != “等于=”:

self.lower_display.set(“0”)

else:

initialize()

至于为什么规定等号就进入一次新运算?可先看到下面的等号分支部分。

删除

计算器删除功能无非就是删除前面输错数字,因此我们进行判断,如果上一次点击的是数字就对其删除,否则不作响应。特别地,当上一次点击是等号的时候,上显示屏清空值,使用set方法将上显示屏设为空就好了。删除的思路就是确定下显示屏删除后是否还有值,有值就直接删除,没有值的话就设为0。

也许有朋友会有这样的一个疑惑,进行一次计算:点击数字8,再点击+号,想输入7不就输不了了?现在下显示屏还是显示8,按照上面那个删除的思路,因为上一次点击是+号不是数字,所以删不了8…这您就别担心,我在前面的设计思路提过重显示这个词吧?现在下显示屏处于重显示状态,如果下次点击是数字的话,他会直接覆盖掉之前的数字8,所以直接点击7就可以了。

因此按钮的第二个情况分支就是

elif button_text == “删除”:

删除最后一个字符

if self.last_click in “0123456789小数点.”:

分析删除一个字符后的情况

text = self.lower_display.get()[:-1]

if len(text) == 0:

self.lower_display.set(“0”)

else:

self.lower_display.set(text)

如果上一次点击是等号,则需保留下方数据,清除上方数据

elif self.last_click == “等于=”:

self.upper_display.set(“”)

记录上一次点击按钮

我们每执行完一次事件,都要记录上一次点击按钮的值,就拿删除功能而言,他也要判断上一次点击按钮是否是数字才能进行相应的操作。而有些按钮不应该被记录,这些按钮分别是“删除清零CE%”,我称这些按钮为状态按钮,因为他们只改变了计算器的状态,不会参与任何计算。

为什么要这么做呢?我打个比方,输入一个1,再输入一个1,输入第二个1的时候会判断上一个输入是否是数字,如果是的话加在它后面变成11,如果不是的话覆盖掉前面的值,变成1。显然,现在下显示屏显示是11。现在我们点击删除键,因为删除一个字符后还有值,所以现在显示变为1。此时输入一个2,如果上一次点击记录的是删除键,那么因为它不是数字,所以下显示屏会覆盖掉前面的值,显示为2,而按我们的计算思路是删除1之后继续输入数字2应该要显示12才对的,因此删除键不能参与记录上一次点击,那样的话上一次点击的按钮依旧是数字,这样就解决了数据插入的问题。

因此在事件的末尾添加如下语句。

if button_text not in “删除清零CE%”:

self.last_click = button_text

而每执行完一次事件后下显示屏应该都要处于最新显示的状态。当输入数字的长度大于显示长度时应显示后面的数字。比如输入数字12345,而显示屏只能显示3个数,那么这时显示屏显示的数字是345。

每执行完一次后将光标移动到最后面位置(考虑到有时候会通过键盘输入某些字符)

self.entry.icursor(“end”)

当输入的文本长度大于文本框长度时会显示更近输入的内容

self.entry.xview(“end”)

虽然我没有完善键盘输入的功能,但我还是设置了每次执行完一次事件光标移动到尾部的过程,因为有时候吧,偶尔输入一两个数字,不输入其他的话还是可以的。

◆等于

这次先上代码再说明情况

elif button_text == “等于=”:

出现多次点击等号时保留因子二不变,让结果与因子二计算

if self.last_click != button_text:

仅在首次点击等号时记录因子二

self.factor2 = self.lower_display.get()

正常情况直接计算结果

if self.operator:

expression = self.factor1 + self.operator + self.factor2

非正常情况点击数字后直接点击等号,上层将显示如 “8=”

else:

expression = self.factor2

用因子一保存结果

try:

self.factor1 = formatting_data(eval(expression))

self.lower_display.set(self.factor1)

self.upper_display.set(expression + " = ")

except ZeroDivisionError:

tkinter.messagebox.showwarning(“李帅哥温馨提示”, “0 不能作为除数!”)

initialize()

**思路:**首次点击等号时用因子2记录下显示屏数据。一般等号是在前面输入“数字1  运算符  数字2”之后出现的,输入等号后就用因子2记录数字2。然后组合字符串因子1, 运算符, 因子2,通过eval函数求解结果。然后在上显示屏显示计算过程,下显示屏显示结果。提到上下显示屏我再说一下。**下显示屏显示数值,也只显示数值。上显示屏显示运算过程。运算过程就只有两种情况“因子1  运算符”, “因子1 运算符 因子2 = 结果”。**正常输入表达式的话是有结果的,但少不了特殊情况,如果你就输入一个数按等于的话,表达式就是这个数,所以结果也是这个数。如果连续点击等号的话因子二的值不会变,还是第一次点击等号时数字2的值,所以连续点击会直接让结果与因子2相加。

另外,当0作为除数求表达式是我们要给出提示,因为0作除数时是无效输入。这里我使用了警告框,是tkinter下面的一个组件,需要提前导入。

import tkinter.messagebox

看一下提示效果。

哎,因为我这个等于号的算法设计的不够好,导致小等于号处处受到排挤,在其他分支都要额外考虑他的存在…怪难受的,都怪我。明明他跟加减乘除都是运算符,可结果只有它独自承担所有。

考虑到等号的特殊性,我们规定,每进行一次等号运算后,都将开始一轮新的计算,有时候还需要对数据进行初始化。

如何理解开始一轮新的计算?我们看一个早期BUG。

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Python工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Python开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img



既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Python开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024c (备注Python)
img

最后

不知道你们用的什么环境,我一般都是用的Python3.6环境和pycharm解释器,没有软件,或者没有资料,没人解答问题,都可以免费领取(包括今天的代码),过几天我还会做个视频教程出来,有需要也可以领取~

给大家准备的学习资料包括但不限于:

Python 环境、pycharm编辑器/永久激活/翻译插件

python 零基础视频教程

Python 界面开发实战教程

Python 爬虫实战教程

Python 数据分析实战教程

python 游戏开发实战教程

Python 电子书100本

Python 学习路线规划

一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!

AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算

2VA-1712346962733)]

最后

不知道你们用的什么环境,我一般都是用的Python3.6环境和pycharm解释器,没有软件,或者没有资料,没人解答问题,都可以免费领取(包括今天的代码),过几天我还会做个视频教程出来,有需要也可以领取~

给大家准备的学习资料包括但不限于:

Python 环境、pycharm编辑器/永久激活/翻译插件

python 零基础视频教程

Python 界面开发实战教程

Python 爬虫实战教程

Python 数据分析实战教程

python 游戏开发实战教程

Python 电子书100本

Python 学习路线规划

一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!

AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值