03---python组合数据类型

💡大纲

👉列表:列表的创建、列表性质(长度、索引、切片)、操作列表(列表元素的增删查改、列表的复制、列表的排序翻转、遍历列表)

👉元组:元组性质(不可变列表)、操作元组(不支持任何关于元组本身的修改)、常见用法(打包、解包)

👉字典:字典的创建、字典性质(索引)、操作字典(键值对的增删改、遍历字典)

👉集合:集合的表达形式、集合运算、操作集合(元素的增删、遍历集合)

一、列表(有序,可修改)

❓什么是列表???

👉序列类型:内部元素有位置关系,可通过位置序号访问

👉可以存放多种类型的数据

(一)列表的创建

1、创建空白对象

list1 = list() # 通过循环给空列表赋值

2、直接赋值

ls = ["Python", C, 1234, {"Day": 10.16}]
ls
# ['Python', C, 1234, {'Day': 10.16}]

3、list(可迭代对象)

💡可迭代对象:字符串、元组、集合、range()

👉字符串转列表、元组转列表、集合转列表、range()转列表

list("今天是周末") # ['今', '天', '是', '周', '末']
list(("你", "我", "他", "她")) # ['你', '我', '他', '她']
list({"盾山", "东皇", "鲁大", "小鲁班"}) # ['盾山', '东皇', '小鲁班', '鲁大']
list(range(1, 11, 2)) # [1, 3, 5, 7, 9]

❓认识一下range()

for i in [0, 1, 2, 3, 4, 5]:
    print(i)
for i in range(6):
    print(i)
# 两者的结果是一样的

👉range(起始数字,中止数字,数字间隔)

👉起始数字缺省,默认为0;数字间隔缺省,默认为1

⚠️中止数字不能省略,读取的时候不包含中止数字

for i in range(1, 11, 2):
    print(i, end=" ")
# 1 3 5 7 9 

(二)列表的性质

1、列表的长度---len(列表)

2、列表的索引---与同为序列类型的字符串完全相同 

H = ["盾山", "东皇", "鲁班", "鲁大"]
print(H[0]) # 盾山
print(H[-1]) # 鲁大

3、列表的切片(正向、反向)---同字符串

👉变量名[开始位置:结束位置:切片间隔]

👉正向:开始位置小于结束位置,切片间隔为正数

👉反向:开始位置大于结束位置,切片间隔为负数

(三)列表的操作符

1、列表的拼接---list1+lis2(类似与字符串的拼接,用的不多)

2、列表的成倍复制---n*list(可作为初始化 列表的一种方式)

[0]*10 # [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] 重复列表内的元素若干次

(四)列表的操作

1、增加元素

💡在列表末尾增加元素---列表.append(待增元素)

H = ["盾山", "东皇", "鲁班"]
H.append("鲁大")
# H[len(H):] = ["鲁大"] 通过切片的方式添加
H # ['盾山', '东皇', '鲁班', '鲁大']

💡在列表任意位置插入元素---列表.insert(位置编号,待增元素)

H = ["盾山", "东皇", "鲁班"]
H.insert(1, "鲁大")
H # ['盾山', '鲁大', '东皇', '鲁班']

💡在列表1的末尾加上整个列表2---列表1.append(列表2)

💡将列表2内的元素逐个添加到列表1中---列表1.extend(列表2) 可以使用切片的方式添加

list1=["C","C++","R"]
list2=["Python","Java"]
list1.append(list2)
list1.extend(list2)
# 对比list1    
# ['C', 'C++', 'R', ['Python', 'Java']]
# ['C', 'C++', 'R', 'Python', 'Java']

2、删除元素

💡删除列表任意位置的元素---列表.pop(位置编号)del 列表[位置编号]

👉对于列表.pop(位置),会返回删除的元素;不写位置信息时,默认删除最后一个元素

list1 = ['Python', 'C', 'C++', 'R', 'Java']
list1.pop(2)
print(list1)
del list1[2]
print(list1)
'''
['Python', 'C', 'R', 'Java']
['Python', 'C', 'Java']
'''

💡删除列表中的第一次出现的待删元素---列表.remove(待删元素)

