Python基础

这篇博客详细介绍了Python的基础知识,包括安装Python、PyCharm环境搭建、基本设置、常见问题及解决办法。深入讲解了Python的命名规则、注释、print函数、数据类型、运算符、流程控制等核心概念,还涵盖了字符串、列表、元组、字典等容器的使用,以及函数定义、模块管理和面向对象编程的基础。此外,还涉及文件操作和异常处理。

一、介绍

Python属于解释型语言
在这里插入图片描述

  • 框架
    ①接口自动化Python+requests;
    ②Web自动化:Python+selenium;
    ③移动端自动化:(手机app)Python+appium;

1安装Python

2、Python环境(Python解释器环境)搭建: ①下载解释器安装包;②自定义安装,勾选添加环境变量:Add Python 3.10 to Path(目的是让程序可以在任意的目录下去执行);③cmd中输入python 查看信息。
官网https://www.python.org/
在这里插入图片描述
在这里插入图片描述
Windows上输入:python,而macos上输入:python3。
在这里插入图片描述
mac终端中输入echo 'alias python="python3"' >> .bash_profile
在这里插入图片描述
卸载Python
在这里插入图片描述

2PyCharm环境搭建

3、pycharm环境搭建:(一般都是用的虚拟环境,而不是本地已存在的环境)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3PyCharm创建虚拟环境

PyCharm创建虚拟环境https://miaojiang.blog.csdn.net/article/details/121493112
在这里插入图片描述

4基本设置

快捷键

在这里插入图片描述

修改字体大小:菜单栏 =》file ----> setting —> editor —>font —> size 修改为需要大小字号例如20,点击ok。
命令行运行python文件
在这里插入图片描述
在这里插入图片描述
滚轮缩小字体:搜索decrease,Ctrl+鼠标滚轮向下,减小字体。
快速格式化代码:Ctrl+Alt+L(code =》 reformat code)

插件

汉化软件插件:搜索chinese安装插件(安装量最多的)
翻译软件:translation

模板

在这里插入图片描述

5.参考笔记

Python基础笔记:https://blog.csdn.net/overcomemyself/article/details/106679109
https://blog.csdn.net/overcomemyself/article/details/106682866

二、常见问题

无法初始化设备PRN

在这里插入图片描述

Debug

在这里插入图片描述

三、基础知识

命名

  • 私有类用下划线开头命名:_HelloWorld

注释

  • 单行注释:#;
  • 多行注释:三对双引号 或者 三对单引号。
  • 三种不同的波浪线

在这里插入图片描述

print函数

在这里插入图片描述
将数据输出到文件中

fp=open('D:/python_code/base/text.txt','a+')
print('HelloWorld',file=fp)
fp.close()
  • a+ 中的a代表以读写的方式打开文件,如果文件不存在,就创建。如果存在,就在文件里追加内容。需要写的内容存到文件中,必须加:file=xx。
  • 不进行换行输出(输出的内容在一行当中):print('Hello','World','Python')

转义字符

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

多行语句

在这里插入图片描述

数据类型

分类

在这里插入图片描述
在这里插入图片描述

type() 和instance

1、查看某个变量的数据类型print(type(变量))
例如:num = ‘20’ print(type(num)) # <class ‘str’>

  • 此外还可以用 isinstance 来判断:
>>> a = 111
>>> isinstance(a, int)
True
>>>

isinstance 和 type 的区别在于:

  • type()不会认为子类是一种父类类型。
  • isinstance()会认为子类是一种父类类型。
>>> class A:
...     pass
... 
>>> class B(A):
...     pass
... 
>>> isinstance(A(), A)
True
>>> type(A()) == A 
True
>>> isinstance(B(), A)
True
>>> type(B()) == A
False

在这里插入图片描述

input

2、输入input:使用input获取到的内容,都是字符串类型,即str

数据类型转换

3、数据类型转换:不会改变原数据的类型
在这里插入图片描述

交互式运行代码

4、交互运行代码:Python Console
在这里插入图片描述

格式化输出

普通格式化输出存在的问题:1.字符串拼接,导致代码可读性差;2.非字符串类型的数据,还要进行类型转换。

