Python 之 基础知识大全

输出

Python的输出打印有四种方式,分别通过字符串格式化符号str.format()格式化字符串f-string格式化字符串、以及直接打印逗号分隔

其中常用的字符串格式化符号如下:

格式符号转换
%s字符串
%d有符号的十进制整数
%f浮点数
%c字符
%u无符号十进制整数
%o八进制整数
%x十六进制整数(小写ox)
%X十六进制整数(大写OX)
%e科学计数法(小写’e’)
%E科学计数法(大写’E’)
%g%f和%e的简写
%G%f和%E的简写

技巧

  • %06d,表示输出的整数显示位数,不足以0补全,超出当前位数则原样输出
  • %.2f,表示小数点后显示的小数位数。
age = 18 
name = 'TOM'
weight = 75.5321313

# 我的名字是TOM,明年019岁了, 体重75.53公斤
print('我的名字是%s,明年%03d岁了, 体重%.2f公斤' % (name, age + 1, weight))

# 我的名字是TOM,明年019岁了, 体重75.53公斤
print('我的名字是{0:s}, 明年{1:03d}岁了, 体重{2:.2f}公斤'.format(name, age + 1, weight))

# 我的名字是TOM,明年019岁了, 体重75.53公斤
print(f'我的名字是{name}, 明年{age + 1:03d}岁了, 体重{weight:.2f}公斤')

# 我的名字是TOM, 明年19岁了, 体重75.5321313公斤
print('我的名字是', name, ', 明年', age+1, '岁了, 体重', weight, '公斤', sep='')

注意:f-string是目前效率最高的格式化打印字符串实现方法,详细的格式化方法可以参考博文Python 中 str.format() 方法详解

输入

输入功能的实现很简单,实现方法用一句话可以实现:input('提示文字'),input接收的任何数据默认都是字符串数据类型,需要自己判断后自行转换。

password = input('请输入您的密码:')
print(f'您输入的密码是:{password}')

数据类型转换

与C++的数据转换相仿,常用的数据类型转换函数表如下:

函数说明
int(x [,base ])将x转换为一个整数
float(x)将x转换为一个浮点数
complex(real [,imag ])创建一个复数,real为实部,imag为虚部
str(x)将对象 x 转换为字符串
repr(x)将对象 x 转换为表达式字符串
eval(str)用来计算在字符串中的有效Python表达式,并返回一个对象
tuple(s)将序列 s 转换为一个元组
list(s)将序列 s 转换为一个列表
chr(x)将一个整数转换为一个Unicode字符
ord(x)将一个字符转换为它的ASCII整数值
hex(x)将一个整数转换为一个十六进制字符串
oct(x)将一个整数转换为一个八进制字符串
bin(x)将一个整数转换为一个二进制字符串

运算符

算数运算符
运算符描述实例
+1 + 1 输出结果为 2
-1-1 输出结果为 0
*2 * 2 输出结果为 4
/10 / 2 输出结果为 5
//整除9 // 4 输出结果为2
%取余9 % 4 输出结果为 1
**指数2 ** 4 输出结果为 16,即 2 * 2 * 2 * 2
()小括号小括号用来提高运算优先级,即 (1 + 2) * 3 输出结果为 9

注意:混合运算优先级顺序:()高于 ** 高于 * / // % 高于 + -

赋值运算符
运算符描述实例
=赋值num1, float1, str1 = 10, 0.5, 'hello world'
复合赋值运算符
运算符描述实例
+=加法赋值运算符c += a 等价于 c = c + a
-=减法赋值运算符c -= a 等价于 c = c- a
*=乘法赋值运算符c *= a 等价于 c = c * a
/=除法赋值运算符c /= a 等价于 c = c / a
//=整除赋值运算符c //= a 等价于 c = c // a
%=取余赋值运算符c %= a 等价于 c = c % a
**=幂赋值运算符c ** = a 等价于 c = c ** a
比较运算符