list1 = ['Python', 'C', 'R', 'C', 'Java']
list1.remove("C")    
list1 # ['Python', 'R', 'C', 'Java']

# 删除字符串中某个指定的元素
list1 = ['Python', 'C', 'R', 'C', 'Java']
while "C" in list1:
    list1.remove("C")    
list1 # ['Python', 'R', 'Java']

💡清空列表---列表.clear()

3、查找元素

💡返回列表某个元素出现的次数---列表.count(待查元素) 

💡返回列表中第一次出现待查元素的位置---列表.index(待查元素)

list1 = ['Python', 'C', 'R','Java']
idx = list1.index("R") 
# idx = list1.index("R", 1, 3)  # 查找元素,查找的范围
idx # 2

4、修改元素

💡通过"先索引后赋值"的方式,对元素进行修改---列表名[位置]=新值

 

5、列表的复制

👉如果以list1给list2赋值,那么两者共用一段数据,在list1中修改,两者的输出都会被修改。这里是对列表的引用

👉以浅拷贝的方式进行列表的复制

💡克隆---列表.copy()

list1 = ['Python', 'C', 'R','Java']
list2 = list1.copy()
list1.pop()
print(list1) # ['Python', 'C', 'R']
print(list2) # ['Python', 'C', 'R', 'Java']

💡切片---列表[:]

list1 = ['Python', 'C', 'R','Java']
list2 = list1[:]
list1.pop()
print(list1) # ['Python', 'C', 'R']
print(list2) # ['Python', 'C', 'R', 'Java']

⚠️浅拷贝在二维列表中会有错误,x改后,y也会对应的改

👉浅拷贝只拷贝了外层的对象,如果包含嵌套对象时,拷贝的只是其引用,需要用到深拷贝

⭕深拷贝需要导入copy模块,有两个函数copy()、deepcopy()

👉深拷贝在进行拷贝时会把拷贝对象所有的内容进行拷贝

  

 

6、列表的排序 

💡对列表进行永久排序(默认升序)---列表.sort()

👉只能处理列表

👉直接在列表上进行操作

list1 = [2, 5, 2, 8, 19, 3, 7]
list1.sort()
list1 # [2, 2, 3, 5, 7, 8, 19]

👉如果想要改为降序

list1.sort(reverse = True)
list1  # [19, 8, 7, 5, 3, 2, 2]

💡列表进行临时排序---sorted(列表)

👉原列表保持不变,返回排序后的列表

list1 = [2, 5, 2, 8, 19, 3, 7]
list2 = sorted(list1)
print(list1) # [2, 5, 2, 8, 19, 3, 7]
print(list2) # [2, 2, 3, 5, 7, 8, 19]

👉改为降序

sorted(list1, reverse = True)
# [19, 8, 7, 5, 3, 2, 2]

7、列表的翻转

💡对列表进行永久翻转---列表.reverse()

👉直接在列表上进行操作,无返回值

list = [1, 2, 3, 4, 5]
print(list[::-1]) # [5, 4, 3, 2, 1],这是以切片的方式翻转
list # [1, 2, 3, 4, 5]

list.reverse()
list # [5, 4, 3, 2, 1]

8、列表的遍历

list = [1, 2, 3, 4, 5]
for i in list:
    print(i,end=" ")
# 1 2 3 4 5 

9、列表的嵌套

A = [0] * 3 # [0, 0 ,0]
for i in range(3):
    A[i] = [0] * 3 # 创建3*3的二维列表 [[0, 0, 0], [0, 0, 0], [0, 0, 0]]

S = [[0] * 3 for i in range(3)] # [[0, 0, 0], [0, 0, 0], [0, 0, 0]]

 💡创建二维列表的方法,A才是真正意义上的创建了二维列表

  

(五)列表推导式

'''[表达式 for 变量 in 列表 (if 条件)]'''
# 列表生成元素表达式,可以是有返回值的函数
# 迭代列表,将变量传入到表达式
# 条件语句,可以过滤列表中不符合条件的值,只有满足条件的才可以使用

1、案例 

📑过滤字符串长度小于或等于3的字符串,并将剩下的转换为大写字母