格式化输出-format方法实现
在这里插入图片描述
在这里插入图片描述
转义字符:①换行,回车:\n;②制表符,tab键:\t
为什么两个 print() 函数会换行输出呢? 因为 print() 函数默认自带 end='\n' 这个换行结束符。移除换行:print('内容', end='')

程序的输入

num1 = int(input("请输入第一个数字:"))
num2 = int(input("请输入第二个数字:"))
print(f"{num1} + {num2} = {num1 + num2}")

运算符

求商:// ,获取的是两个数据做除法的商。(被除数 ÷ 除数 = 商…余数)
取余:%,获取的是两个数据做除法的余数。
幂、次方:**
优先级: () > ** > * / // % > + -
赋值运算法
在这里插入图片描述

多个变量赋值

在这里插入图片描述

流程控制

If分支语句

1、if else结构。
2、if和逻辑运算符结合。
3、if elif else结构。
4、if嵌套。
5、综合应用(石头剪刀布):

import random
# 控制台出拳
player = int(input('请出拳 石头1/剪刀2/布3:'))
# 电脑随机出拳
computer = random.randint(1, 3)
# 1、玩家胜利
if(player == 1 and computer == 2) or (player == 2 and computer == 3) or (player == 3 and computer == 1):
    print('玩家胜利')
# 2、平局
elif player == computer:
    print('平局')
# 3、电脑胜利
else:
    print('电脑胜利')

随机数:①import random ②random.randint(a, b) # 产⽣[a, b]之间的随机整数,包含a和 b

while&for循环

1、while循环。
2、死循环和无限循环。①break:终止循环;②结束本次循环,继续下一次循环。
3、for循环:称为for遍历,也可以做指定次数的循环。遍历:是从容器(字符串、列表、元组、字典)中将数据逐个取出的过程。
例如:①for循环遍历字符串:for 变量 in 字符串:
for为指定次数的循环for 变量 in range(n):其中的range(n)可以生成[0,n)的整数序列,不包含n。n就是要循环的次数。

# for循环实现1~100的累加和
num = 0
for i in range(101):
    num += i
print('求和的结果为:', num)

容器

切片操作适用于字符串(str)/列表(list)/元组(tuple)
len():适用类型: 字符串、列表、元组、字典
在这里插入图片描述

1.字符串

Python 没有单独的字符类型,一个字符就是长度为 1 的字符串
1、使用引号(单引号, 双引号, 三引号)引起来的内容,就是字符串。
2、原生字符串 在字符串的前边 加上 r"", 字符串中的 \ 就不会进行转义。
在这里插入图片描述

3、下标(索引), 是数据在容器(字符串, 列表, 元组)中的位置, 编号。Python 中是支持负数下标, -1 表示最后一个位置的数据。

【注意】与 C 字符串不同的是,Python 字符串不能被改变。向一个索引位置赋值,比如word[0] = 'm’会导致错误。

1-1.切片

4、切片:使用切片操作, 可以一次性获取容器中的多个数据(多个数据之间存在一定的规律,数据的下标是 等差数列(相邻的两个数字之间的差值是一样的))。语法:容器[start:end:step]
在这里插入图片描述

my_str = 'abcdefg'
# 需求1 : 打印字符串中 abc 字符 start 0, end 3, step 1
print(my_str[0:3:1]) # abc
# 1.1 如果步长是 1, 可以省略不写
print(my_str[0:3]) # abc
# 1.2 如果 start 开始位置的下标为 0, 可以不写,但是冒号不能少
print(my_str[:3]) # abc
# 需求 2: 打印字符串中的 efg , start 4, end 7, step 1
print(my_str[4: 7]) # efg
# 2.1 如果取到最后一个字符, end 可以不写,但是冒号不能少
print(my_str[4:]) # efg
# 需求 3: 打印字符串中的 aceg , start 0, end 7(最后), 步长 2
print(my_str[::2]) # aceg
# 练习: 打印cf
print(my_str[2:6:3])
# 特殊情况, 步长为 -1, 反转(逆序) 字符串
print(my_str[::-1]) # gfedcba

特殊情况, 步长为 -1, 反转(逆序) 字符串:print(my_str[::-1]) # gfedcba

1-2.查找find()

在这里插入图片描述