比较运算符也叫关系运算符, 通常用来判断。

运算符描述实例
==判断相等。如果两个操作数的结果相等,则条件结果为真(True),否则条件结果为假(False)如a=3,b=3,则(a == b) 为 True
!=不等于 。如果两个操作数的结果不相等,则条件为真(True),否则条件结果为假(False)如a=3,b=3,则(a == b) 为 True如a=1,b=3,则(a != b) 为 True
>运算符左侧操作数结果是否大于右侧操作数结果,如果大于,则条件为真,否则为假如a=7,b=3,则(a > b) 为 True
<运算符左侧操作数结果是否小于右侧操作数结果,如果小于,则条件为真,否则为假如a=7,b=3,则(a < b) 为 False
>=运算符左侧操作数结果是否大于等于右侧操作数结果,如果大于,则条件为真,否则为假如a=7,b=3,则(a < b) 为 False如a=3,b=3,则(a >= b) 为 True
<=运算符左侧操作数结果是否小于等于右侧操作数结果,如果小于,则条件为真,否则为假如a=3,b=3,则(a <= b) 为 True
逻辑运算符
运算符逻辑表达式描述实例
andx and y布尔"与":如果 x 为 False,x and y 返回 False,否则它返回 y 的值。True and False, 返回 False。
orx or y布尔"或":如果 x 是 True,它返回 True,否则它返回 y 的值。False or True, 返回 True。
notnot x布尔"非":如果 x 为 True,返回 False 。如果 x 为 False,它返回 True。not True 返回 False, not False 返回 True

类型

除却常用的整型、浮点型外还构建了一些常用的数据结构,分为可变类型与不可变类型(数据能够直接进行修改,如果能直接修改那么就是可变,否则是不可变):

  • 可变类型
    • 列表
    • 字典
    • 集合
  • 不可变类型
    • 整型
    • 浮点型
    • 字符串
    • 元组

id()可以用来判断两个变量是否为同一个值的引用。

字符串
功能语法
判断数据是否存在数据 in 变量
获取变量长度len(变量)
获取数据所在下标变量.index(数据, 开始位置下标, 结束位置下标)
统计数据出现次数变量.count(数据, 开始位置下标, 结束位置下标)
字符串切片序列[开始位置下标:结束位置下标:步长]
替换特定字符串字符串序列.replace(旧子串, 新子串, 替换次数)
按特定字符分割字符串字符串序列.split(分割字符, num)
将多个字符串合并字符或子串.join(多字符串组成的序列) 或 字符串 + 字符串
检测某个子串是否包含在这个字符串中字符串序列.find(子串, 开始位置下标, 结束位置下标)
返回某个子串在字符串中出现的次数字符串序列.count(子串, 开始位置下标, 结束位置下标)
检查字符串是否是以指定子串开头字符串序列.startswith(子串, 开始位置下标, 结束位置下标)
检查字符串是否是以指定子串结尾字符串序列.endswith(子串, 开始位置下标, 结束位置下标)

还有一些其他扩展实现以方便开发:

查找

  • rfind(): 和find()功能相同,但查找方向为右侧开始。
  • rindex():和index()功能相同,但查找方向为右侧开始。
  • count():返回某个子串在字符串中出现的次数

修改

  • capitalize():返回一个 将原字符串第一个字符转换成大写 的新字符串。
  • title():返回一个 将原字符串每个单词首字母转换成大写 的新字符串。
  • lower():返回一个 将原字符串中大写转小写 的新字符串。
  • upper():返回一个 将原字符串中小写转大写 的新字符串。
  • lstrip():返回一个 删除原字符串左侧空白字符 的新字符串。
  • rstrip():返回一个 删除原字符串右侧空白字符 的新字符串。
  • strip():返回一个 删除原字符串两侧空白字符 的新字符串。
  • ljust():返回一个 原字符串左对齐,并使用指定字符(默认空格)填充至对应长度 的新字符串。
  • rjust():返回一个 原字符串右对齐,并使用指定字符(默认空格)填充至对应长度 的新字符串,语法和ljust()相同。
  • center():返回一个原字符串居中对齐,并使用指定字符(默认空格)填充至对应长度 的新字符串,语法和ljust()相同。