names = ["Bob","Tom","Jerry","Smith"]
new_name = [name.upper() for name in names if len(name)>3]
print(new_name) # ['JERRY', 'SMITH']

📑计算30以内可以被3整除的数字

num = [i for i in range(30) if i % 3 == 0]
print(num,end=" ") # [0, 3, 6, 9, 12, 15, 18, 21, 24, 27] 

2、嵌套的列表推导式 

_表示临时变量名

二、元组(不可修改)

❓什么是元组???

👉序列类型:内部元素有位置关系,可通过位置序号访问

👉可以存放多种类型的数据

⚠️与列表相比:元组一旦定义,内部元素不允许修改操作,其他操作与列表一样

⚠️元组可看作不可变的列表

(一)元组

 👉元素中只包含一个元素时,需要在元素后面添加逗号,表示这是元组

tup1 = (50) # 这是当作整数的
print(type(tup1))

tup2 = (50,) # 加上逗号,表示这是元组
print(type(tup2))

'''
<class 'int'>
<class 'tuple'>
'''

(二)元组的常见用法

1、打包

x,y = 10,20 # 其实是_ = (10,20)进行打包,然后再解包
def f1(x):              # 返回x的平方和立方
    return x**2, x**3   # 实现打包返回

print(f1(3))            # (9,27)
print(type(f1(3)))      # 元组类型<class 'tuple'>

2、解包(列表、元组、字符串)

a, b = f1(3)            # 实现解包赋值 
print(a)                # 9
print(b)                # 27

3、元组的嵌套

 

4、元组推导式? 

👉有列表推导式,但是不存在元组推导式的,会得到一个生成器

(三)关于元组的元素是不可变的 

💡元组中存放的是元素的地址不可变指的是元组所指向的内存中的内容不可变,如果元组里的元素指向一个可变的列表,依然可以修改列表里的值

  

 👉重新赋值后的元组tup1,其实是重新创建的,因为地址改变了

tup1=(1,2,3)
print(id(tup1)) # tup1的内存地址

tup1=(4,5,6,7)
print(id(tup1)) # 重新赋值后tup1的内存地址

'''
2744756391752
2744752371336
'''

(四)实例

numbers = [201901, 201902, 201903]
name = ["小明", "小红", "小强"]
list(zip(numbers,name))                 # [(201901, '小明'), (201902, '小红'), (201903, '小强')]

for number,name in zip(numbers,name):   # 每次取到一个元组,立刻进行解包赋值
    print(number, name)
# 201901 小明
# 201902 小红
# 201903 小强

三、字典(有序,可修改) 在python3.7以后

❓什么是字典???

👉字典的键不能重复的,如果重复了,随机读取重复键的一个键值

👉字典的键必须是不可变类型,不能更改键值,因为键与键值一一对应

👉不可变类型:数字、字符串、元组

👉可变类型:列表、字典、集合

(一)创建字典:7种方法

a = {"吕布":"口口布","关羽":"关习习","刘备":"刘baby"}
b = dict(吕布="口口布",关羽="关习习",刘备="刘baby") # 要求键不能加引号
c = dict([("吕布","口口布"),("关羽","关习习"),("刘备","刘baby")]) # 将列表传入dict函数,列表内容为映射关系的元组
d = dict( {"吕布":"口口布","关羽":"关习习","刘备":"刘baby"}) # 不用,跟第一种一样
e = dict( {"吕布":"口口布","关羽":"关习习"},刘备="刘baby") # 混合方法
f = dict(zip(["吕布","关羽","刘备"],["口口布","关习习","刘baby"])) # zip函数将两个列表组合成一个二元组
g = dict.fromkeys(可迭代对象,数值(none)) 

(二)字典的性质

1、字典的长度---键值对的个数

len(d)  

2、键是否在字典中:键 in 字典

'C' in d # True

3、字典转换为列表

💡字典中的所有键构成一个列表

list(d) # ['F', 'i', 's', 'h', 'C']
list(d.keys())
list(d.values()) # ['70', 105, 115, 104, '67']

 4、将字典设置为一个迭代器

💡创建一个字典迭代器---iter(字典)

e = iter(d) 
next(e) # 依次读取迭代器内容

 5、逆序字典的键、键值