1-3.替换replace()

字符串属于不可变数据类型,所有修改并不会影响原来的内容。
在这里插入图片描述
在这里插入图片描述

1-4.拆分split()

字符串.split(分隔符,分隔的次数)
①不传入分隔符时,默认按照空白字符分隔(空格,\n,\t)。
②分割次数不写,默认全部分割。
③得到的数据是列表list
在这里插入图片描述

1-5.连接 join

一般用于将列表按指定子字符合并为字符串:字符串.join(一般为列表),列表中的数据必须都是字符串才可以。
在这里插入图片描述
判断以什么结尾还可以用字符串.endswith():例如:’aaa’.endswith(‘a’)

2.列表list

2-1.定义

列表(list)是 Python 中使用最频繁的数据类型, 在其他语言中通常叫做数组, 专门用来存储一组数据。
1、列表,list, 使用 []。可以存放任意多个数据。可以存放任意类型的数据。列表中数据之间 使用 逗号隔开。
在这里插入图片描述
2、列表支持下标和切片
在这里插入图片描述
3、求长度(数据的个数):len(列表)

2-2.查询-index()

在这里插入图片描述

2-3.查询-count()

列表.count(数据) # 统计 指定数据在列表中出现的次数。

list1 = ['hello', 2, 3, 2, 3, 4]
# 查找 2 出现的下标
num = list1.index(2)
print(num) # 1
# 统计数据 2 出现的次数
num1 = list1.count(2)
print(num1) # 2
# 统计数据 20 出现的次数
num2 = list1.count(20)
print(num2) # 0

2-4.添加数据 append()

方法执行是对原数据进行的修改,固列表是可变数据类型
在这里插入图片描述

2-5.删除数据 pop()

列表.pop(下标),①如果书写的下标不存在,会报错。②返回:返回删除的数据。
①列表.pop(index) # 根据下标删除列表中的数据。index 下标可以不写, 默认删除最后一个。
返回删除的数据

list1 = ['张三', '李四', '王五', '赵六']
# 删除最后一个数据
list1.pop()
print(list1) # ['张三', '李四', '王五']
# 删除第二个数据
name = list1.pop(1)
print('删除的对象为:', name) # 删除的对象为: 李四
print(list1) # ['张三', '王五']

2-6.修改数据

想要修改列表中的数据, 直接使用下标即可:列表[下标] = 新数据

2-7.列表的反转 reverse()

1、字符串的反转:字符串[::-1]
2、列表的反转:
列表[::-1] 得到一个新的列表, 原列表不会改动。
列表.reverse() 直接修改原列表的数据,返回None

my_list = ['a', 'b', 'c', 'd', 'e']
# 1. 切片的方法进行反转
my_list1 = my_list[::-1]
print('原列表my_list :', my_list) # 原列表my_list: ['a', 'b', 'c', 'd', 'e']
print('my_list1:', my_list1) # ['e', 'd', 'c', 'b', 'a']
# 2. reverse
my_list.reverse()
print('my_list :', my_list) # ['e', 'd', 'c', 'b', 'a']

2-8.列表的排序

(前提: 列表中的数据要一样)
①升序, 从小到大, 直接在原列表中进行排序:列表.sort()
②降序, 从大到下, 直接在原列表中进行排序:列表.sort(reverse=True)

my_list = [1, 4, 7, 2, 5, 8, 3, 6, 9]
# 升序
my_list.sort()
print(my_list)
# 降序
my_list.sort(reverse=True)
print(my_list)

2-9.列表的嵌套

列表的嵌套 就是指 列表中数据都是列表。

student_list = [["张三", "18", "功能测试"], ["李四", "20", "自动化测试"], ["王五", "21", "自动化测试"]]
# 打印所有人员的年龄
for info in student_list: # info 是 列表
    print(info[1])

2-10.练习

在这里插入图片描述
判断以什么结尾还可以用字符串.endswith():例如:’aaa’.endswith(‘a’)

3.元组tuple

3-1.定义