注意:虽然Python实现了许多字符串修改操作函数,但是字符串为const变量不可在原基础上进行修改,即所有的增删操作都会生成新的字符串变量。

判断

  • isspace():如果字符串中只包含空白,则返回 True,否则返回 False。
  • isdigit():如果字符串只包含数字则返回 True 否则返回 False。
  • isalpha():如果字符串至少有一个字符并且所有字符都是字母则返回 True, 否则返回 False。
  • isalnum():如果字符串至少有一个字符并且所有字符都是字母或数字则返 回 True,否则返回 False。
列表
功能语法
判断数据是否存在数据 in 变量
获取变量长度len(变量)
获取数据所在下标变量.index(数据, 开始位置下标, 结束位置下标)
统计数据出现次数变量.count(数据, 开始位置下标, 结束位置下标)
增加数据列表序列.append(数据)
追加数据中的每个元素至列表列表序列.extend(数据)
指定位置增加数据列表序列.insert(位置下标, 数据)
删除指定下标的数据列表序列.pop(下标)
删除指定下标的数据del 列表序列[下标]
移除列表中数据的第一个匹配项列表序列.remove(数据)
排序列表序列.sort( key=None, reverse=False)
深拷贝列表序列.copy()
逆置列表序列.reverse()
清空列表序列.clear()
元组

元组与列表类似,但是不支持增删改,只支持查询功能。

功能语法
判断数据是否存在数据 in 变量
获取变量长度len(变量)
获取数据所在下标变量.index(数据, 开始位置下标, 结束位置下标)
统计数据出现次数变量.count(数据, 开始位置下标, 结束位置下标)
集合

特点:

  1. 集合可以去掉重复数据;
  2. 集合数据是无序的,故不支持下标
功能语法
判断数据是否存在数据 in 变量
获取变量长度len(变量)
追加数据变量.add(数据)
追加数据序列变量.update(数据序列)
删除集合中的指定数据变量.discard(数据)
随机删除集合中的某个数据变量.pop(数据)
字典
功能语法
判断数据是否存在数据 in 变量
获取变量长度len(变量)
新增键值对或修改值字典序列[key] = 值
删除指定下标的数据del 字典序列[key]
清空字典序列.clear()
如果当前查找的key不存在则返回第二个参数字典序列.get(key, 默认值)
返回键值对的列表字典序列.items()
返回值的列表字典序列.values()
返回键的列表字典序列.keys()

函数

函数定义方法

def 函数名(参数):
    代码1
    代码2
    ......

不定长参数也叫可变参数。用于不确定调用的时候会传递多少个参数(不传参也可以)的场景。此时,与C++不同Python选择将其位置或者关键字与参数打包,进行传递。

# 将传入的所有参数打包为元组传入
def user_info(*args):
    print(args)

# ('TOM', 18)
user_info('TOM', 18)

# 将传入的所有参数和关键字打包为字典传入
def user_info(**kwargs):
    print(kwargs)

# {'name': 'TOM', 'age': 18, 'id': 110}
user_info(name='TOM', age=18, id=110)
lambda表达式

lambda表达式是一种特殊的函数,支持无参数,默认参数以及不定长参数:

lambda 参数: 表达式

文件读写

在python,使用open函数,可以打开一个已经存在的文件,或者创建一个新文件,语法如下:

open(name, mode)

name:是要打开的目标文件名的字符串(可以包含文件所在的具体路径)。
mode:设置打开文件的模式(访问模式):只读、写入、追加等。

这里将常用的模式如下表:

模式描述
r以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。
rb以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。
r+打开一个文件用于读写。文件指针将会放在文件的开头。
rb+以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。
w打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。
wb以二进制格式打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。
w+打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。
wb+以二进制格式打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。
a打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
ab以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
a+打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。
ab+以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。