💡将字典的键、键值顺序颠倒---reversed(d.values())

list(reversed(d.values())) # ['67', 104, 115, 105, '70']
list(reversed(d)) # ['C', 'h', 's', 'i', 'F']

(三)字典的相关操作

1、增加键值对

💡形式:fromkeys(iterable[, values])

👉将iterable参数指定的可迭代对象来创建一个字典,并将所有的键值初始化为values参数指定的值

👉键名是可迭代对象的每个元素,键值是values参数(默认情况下是none)

👉需要修改键值时,就通过正常的访问来修改

d = dict.fromkeys("fish",250) # {'f': 250, 'i': 250, 's': 250, 'h': 250}
d['f'] = 70 # {'f': 70, 'i': 250, 's': 250, 'h': 250}

💡变量名[新键] = 新值

👉如果创建的新键名已存在,那么新键值覆盖旧键值

d['c'] = 80 # {'f': 70, 'i': 250, 's': 250, 'h': 250, 'c': 80}

2、删除键值对

💡删除任意键

👉del 字典名[待删除键]

👉del 字典名,删除整个字典

d = {'f': 70, 'i': 250, 's': 250, 'h': 250, 'c': 80}
del d['f'] # {'i': 250, 's': 250, 'h': 250, 'c': 80}
del d # 删除整个字典,不能再进行访问,会抛出异常

💡变量名.pop(待删除键),会返回键值 

👉删除不存在的键会抛出异常,可以设置默认值来规避异常。以下列形式:字典.pop(不存在的键,自己写的内容)

d.pop('s') # 250 返回键值
d.pop('狗') # 抛出异常
d.pop('狗',"没有该键") # '没有该键'

💡删除末尾键值对---字典名.popitem(),需要两个变量来接收返回的删除键值对

d = {'f': 70, 'i': 250, 's': 250, 'h': 250, 'c': 80}
key, value = d.popitem()
print(key,value) # c 80
print(d) # {'f': 70, 'i': 250, 's': 250, 'h': 250}

💡清空字典---字典名.clear()

d = dict.fromkeys("fishc",250)
d.clear() # {}

3、修改键值

💡通过先索引后赋值的方式对相应的值进行修改

👉可以通过update函数来更新多个键值对,传入的参数可以是另一个字典,也可以是包含映射关系的可迭代对象

d = dict.fromkeys("FishC")
d['s'] = 115 # {'F': None, 'i': None, 's': 115, 'h': None, 'C': None
d.update({'i':105,'h':104})
d.update(F='70',C='67') # {'F': '70', 'i': 105, 's': 115, 'h': 104, 'C': '67'}

 4、获取键值

💡获取字典中某一键值对的值

👉从字典d中获取键key对应的值,如果没有这个键,则返回default---d.get(key,default) 

d.get('C') # 67
d.get('c','这里没有c') # '这里没有c'

 💡在获取字典中某一个键值对的键值时,若该键存在,则输出键值;若键不存在,则将查找的键与默认键值组成键值对添加进字典---d.setdefault(键,默认键值)

d.setdefault('C','code') # 67
d.setdefault('c','code') # {'F': '70', 'i': 105, 's': 115, 'h': 104, 'C': '67', 'c': 'code'}

📑统计字符串中字符出现的频率 

love = "亲亲我吧爱我吧"
d = {}
print(d)
for i in love:
    d[i] = d.get(i, 0)+1 # 创建键值对
    print(d)

'''
{}
{'亲': 1}
{'亲': 2}
{'亲': 2, '我': 1}
{'亲': 2, '我': 1, '吧': 1}
{'亲': 2, '我': 1, '吧': 1, '爱': 1}
{'亲': 2, '我': 2, '吧': 1, '爱': 1}
{'亲': 2, '我': 2, '吧': 2, '爱': 1}
'''

💡获取整个字典的键值对、键与值的视图对象---d.items()、d.keys( )、d.values( )

👉视图对象的内容是动态、可修改的