①元组 tuple, 使用的是 ()
②元组和列表非常相似, 都可以存储多个数据, 都可以存储任意类型的数据
③区别就是元组中的数据不能修改,列表中的数据可以修改
④ 因为元组中的数据不能修改,所以只能查询, 如 len(), index(), count() ,支持下标和切片,可以访问指定位置的数据。
⑤元组主要用于传参和返回值。
在这里插入图片描述
【注意】:元组中只包含一个元素时,需要在元素后面添加逗号data = (1,)

3-2.组包和拆包

元组的特殊用法:交换两个变量的值【面试题】
在这里插入图片描述

a = 10
b = 20
# c = b, a # 组包
# print(c) # (20, 10)
# a, b = c # 拆包 a(20) b(10)
# print(a, b) # 20 10
a, b = b, a
print(a, b) # 20 10
x, y, z = 'abc'
print(y) # b

4.字典dict

4-1.定义

在这里插入图片描述
【注意】字典中的键一般都使用字符串,并且键名不能重复(如果重复原数据会被覆盖)。

4-2.增加和修改

【格式】:字典['键'] = 值 ①键 存在, 修改;②键 不存在, 添加。

4-3.删除

字典的删除是根据字典的键 删除键值对。字典.pop('键')

4-4.查询

字典['键'] # 键 不存在,会报错。
字典.get(键) # 键不存在,返回 None。

4-5.遍历

遍历字典的键:for key in 字典:
遍历字典的Key:for key in 字典.keys():
遍历字典的Value:for value in 字典.values():
遍历字典的Key和Value:for k, v in 字典.items():

1、遍历字典的键。
# 方式一
for 变量 in 字典:
print(变量)
# 方式二
for 变量 in 字典.keys(): # 字典.keys() 可以获取字典所有的键
print(变量)
2、遍历字典的值[使用较多]for 变量 in 字典.values(): # 字典.values() 可以获取字典中是所有的值
print(变量)
3、遍历字典的键和值。
# 变量1 就是 键, 变量2 就是值
for 变量1, 变量2 in 字典.items(): # 字典.items() 获取的是字典的键值对
print(变量1, 变量2)

5.集合

5-1.In操作符

1、数据 in 容器 可以⽤来判断 容器中是否包含这个数据。如果 包含返回 True,如果不包含返回 False。对于字典来说,判断的是字典中是否包含这个键。

5-2.集合 set(了解)

定义:{数据, 数据, …}
1、集合中的数据是不能重复的, 即没有重复数据。
2、对列表进⾏去重操作就是类型转换 , 可以将 列表转 换为 集合, 然后再将集合转换为列表。

my_list = [1, 2, 1, 2, 5, 2, 2, 4, 13]
# 方式一:使用set()方法进行去重。
list1 = list(set(my_list))
print(list1)
# 方式二:1.创建一个新列表。2.遍历原列表,使用in判断遍历出的元素是否在新列表中,
# 如果在就跳过,如果不在就添加到新列表中。
new_list = [] # 定义新列表 ,保存去重后的数据
# 遍历原列表
for i in my_list:
 # 判断数据是否存在于新列表
 if i not in new_list:
 # 不存在, 添加到新列表
 new_list.append(i)
print(new_list)

函数

Range函数的补充:
range(n) ---> [0, n)
range(start, end, step) ---> [start, end) 步长是 step,默认 1
range(1, 5, 2) # [1, 3]
range(1, 101) # 1-100

1.定义

  • type() 获取变量的数据类型
  • len() 获取容器的⻓度 (元素的个数)。
  • range(n) ⽣成⼀个序列[0, n)。
    • range(start, end, step) 表示 [start, end) 步长是step,默认为1
  • 定义:def 函数名():

在这里插入图片描述

2.文档注释

在这里插入图片描述

def get_max(x, y):
    """获取两个数中的最大值"""
    if x > y:
        return x
    else:
        return y


max_num = get_max(10, 20)
print(f"max_num={max_num}")

案例

# 1. 定义名为 input_username 的函数, 获取用户输入的用户名
def input_username():
	'''请输入用户名'''
	return input('请输入用户名:')

	
# 2. 定义名为 input_password 的函数, 获取用户输入的密码
def input_password():
	'''请输入密码'''
	return input('请输入密码:')

	