常用函数表

功能语法
打开文件文件对象 = open(目标文件, 访问模式)
关闭文件文件对象.close()
写入文件文件对象.write()
从文件中读取num个字符文件对象.read(num)
将文件整体读取,返回以行为单位的列表文件对象.readlines()
读取一行数据文件对象.readline()
用来移动文件读取/写入位置文件对象.seek(偏移量, 起始位置)

注:seek函数的起始位置参数设置

  • 0:文件开头
  • 1:当前位置
  • 2:文件结尾

文件、文件夹操作

功能语法
删除文件os.remove(目标文件名)
创建文件夹os.mkdir(文件夹名字)
删除文件夹os.rmdir(文件夹名字)
获取当前路径os.getcwd()
改变当前路径os.chdir(目录)
获取文件列表os.listdir(目录)

面向对象编程

在实现类代码后可以通过继承重用已实现功能,并在此基础上实现更加个性化的功能,但是父类也可以通过声明为私有方法或变量来阻隔无必要的权限继承。

私有方法或变量实现方法如下:

class 类名():
  # 私有属性
  __属性名 =# 私有方法
  def __函数名(self):
    代码

但是子类虽然继承了父类所允许的全部方法和变量,但是父类的初始化过程函数并不会在实例化时调用,所以需要自行调用__init__函数进行参数初始化。对于不需要实例化和参数输入的函数,可以使用装饰器@staticmethod来进行修饰,声明为静态实现,同时对于不需要实例化的函数可以使用装饰器@classmethod 进行修饰,但第一个参数需要是表示自身类的 cls 参数,可以来调用类的属性,类的方法,实例化对象等。

# 父类A
class A(object):
	__name = "A"
	
    def __init__(self):
        self.__num = 1
	
	@classmethod
    def info_print(cls):
        print(cls.__name)
        
	@staticmethod
    def info_print():
        print('这是一个测试类....')

# 子类B
class B(A):
    def __init__(self):
        A.__init__(self) # super(B,self).__init__()
    pass

异常

捕捉处理异常的语法如下:

try:
  	可能发生异常的代码
except:
  	如果出现异常执行的代码
else:
  	没有异常执行的代码
finally:
  	无论是否异常都要执行的代码

自定义异常的实现示例如下:

# 自定义异常类,继承Exception
class ShortInputError(Exception):
    def __init__(self, length, min_len):
        self.length = length
        self.min_len = min_len

    # 设置抛出异常的描述信息
    def __str__(self):
        return f'你输入的长度是{self.length}, 不能少于{self.min_len}个字符'


def main():
    try:
        con = input('请输入密码:')
        if len(con) < 3:
            raise ShortInputError(len(con), 3)
    except Exception as result:
        print(result)
    else:
        print('密码已经输入完成')


main()

模块导入

import 模块名
from 模块名 import 功能名
from 模块名 import *
import 模块名 as 别名
from 模块名 import 功能名 as 别名

多进程

Process进程类的参数说明

Process([group [, target [, name [, args [, kwargs]]]]])

  1. group:指定进程组,目前只能使用None
  2. target:执行的目标任务名
  3. name:进程名字
  4. args:以元组方式给执行任务传参,和原参数的顺序保持一致
  5. kwargs:以字典方式给执行任务传参,key要和原参数名保持一致

Process创建的实例对象的常用属性

name:当前进程的别名,默认为Process-N,N为从1开始递增的整数

其他常用语句如下:

  1. os.getpid() 获取当前进程编号
  2. os.getppid() 获取父进程编号
  3. 子进程对象.daemon = True 守护主进程
  4. 子进程对象.terminate() 销毁子进程
  5. import multiprocessing 导入进程包
  6. sub_process = multiprocessing.Process (target=任务名) 创建子进程并指定执行的任务
  7. sub_process.start() 启动进程执行任务
  8. sub_process.join():等待当前子进程执行结束
  9. sub_process.terminate():不管任务是否完成,立即终止当前子进程