keys = d.keys() # dict_keys(['F', 'i', 's', 'h', 'C', 'c'])
values = d.values() # dict_values(['70', 105, 115, 104, '67', 'code'])
items = d.items() # dict_items([('F', '70'), ('i', 105), ('s', 115), ('h', 104), ('C', '67'), ('c', 'code')])
d.pop('c') # 'code'
d # {'F': '70', 'i': 105, 's': 115, 'h': 104, 'C': '67'}
keys # dict_keys(['F', 'i', 's', 'h', 'C'])

5、字典的遍历

for k, v in Hero.items():
    print(k, v)
'''
101 盾山
102 东皇
103 鲁大
'''

6、字典的嵌套 

💡将字典的键值改为另一个嵌套的字典,访问时是两次索引

d = {"吕布":{"语文":60,"数学":60,"英语":90},"关羽":{"语文":50,"数学":60,"英语":40},"刘备":{"语文":70,"数学":30,"英语":80}}
d["刘备"]["英语"] # 80

(四)字典推导式

d = {'F': '70', 'i': 105, 's': 115, 'h': 104, 'C': '67'}
b = {v:k for k,v in d.items()} # {'70': 'F', 105: 'i', 115: 's', 104: 'h', '67': 'C'}

# 利用字典推导式求出字符串的编码值
d = {x:ord(x) for x in "FishC"} # {'F': 70, 'i': 105, 's': 115, 'h': 104, 'C': 67}

# 对于两个循环,在第一次循环后,第二次循环对于键值进行覆盖了
d = {x:y for x in [1,3,5] for y in [2,4,6]}
d # {1: 6, 3: 6, 5: 6}

四、集合(无序,可变)

❓什么是集合???

👉是一系列互不相等元素的集合,可用于去重

👉元素必须是不可变类型

⚠️与字典的关系:集合的元素可以看作字典的键,集合可以看作没有值或值为None的字典。在后续的学习中知道,字典的键与集合的元素都是可哈希的

s = [1,1,2,3,4,5]
# 判断有没有重复元素
len(s) == len(set(s)) # False

(一)集合的运算

两个班级的授课老师S、T

S = {"王老师", "吴老师", "郭老师", "刘老师", "赵老师", "张老师"}
T = {"王老师", "张老师", "吴老师", "陈老师", "赵老师", "林老师"}

1、交集

💡S.intersection(T)

👉S & T 返回一个新集合,包括同时在集合S和T中的元素

👉可以多参数

S & T    # {'吴老师', '张老师', '王老师', '赵老师'}
S.intersection(T)

2、并集

💡S.union(T)

👉返回一个新集合,包括集合S和T中的所有元素

👉可以多参数 

S | T    # {'刘老师', '吴老师', '张老师', '林老师', '王老师', '赵老师', '郭老师', '陈老师'}
S.union(T)

 3、非共同元素集合(对称差集)

💡s.symmetric_difference(可迭代对象)

👉S ^ T 返回一个新集合,包括集合S和T中的非共同元素(交集的补集)

👉不可以多参数 

S ^ T    # {'刘老师', '林老师', '郭老师', '陈老师'}

s = set("FishC")
s.symmetric_difference("Python") # {'C', 'F', 'P', 'i', 'n', 'o', 's', 't', 'y'}

4、in S not in T

💡S.difference(T)

👉S - T 返回一个新集合,包括在集合S但不在集合T中的元素

👉可以多参数 

S - T    # {'刘老师', '郭老师'}
T - S    # {'林老师', '陈老师'}
S.difference(T)

5、检测子集或超集 

💡集合.issubset(可迭代对象)        集合.issuperset(可迭代对象)

s.issubset("I Love python.com") # True
s.issuperset("py") # Ture

s = set("FishC")
s <= set("FishC") # True 子集
s < set("FishC") # False 真子集
s >= set("Fish") # True
s > set("FishC") # False 真超集

⭕在用符号进行计算时需要注意,操作数只能是集合;使用操作符进行计算时 ,可以使用所有可迭代对象

👉所有计算都是返回新的集合,并不是修改原本的集合

(二)集合的创建:3种方法

 1、集合推导式

💡集合数据是无序的

{s for s in "FishC"} # {'C', 'F', 'h', 'i', 's'}

 2、set()函数

👉创建空集合必须用函数set()集合名 = set(可迭代对象)

👉集合名 = {value1, value2,……} 