# 3. 定义名为 login 的函数, 判断获取的用户名和密码信息
# 4. 要求当获取的用户名为:admin 并且密码为: 123456 时, 输出“登录成功!”,否则提示“用户名或密码错误!”
def login():
	'''登录函数'''
	if input_username() == 'admin' and input_password() == '123456':
		print('登录成功')
	else:
		print('用户名或者密码错误')

login()			

3.模块

如果模块的名字太长,可以使用 as 指定模块的名称,以方便在代码中的使用:import 模块名1 as 模块别名
【注意】:模块别名应该符合大驼峰命名法。
在这里插入图片描述
在这里插入图片描述

方式一:
import 模块名 # 模块名 就是代码⽂件名 ,不要 .py
# 使⽤其中的功能  模块名.功能名 (功能可以是变量, 函数 和类)
# 【多⽤于导⼊系统中的常⽤的模块和功能】
import random
num = random.randint(1, 10)
print(num)

方式二:
from 模块名 import 功能名 # 导⼊指定的功能
# 使⽤  功能名()
# ⽅式⼆ 【多⽤于导⼊⾃⼰书写的,或者是第三⽅的模块】
# 【可以使⽤快捷键 Alt+回⻋】
from random import randint
num = randint(1, 10)
print(num)

在这里插入图片描述
练习
在这里插入图片描述

4.__name__变量

【将不想执行的代码写在这个里面】
在这里插入图片描述
在这里插入图片描述
快捷写:直接写main然后回车即可。
在这里插入图片描述
【注意】一般情况下, 都需要将模块内的调试代码置于该条件下, 以防止被其他模块导入后, 调试代码也参与执行。

def test01():
    print("test01")


def test02():
    """函数嵌套调用:一个函数里面又调用了另外一个函数"""
    print("test02")
    test01()


if __name__ == '__main__':
    test02()

5.模块导入顺序

1, 在导⼊模块的时候, 会先从代码所在的⽬录进⾏导⼊ 。
2, 如果没有找到,回去 Python 系统的⽬录查找导⼊ 。
3, 如果没有找到, 报错
【注意点】我们⾃⼰定义的代码⽂件名字 不要和你导⼊的系统的模 块⽂件名⼀样

6.包

定义:将多个模块放在⼀个⽬录中集中管理(是一个包含多个模块的特殊目录), 并在这个⽬录中创建 ⼀个 __init__.py ⽂件(可以什么都不写), 就是⼀个包。
在这里插入图片描述
提示:在PyCharm中支持直接创建包,工程根目录上鼠标右键 =》 New =》 Python Package。

# ⽅式⼀
import 包名.模块名
# 使⽤:【包名.模块名.⼯具名】

# ⽅式⼆
from 包名 import 模块名
# 使⽤:【模块名.⼯具名】

# ⽅式三, 使⽤快捷键导包:【Alt+回车】
from 包名.模块名 import ⼯具名 
# 直接使⽤⼯具名 (功能可以是变量, 函数 和类):【⼯具名】

在这里插入图片描述
综合案例:
在这里插入图片描述

  • service包下的login_service.py
def login(username, password, code):
    if code == "8888":
        if username == "admin" and password == "hrj":
            print('登录成功')
        else:
            print('用户名或者密码错误')
    else:
        print('验证码错误')
  • script包下的test_login.py
from service.login_service import login

login('admin', 'hrj', '8888')
login('admin', 'href', '8888')
login('admin', 'hrj', '88888')

7.变量的进阶

7-1.引用

1、变量和数据是分开存储的;定义变量的时候,变量和数据都会在内存开辟空间。
2、数据 保存在内存中的一个位置;
3、变量 中保存着数据在内存中的地址;使用id() 函数可以查看变量中保存数据所在的内存地址。
4、变量中记录数据的地址,就叫做引用Python中所有数据的传递,传递的都是引用(即地址)
5、【注意】当给一个变量重新赋值的时候,本质上是修改了数据的引用(赋值运算符(=), 会改变变量的引用, 即只有 = 可以修改变量的引用)。
①变量不再对之前的数据引用;
②变量改为对新复制的数据引用。
在这里插入图片描述

7-2.可变类型与不可变类型

在这里插入图片描述
在这里插入图片描述

7-3.局部变量和全局变量