注意:为了保证子进程能够正常的运行,主进程会等所有的子进程执行完成以后再销毁,设置守护主进程的目的是主进程退出时子进程自动销毁,不让主进程再等待子进程去执行。当然也可以在主进程退出之前让手动调用子进程销毁。

多线程

线程类Thread参数说明

Thread([group [, target [, name [, args [, kwargs]]]]])

  1. group: 线程组,目前只能使用None
  2. target: 执行的目标任务名
  3. args: 以元组的方式给执行任务传参
  4. kwargs: 以字典方式给执行任务传参
  5. name: 线程名,一般不用设置

其他常用语句如下:

  1. import threading 导入线程包
  2. sub_thread = threading.Thread(target=任务名) 创建子线程并指定执行的任务
  3. sub_thread.start() 启动线程执行任务
  4. sub_thread.join() 等待当前线程任务执行完毕,与sleep有类似效果
  5. threading.Thread(target=show_info, daemon=True) 守护主线程
  6. 线程对象.setDaemon(True) 守护主线程
  7. mutex = threading.Lock()创建互斥锁
  8. mutex.acquire() 上锁
  9. mutex.release() 释放锁

因为多线程允许共享变量,但是多个线程访问共享数据会出现数据错误问题,而互斥锁能够妥当的解决该问题,但是需要注意死锁问题。

闭包

定义: 在函数嵌套的前提下,内部函数使用了外部函数的变量,并且外部函数返回了内部函数,使用外部函数变量的内部函数则被称为闭包

据此可知闭包的形成条件为:

  1. 在函数嵌套(函数里面再定义函数)的前提下
  2. 内部函数使用了外部函数的变量(还包括外部函数的参数)
  3. 外部函数返回了内部函数

可见其优点是可以暂存外部函数的一些状态,提高代码重用的效率,但是因此会增加内存的占用。当然如果闭包(内部函数)想要修改外部函数的某些变量,可以使用nonlocal声明一下即可,闭包使用示例代码如下:

# 定义一个外部函数
def func_out(num1):

    # 定义一个内部函数
    def func_inner(num2):
        # 这里本意想要修改外部num1的值,实际上是在内部函数定义了一个局部变量num1
        nonlocal num1  # 告诉解释器,此处使用的是 外部变量a
        # 修改外部变量num1
        num1 = 10
        # 内部函数使用了外部函数的变量(num1)
        result = num1 + num2
        print("结果是:", result)

    print(num1)
    func_inner(1)
    print(num1)

    # 外部函数返回了内部函数,这里返回的内部函数就是闭包
    return func_inner

# 创建闭包实例
f = func_out(1)
# 执行闭包
f(2)

装饰器

装饰器的功能特点:

  1. 不修改已有函数的源代码
  2. 不修改已有函数的调用方式
  3. 给已有函数增加额外的功能

装饰器的使用语法:

# 添加一个登录验证的功能
def check(fn):
    def inner():
        print("请先登录....")
        fn()
    return inner

def comment():
    print("发表评论")

# 使用装饰器来装饰函数
comment_with_check = check(comment)
comment_with_check()

同时Python为固化已有功能在新函数上的场景提供了语法糖写法:

# 添加一个登录验证的功能
def check(fn):
    print("装饰器函数执行了")
    def inner():
        print("请先登录....")
        fn()
    return inner

# 使用语法糖方式来装饰函数
@check
def comment():
    print("发表评论")

comment()

深、浅拷贝

  1. copy.copy(变量) 函数是浅拷贝,只对可变类型的第一层对象进行拷贝,对拷贝的对象开辟新的内存空间进行存储,不会拷贝对象内部的子对象。
  2. copy.deepcopy(变量) 函数是深拷贝, 只要发现对象有可变类型就会对该对象到最后一个可变类型的每一层对象就行拷贝, 对每一层拷贝的对象都会开辟新的内存空间进行存储。