set("FishC") # {'C', 'F', 'h', 'i', 's'}

3、直接创建 

(三)set()与frozenset() 

💡两者都是集合,差别在于可变与不可变,不可变指的是内容不能修改

👉set是可变的集合

👉frozenset是不可变的集合

t = frozenset("FishC") # frozenset({'C', 'F', 'h', 'i', 's'})

1、前面说的所有方法两者都可以使用

2、仅适用于set()的方法

  • 增加集合元素

💡使用函数参数others指定的值来更新集合,插入新的元素---s.update(*others) 

👉others表示支持多参数,other只支持一个参数

👉因为集合中不能有重复的元素,所以[1,1]只会更新一个1,然后"23"在集合中随机更新

👉需要注意的是每一个参数的内容都是通过迭代的方式添加进集合的,并不是整体

s = set("FishC")
s.update([1,1],"23") # {1, '2', '3', 'C', 'F', 'h', 'i', 's'}

 💡将参数整体作为一个元素添加进集合中---s.add(参数)

s.add("45") # {'45', 'C', 'F', 'P', 'h', 'i', 'n', 'o', 's', 't', 'y'}
  • 集合的计算 

💡集合的计算,s.intersection_update(*others),s.difference_update(*others),s.symmetric_difference_update(*others)

👉关于union_update,因为使用比较多,直接表示为update

s = set("FishC")
s.update([1,1],"23") # {1, '2', '3', 'C', 'F', 'h', 'i', 's'}
s.intersection_update("FishC") # {'C', 'F', 'h', 'i', 's'}
s.difference_update("Php","Python") # {'C', 'F', 'i', 's'}
s.symmetric_difference_update("Python") # {'C', 'F', 'P', 'h', 'i', 'n', 'o', 's', 't', 'y'}
  • 删除指定元素

💡两种方法:s.remove(参数)、s.discard(参数)

👉区别是,前者删除的内容不存在会抛出异常,后者删除的内容不存在有一个静默处理

s.remove("Php") # 抛出异常
s.discard("Php") # 没有任何处理
  • 随机从集合中弹出一个元素---s.pop()

👉因为存储的顺序是随机的,虽然在弹出时是按照顺序来的,但其实就是随即弹出一个元素

s.pop() # 'F'
s.pop() # 'h'
  • 集合的长度---len(s)
  • 清空集合---s.clear()

3、集合的遍历

for i in Hero:
    print(i,end=' ')    # 东皇 小鲁班 鲁大 

4、判断元素存在与否 in() not in()

'C' in s # True

5、拷贝

s = set([1,2,3,4,5])
t = s.copy()

6、判断集合与一个可迭代对象是否相关 

💡集合.isdisjoint(可迭代对象)

👉False代表相关,元素有交集;True代表确实是不相关的

s = set("python")
s.isdisjoint(set("FishC")) # 并不是毫不相关,有交集'h' False
s.isdisjoint(set("JAVA")) # True

7、集合的嵌套 

💡因为集合是一个可变的无序对象,不能通过简单的包含进行嵌套。考虑到frozenset()的不可变性,可以使用其创建一个不可变对象,然后再将其嵌套进别的集合 

s = frozenset("fishc")
y = {s,4,5} # {4, 5, frozenset({'c', 'f', 'h', 'i', 's'})}

(四)集合推导式 

{s for s in "FishC"} # {'C', 'F', 'h', 'i', 's'}

五、python推导式

💡是一种独特的数据处理方式,可以从一个数据结构序列构建另一个新的数据结构序列的结构体

👉python支持列表、元组、字典、集合推导式

附:可哈希

💡可哈希:如果一个对象是可哈希的,那么就要求它的哈希值在其程序的整个生命周期都是不变的

👉可使用hash()函数获取哈希值

  • 对整数进行哈希,它的值等于本身
  • 如果两个对象的值是想等的,那么它们的哈希值是相等的
  • 对于可变类型的数据不能获得哈希值
hash(1) # 1
hash(1.0) # 1
hash(2) # 2

hash([1,2,3]) # 抛出异常

 📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

盾山狂热粉

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

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

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

打赏作者

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

抵扣说明:

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

余额充值