【注意】在开发中, 大多不推荐使用全局变量, 可变范围太大, 会导致程序不好维护!
如果想要在函数外部使用局部变量的值, 使用 return 返回
在这里插入图片描述
在这里插入图片描述

def func1():
	list1.append(10)

def func2():
	list1 = [1, 1] # 定义局部变量, 不影响全局变量
	list1.append(0)

def func3():
	global list1 # 全局变量
	list1.pop() # 删除最后一个数据

def func_5():
	list1.pop() # 用的全局变量,没有改引用

def func4():
	global list1 # 全局变量
	list1 = [1]

if __name__ == '__main__':
	list1 = [1, 2]
	func1()
	print(list1) # ①[1, 2] ②[1, 2, 10](√) ③报错
	func2()
	print(list1) # ① [1, 1, 0] ②[1, 2, 10](√) ③报错
	func3()
	print(list1) # [1, 2]
	# func_5()
	# print(list1) # ②[1, 2] ①[1]对
	func4()
	print(list1) # [1]

8.函数的进阶

1、函数返回多个数据值:return a + b, a - b,返回的是一个元组数据。
2、函数传参的方式:
在这里插入图片描述

def show_info(name, age):
print(f"name:{name}, age: {age}")
# 位置传参
show_info('小明', 18)
# 关键字传参
show_info(age=18, name='张三')
# 混合使用
show_info('李四', age=17) #  位置参数必须写在关键字参数的前边

8-1.缺省参数(默认参数)

1、在函数定义的时候, 给形参一个默认的数据值,这个参数就是缺省参数(默认参数)。
2、在函数调用的时候, 缺省参数可以不用传递实参值。
①如果不传实参值, 使用的就是默认值。
②如果传递实参值, 使用的就是传递的实参值。
【注意】缺省参数必须写在 普通参数的后边

def show_info(name, age=18, sex='保密'):
	print(name, age, sex)


# 调用
show_info('张三', 18, '男')
show_info('李四') # 李四 18 保密
show_info('王五', 19) # 王五 19 保密
show_info('赵六', sex='男') # 赵六 18 男

8-2.多值参数(可变参数/不定长参数)

拆包

1, 在函数定义的时候,不确定在调用的时候,实参有多少个,此时可以使用 多值参数
2, 在普通的参数前边加上一个 *, 这个参数就变为:多值参数。
3, 这个参数可以接收任意多个位置传参的数据, 类型为元组
4, 这个形参一般写作 args(arguments), 即 *args

def 函数名(普通, *args, 缺省):
【函数调用过程中拆包】:
def my_sum(*args): # args 是元组
	num = 0
	for i in args:
		num += i
	return num
		
print(my_sum()) # 0
print(my_sum(1)) # 1
print(my_sum(1, 2)) # 3
print(my_sum(1, 2, 3)) # 6
my_tuple = (1, 2, 3, 4, 5)
# 需求对 元组中的所有数据使用 my_sum 进行求和
# 想要把列表(元组) 中的数据作为位置参数进行传递, 
# 只需要在列表(元组)前边加上一个 * ,进行拆包即可
print(my_sum(*my_tuple)) # 15

8-3.匿名函数

匿名函数:使用 lambda关键字定义的 表达式,称为匿名函数。
在这里插入图片描述

8-4.匿名函数的应用

要求按照年龄对用户数据进行排序。
在这里插入图片描述

9.函数练习

在这里插入图片描述
3.封装一个获取列表数据中最大值的函数:my_max()

  • 也可以直接使用系统中找最大值的方法:max(列表)
import random


def my_max(list1):
    '''求列表中最大的值'''
    max_num = list1[0]
    for i in list1:
        if i > max_num:
            max_num = i
    return max_num


if __name__ == '__main__':
    my_list = []
    for i in range(10):
        my_list.append(random.randint(1, 100))

    print(f"{my_list}中最大的数字为:{my_max(my_list)}")

在这里插入图片描述
5.
在这里插入图片描述

匿名管理系统

在这里插入图片描述

面向对象

基础

属性和方法

面向对象练习

三大特征

属性和方法的分类

文件操作

基本文件操作

JSON文件操作

异常处理

unittest框架

unittest

断言与参数化

测试报告和跳过

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值