字符串匹配

在Python中需要通过正则表达式对字符串进行匹配的时候,可以使用 re 模块

# 导入re模块
import re

# 使用match方法进行匹配操作
result = re.match(正则表达式,要匹配的字符串)

# 如果上一步匹配到数据的话,可以使用group方法来提取数据
result.group()

另一种方式

# 导入re模块
import re

# 使用compile方法获取匹配器
reg = re.compile(正则表达式)

# 然后可以使用findall方法来获取字符串中所有匹配项
result = reg.findall(字符串)

注意 re.match() 根据正则表达式从头开始匹配字符串数据,而不是从任意位置开始。

单个字符匹配

  1. . 表示匹配任意1个字符(除了\n)
  2. [ ] 表示匹配[ ]中列举的1个字符
  3. \d 表示匹配一个数字,即0-9
  4. \D 表示匹配一个非数字,即不是数字
  5. \s 表示匹配一个空白字符,即 空格,tab键
  6. \S | 匹配一个非空白字符
  7. \w | 匹配一个非特殊字符,即a-z、A-Z、0-9、_、汉字
  8. \W | 匹配一个特殊字符,即非字母、非数字、非汉字

多个字符匹配

  1. *表示匹配前一个字符出现0次或者无限次,即可有可无
  2. +表示匹配前一个字符出现1次或者无限次,即至少有1次
  3. ?表示匹配前一个字符出现1次或者0次,即要么有1次,要么没有
  4. {m}表示匹配前一个字符出现m次
  5. {m,n}表示匹配前一个字符出现从m到n次

匹配开头和结尾

  1. ^ 表示匹配字符串开头
  2. $ 表示匹配字符串结尾

匹配分组

  1. | 表示匹配左右任意一个表达式
  2. (ab) 表示将括号中字符作为一个分组
  3. \num 表示引用分组num匹配到的字符串
  4. (?P) 表示分组起别名
  5. (?P=name) 表示引用别名为name分组匹配到的字符串
  6. (分组数据):分组数是从左到右的方式进行分配的,最左边的是第一个分组,依次类推

上下文管理器

上下文管理器是指在执行一段代码执行前,先执行一段代码用于一些预处理工作;执行这段代码之后再执行一段代码进行清理工作。构建上下文管理器生成类同时使用with语句与之配合,便可实现。一个类只要实现了__enter__()__exit__()这个两个上、下文方法,通过该类创建的对象我们就称之为上下文管理器。

class File(object):

    # 初始化方法
    def __init__(self, file_name, file_model):
        # 定义变量保存文件名和打开模式
        self.file_name = file_name
        self.file_model = file_model

    # 上文方法
    def __enter__(self):
        print("进入上文方法")
        # 返回文件资源
        self.file = open(self.file_name,self.file_model)
        return self.file

    # 下文方法
    def __exit__(self, exc_type, exc_val, exc_tb):
        print("进入下文方法")
        self.file.close()


if __name__ == '__main__':

    # 使用with管理文件
    with File("1.txt", "r") as file:
        file_data = file.read()
        print(file_data)

另外一种实现方式是使用 @contextmanager 的装饰器,更进一步简化了上下文管理器的实现方式。通过 yield 将函数分割成上下文两个部分,将所跟的代码加载两者之间。

# 导入装饰器
from contextlib import contextmanager
# 装饰器装饰函数,让其称为一个上下文管理器对象
@contextmanager
def my_open(path, mode):
    try:
        # 打开文件
        file = open(file_name, file_mode)
        # yield之前的代码好比是上文方法
        yield file
    except Exception as e:
        print(e)
    finally:
        print("over")
        # yield下面的代码好比是下文方法
        file.close()

# 使用with语句
with my_open('out.txt', 'w') as f:
    f.write("hello , the simplest context manager")
  • 20
    点赞
  • 91
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 17
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

FlameAlpha

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值