Python基础

Python基础

pycharm项目打开方式

  1. This Window

覆盖当前项目,从而打开目标项目

  1. New Window

在新窗口打开,则打开两次PyCharm,每个PyCharm负责一个项目。

​ 3.Attach

​ 一个窗口两个项目

注释

  • 单行: # 注释内容,快捷键ctrl+/
  • 多行:""" 注释内容 """''' 注释内容 '''

变量

检测数据类型的方法:type()

数据类型

  • 整型:int
  • 浮点型:float
  • 字符串:str
  • 布尔型:bool
  • 元组:tuple
  • 集合:set
  • 字典:dict

输出

  • 格式化符号

    • %s:格式化输出字符串

    • %d:格式化输出整数

    • %f:格式化输出浮点数

    • %06d,表示输出的整数显示位数,不足以0补全,超出当前位数则原样输出

    • %.2f,表示小数点后显示的小数位数。

  • f-字符串

    • f’{表达式}’(3.6以上版本)
print('我的名字是%s' % name)
print('我的名字是%s,今年%d岁了' % (name, age))
print(f'我的名字是{name}, 明年{age + 1}岁了')
print('We are the {} who say "{}!"'.format('knights', 'Ni'))
  • 转义字符
    • \n:换行
    • \t:制表符 一个tab键(4个空格)的距离。
  • print结束符
print('内容', end="")

在Python中,print(), 默认自带end="\n"这个换行结束符,所以导致每两个print直接会换行展示,用户可以按需求更改结束符。

输入

  • 输入功能
    • input(‘提示文字’)
  • 输入的特点
    • 一般将input接收的数据存储到变量
    • input接收的任何数据默认都是字符串数据类型

数据类型转换

转换数据类型常用的函数

  • int()
  • float()
  • str()
  • list()
  • tuple()
  • eval()(转换成对应的python格式)

运算符

/10 / 2 输出结果为 5.0
//整除9 // 4 输出结果为2
**指数2 ** 4 输出结果为 16,即 2 * 2 * 2 * 2

与其他语言不同,除法得到为浮点数

  • 多个变量赋值 中间一个等号,左边变量个数与右边数据对应
num1, float1, str1 = 10, 0.5, 'hello world'
  • 多变量赋相同值(c语言定义时无法如此赋值,可先定义再赋值)
a = b = 10

复合赋值运算符

  • +=
  • -=
  • 优先级
    1. 先算复合赋值运算符右侧的表达式
    2. 再算复合赋值运算的算数运算
    3. 最后算赋值运算

逻辑运算符(与c语言不同)

  • 与: and
  • 或:or
  • 非:not

条件语句

if 条件1:
    条件1成立执行的代码
elif 条件2:
    条件2成立执行的代码
else:
    以上条件都不成立执行的代码

python中age >= 18 and age <= 60可以化简为18 <= age <= 60

三目运算符也叫三元运算符。

语法如下:

#值1 if 条件 else 值2

a = 1
b = 2

c = a if a > b else b
print(c)

循环

while

while 条件:
    条件成立重复执行的代码1
    条件成立重复执行的代码2
    ......
    
    
while 条件:
    条件成立重复执行的代码
else:
    循环正常结束之后要执行的代码

for循环

for 临时变量 in 序列:
    重复执行的代码1
    重复执行的代码2
    ......
    
    
for 临时变量 in 序列:
    重复执行的代码
    ...
else:
    循环正常结束之后要执行的代码

所谓else指的是循环正常结束之后要执行的代码,即如果是break终止循环的情况,else下方缩进的代码将不执行。

  • while和for都可以配合else使用
  • else下方缩进的代码含义:当循环正常结束后执行的代码
  • break终止循环不会执行else下方缩进的代码
  • continue退出循环的方式执行else下方缩进的代码

字符串

  • 一对引号字符串
name1 = 'Tom'
  • 三引号字符串
name3 = ''' Tom '''
b = """ i am Rose, 
        nice to meet you! """

注意:三引号形式的字符串支持换行。

思考:如果创建一个字符串I'm Tom?

c = "I'm Tom"
d = 'I\'m Tom'

下标

name = "abcdef"
print(name[1])

☆切片☆

切片是指对操作的对象截取其中一部分的操作。字符串、列表、元组都支持切片操作。

语法
序列[开始位置下标:结束位置下标:步长]

注意

  1. 不包含结束位置下标对应的数据, 正负整数均可;
  2. 步长是选取间隔,正负整数均可,默认步长为1。
  3. 下标-1为最后一个

常用操作方法

查找
  • find():检测某个子串是否包含在这个字符串中,如果在返回这个子串开始的位置下标,否则则返回-1
字符串序列.find(子串, 开始位置下标, 结束位置下标)

注意:开始和结束位置下标可以省略,表示在整个字符串序列中查找。

  • index():检测某个子串是否包含在这个字符串中,如果在返回这个子串开始的位置下标,否则则报异常

  • rfind(): 和find()功能相同,但查找方向为右侧开始。下标依然从左计数,不过返回的是从右边开始查找到的第一个位置

  • rindex():和index()功能相同,但查找方向为右侧开始。

  • count():返回某个子串在字符串中出现的次数

修改
  • replace():替换
  1. 语法
字符串序列.replace(旧子串, 新子串, 替换次数)

注意:替换次数如果查出子串出现次数,则替换次数为该子串出现次数。省略全部替换。

注意:数据按照是否能直接修改分为可变类型不可变类型两种。字符串类型的数据修改的时候不能改变原有字符串,属于不能直接修改数据的类型即是不可变类型。修改后的数据是replace的返回值

  • split():按照指定字符分割字符串。
  1. 语法,返回的是一个列表 丢失分割字符
字符串序列.split(分割字符, num)

注意:num表示的是分割字符出现的次数,即将来返回数据个数为num+1个。

注意:如果分割字符是原有字符串中的子串,分割后则丢失该子串。

  • join():用一个字符或子串合并字符串,即是将多个字符串合并为一个新的字符串。
  1. 语法
字符或子串.join(多字符串组成的序列)
list1 = ['chuan', 'zhi', 'bo', 'ke']
# 结果:chuan_zhi_bo_ke
print('_'.join(list1))
  • capitalize():将字符串第一个字符转换成大写。

注意:capitalize()函数转换后,只字符串第一个字符大写,其他的字符全都小写。

  • title():将字符串每个单词首字母转换成大写。

  • lower():将字符串中大写转小写。

  • upper():将字符串中小写转大写。

  • lstrip():删除字符串左侧空白字符。

  • rstrip():删除字符串右侧空白字符。

  • strip():删除字符串两侧空白字符。

  • ljust():返回一个原字符串左对齐,并使用指定字符(默认空格)填充至对应长度 的新字符串。

字符串序列.ljust(长度, 填充字符)
  • rjust():返回一个原字符串右对齐,并使用指定字符(默认空格)填充至对应长度 的新字符串,语法和ljust()相同。
  • center():返回一个原字符串居中对齐,并使用指定字符(默认空格)填充至对应长度 的新字符串,语法和ljust()相同。
判断

所谓判断即是判断真假,返回的结果是布尔型数据类型:True 或 False。

  • startswith():检查字符串是否是以指定子串开头,是则返回 True,否则返回 False。如果设置开始和结束位置下标,则在指定范围内检查。
字符串序列.startswith(子串, 开始位置下标, 结束位置下标)
  • endswith()::检查字符串是否是以指定子串结尾,是则返回 True,否则返回 False。如果设置开始和结束位置下标,则在指定范围内检查。

  • isalpha():如果字符串至少有一个字符并且所有字符都是字母则返回 True, 否则返回 False。

  • isdigit():如果字符串只包含数字则返回 True 否则返回 False。

  • isalnum():如果字符串至少有一个字符并且所有字符都是字母或数字则返 回 True,否则返回 False。

  • isspace():如果字符串中只包含空白,则返回 True,否则返回 False。

列表

  • 列表的格式[中括号] 可以为不同数据类型
[数据1, 数据2, 数据3]

常用操作方法

  • index()
  • count()
  • len()
  • append() 列表结尾追加数据。

列表追加数据的时候,直接在原列表里面追加了指定数据,即修改了原列表,故列表为可变类型数据。

  • extend():列表结尾追加数据,如果数据是一个序列,则将这个序列的数据逐一添加到列表。

  • insert():指定位置新增数据。

  • del

    1 删除列表 2 删除指定数据

  • pop() 删除指定下标的数据(默认为最后一个),并返回该数据。

  • remove() 移除列表中某个数据的第一个匹配项。

  • clear():清空列表 清空后列表仍在但为空 del直接列表变为未定义

列表嵌套

name_list = [['小明', '小红', '小绿'], ['Tom', 'Lily', 'Rose'], ['张三', '李四', '王五']]
name_list[2][1]

判断是否存在

  • in:判断指定数据在某个列表序列,如果在返回True,否则返回False
name_list = ['Tom', 'Lily', 'Rose']

# 结果:True
print('Lily' in name_list)

# 结果:False
print('Lilys' in name_list)
  • not in:判断指定数据不在某个列表序列,如果不在返回True,否则返回False

  • 修改指定下标数据

name_list = ['Tom', 'Lily', 'Rose']

name_list[0] = 'aaa'

# 结果:['aaa', 'Lily', 'Rose']
print(name_list)
  • 逆置:reverse()
num_list = [1, 5, 2, 3, 6, 8]

num_list.reverse()

# 结果:[8, 6, 3, 2, 5, 1]
print(num_list)
  • 排序:sort()
  1. 语法
列表序列.sort( key=None, reverse=False)

注意:reverse表示排序规则,reverse = True 降序, reverse = False 升序(默认)

  1. 快速体验
num_list = [1, 5, 2, 3, 6, 8]

num_list.sort()

# 结果:[1, 2, 3, 5, 6, 8]
print(num_list)

复制

函数:copy()

name_list = ['Tom', 'Lily', 'Rose']

name_li2 = name_list.copy()

# 结果:['Tom', 'Lily', 'Rose']
print(name_li2)

c语言free() 不会改变 ptr 变量本身的值,调用 free() 后它仍然会指向相同的内存空间,但是此时该内存已无效,不能被使用。所以建议将 ptr 的值设置为 NULL

Pycharm 导入自己写的.py文件出错(No Module named…)右键文件夹,选择Mark Dictionary as下的Sources root

元组

一个元组可以存储多个数据,元组内的数据是不能修改的

元组特点:定义元组使用小括号,且逗号隔开各个数据,数据可以是不同的数据类型。

# 多个数据元组
t1 = (10, 20, 30)

# 单个数据元组
t2 = (10,)

注意:如果定义的元组只有一个数据,那么这个数据后面也好添加逗号,否则数据类型为唯一的这个数据的数据类型

​ 元组数据不支持修改,只支持查找,具体如下:

  • 按下标查找数据

  • index():查找某个数据,如果数据存在返回对应的下标,否则报错,语法和列表、字符串的index方法相同。

  • count():统计某个数据在当前元组出现的次数。

  • len():统计元组中数据的个数。

注意:元组内的直接数据如果修改则立即报错

但是如果元组里面有列表,修改列表里面的数据则是支持的,故自觉很重

字典

字典特点:

  • 符号为大括号
  • 数据为键值对形式出现
  • 各个键值对之间用逗号隔开
# 有数据字典
dict1 = {'name': 'Tom', 'age': 20, 'gender': '男'}

# 空字典
dict2 = {}

dict3 = dict()

增加 写法:字典序列[key] = 值

注意:如果key存在则修改这个key对应的值;如果key不存在则新增此键值对。

del() / del:删除字典或删除字典中指定键值对。

clear():清空字典

改 写法:字典序列[key] = 值

注意:如果key存在则修改这个key对应的值 ;如果key不存在则新增此键值对。

查找

  • 字典序列[key]
  • keys() 键
  • values() 值
  • items() 键值对

集合

创建集合使用{}set(), 但是如果要创建空集合只能使用set(),因为{}用来创建空字典。

特点:

  1. 集合可以去掉重复数据;
  2. 集合数据是无序的,故不支持下标
  • 常见操作
    • 增加数据
      • add()
      • update() 追加的数据是序列。
    • 删除数据
      • remove() 数据不存在则报错。
      • discard() 数据不存在也不会报错。
      • pop(),随机删除集合中的某个数据,并返回这个数据。

公共操作

运算符

运算符描述支持的容器类型
+合并字符串、列表、元组
*复制字符串、列表、元组
in元素是否存在字符串、列表、元组、字典
not in元素是否不存在字符串、列表、元组、字典

公共方法

函数描述
len()计算容器中元素个数
del 或 del()删除
max()返回容器中元素最大值
min()返回容器中元素最小值
range(start, end, step)生成从start到end的数字,步长为 step,供for循环使用
enumerate()函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中。

注意:range()生成的序列不包含end数字。

注意:start参数用来设置遍历数据的下标的起始值,默认为0。

  • 数据类型转换
    • tuple()将某个序列转换成元组
    • list()将某个序列转换成列表
    • set()将某个序列转换成集合
  1. 集合可以快速完成列表去重
  2. 集合不支持下标

推导式

  • 推导式的作用:简化代码
  • 推导式写法
# 列表推导式
[xx for xx in range()]
[xx for xx in range() if...]
[xx for xx in range() for xx in range()]

# 字典推导式
{xx1: xx2 for ... in ...}

# 集合推导式
{xx for xx in ...}

函数

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

注意:

1. 不同的需求,参数可有可无。
2. 在Python中,函数必须==先定义后使用==。

说明文档

  • 定义函数的说明文档
def 函数名(参数):
    """ 说明文档的位置 """
    代码
    ......
  • 查看函数的说明文档
help(函数名)
  • 变量作用域
    • 全局:函数体内外都能生效
    • 局部:当前函数体内部生效
  • 函数多返回值写法
return 表达式1, 表达式2...
  • 函数的参数
    • 位置参数
      • 形参和实参的个数和书写顺序必须一致
    • 关键字参数
      • 写法: key=value
      • 特点:形参和实参的书写顺序可以不一致;关键字参数必须书写在位置参数的后面
    • 缺省参数
      • 缺省参数就是默认参数
      • 写法:key=vlaue
    • 不定长位置参数
      • 收集所有位置参数,返回一个元组
    • 不定长关键字参数
      • 收集所有关键字参数,返回一个字典
  • 引用:Python中,数据的传递都是通过引用

所谓可变类型与不可变类型是指:数据能够直接进行修改,如果能直接修改那么就是可变,否则是不可变.

不可变 a = 1 b =a a =2 a改编id b仍然为1 因为int不能改变

而列表 a =[1,2] b =a a.append(3) a b 仍然是原来的id

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

递归的特点

  • 函数内部自己调用自己
  • 必须有出口

lambda 表达式

  • lambda

    • 语法
    lambda 参数列表: 表达式
    
    • lambda的参数形式

      • 无参数
      lambda: 表达式
      
      • 一个参数
      lambda 参数: 表达式
      
      • 默认参数
      lambda key=value: 表达式
      
      • 不定长位置参数
      lambda *args: 表达式
      
      • 不定长关键字参数
      lambda **kwargs: 表达式
      
  • 高阶函数

    • 作用:把函数作为参数传入,化简代码

    • 内置高阶函数

      • map()

      map(func, lst),将传入的函数变量func作用到lst变量的每个元素中,并将结果组成新的列表(Python2)/迭代器(Python3)返回

      • reduce()

      reduce(func,lst),其中func必须有两个参数。每次func计算的结果继续和序列的下一个元素做累积计算。

      注意:reduce()传入的参数func必须接收2个参数。

      • filter()

      filter(func, lst)函数用于过滤序列, 过滤掉不符合条件的元素, 返回一个 filter 对象。如果要转换为列表, 可以使用 list() 来转换。

文件

  • 文件操作步骤

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

    注意:

    1. wa模式:如果文件不存在则创建该文件;如果文件存在,w模式先清空再写入,a模式直接末尾追加。
    2. r模式:如果文件不存在则报错。
    • 操作

      文件对象.read(num)
      num表示要从文件中读取的数据的长度(单位是字节),如果没有传入num,那么就表示读取文件中所有的数据。
      
      文件对象.readlines()
      readlines可以按照行的方式把整个文件中的内容进行一次性读取,并且返回的是一个列表,其中每一行的数据为一个元素。
      
      文件对象.readline()
      readline()一次读取一行内容。
      
      文件对象.write()
      
      • seek()

      • 作用:用来移动文件指针。

        语法如下:

        文件对象.seek(偏移量, 起始位置)
        

        起始位置:

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

    文件对象.close()
    
  • 主访问模式

    • w:写,文件不存在则新建该文件 覆盖原文件会全部清空 即原有内容会被删除
    • r:读,文件不存在则报错
    • a:追加
    # 提取文件后缀点的下标
    index = old_name.rfind('.')
    
    # print(index)  # 后缀中.的下标
    
    # print(old_name[:index])  # 源文件名(无后缀)
    
    # 组织新文件名 旧文件名 + [备份] + 后缀
    new_name = old_name[:index] + '[备份]' + old_name[index:]
    
    # 打印新文件名(带后缀)
    # print(new_name)
    
  • 文件和文件夹操作

  • import os 导入os模块

    • 重命名:os.rename(目标文件名, 新文件名)
    • 删除文件:os.remove(目标文件名)
    • 创建文件夹:os.mkdir(文件夹名字)
    • 删除文件夹:os.rmdir(文件夹名字)
    • 获取当前目录:os.getcwd()
    • 改变默认目录:os.chdir(目录)
    • 获取目录列表:os.listdir()
try:
    f = open('/path/', 'r')
    print(f.read())
finally:
    if f:
        f.close()
        
with open('/path/to/file', 'r') as f:
    print(f.read())

这和前面的try ... finally是一样的,但是代码更佳简洁,并且不必调用f.close()方法。

面向对象

  • 面向对象重要组成部分

      • 创建类
    class 类名():
      代码
    
    • 对象
    对象名 = 类名()
    
  • 添加对象属性

    • 类外面
    对象名.属性名 =
    • 类里面
    self.属性名 =
  • 获取对象属性

    • 类外面
    对象名.属性名
    
    • 类里面
    self.属性名
    
  • 魔法方法

    • __init__(): 初始化
    • __str__():输出对象信息
    • __del__():删除对象时调用
  • 继承的特点

    • 子类默认拥有父类的所有属性和方法
    • 子类重写父类同名方法和属性
    • 子类调用父类同名方法和属性
  • super()方法快速调用父类方法

  • 私有权限 函数名前面加两个_

    • 不能继承给子类的属性和方法需要添加私有权限
    • 语法
    class 类名():
      # 私有属性
      __属性名 =# 私有方法
      def __函数名(self):
        代码
    

面向对象三大特性

  • 封装

    • 将属性和方法书写到类的里面的操作即为封装
    • 封装可以为属性和方法添加私有权限
  • 继承

    • 子类默认继承父类的所有属性和方法
    • 子类可以重写父类属性和方法
  • 多态

    • 传入不同的对象,产生不同的结果
  • 类属性

    • 归属于类对象的属性,所有对象共有的属性
  • 实例属性

  • 类方法

@classmethod
def xx():
  代码
  • 静态方法
@staticmethod
def xx():
  代码

is和==

在 Python 中一切都是对象,毫无例外整数也是对象,对象之间比较是否相等可以用==,也可以用is。==和is操作的区别是:

Is比较的是两个对象的id值是否相等,也就是比较俩对象是否为同一个实例对象,是否指向同一个内存地址。
==比较的是两个对象的内容是否相等,默认会调用对象的 _eq_() 方法。

Python基础:is和==的区别 - 诚意 - 博客园 (cnblogs.com)

快速在当前文件夹进入cmd 只需在地址栏 输入cmd即可

异常

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

except 异常类型 as xx:
		代码
  • 自定义异常
# 1. 自定义异常类
class 异常类类名(Exception):
  	代码
    
    # 设置抛出异常的描述信息
    def __str__(self):
      return ...


# 2. 抛出异常
raise 异常类名()

# 捕获异常
except Exception...
  • 导入模块方法
import 模块名

from 模块名 import 目标

from 模块名 import *
  • 导入包
import 包名.模块名

from 包名 import *   必须有__all__
  • __all__ = [] :允许导入的模块或功能列表

__dict__ 返回类内部所有属性和方法对应的字典 或者 返回实例属性和值组成的字典
方法

@staticmethod
def xx():
  代码

is和==

在 Python 中一切都是对象,毫无例外整数也是对象,对象之间比较是否相等可以用==,也可以用is。==和is操作的区别是:

Is比较的是两个对象的id值是否相等,也就是比较俩对象是否为同一个实例对象,是否指向同一个内存地址。
==比较的是两个对象的内容是否相等,默认会调用对象的 _eq_() 方法。

Python基础:is和==的区别 - 诚意 - 博客园 (cnblogs.com)

快速在当前文件夹进入cmd 只需在地址栏 输入cmd即可

异常

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

except 异常类型 as xx:
		代码
  • 自定义异常
# 1. 自定义异常类
class 异常类类名(Exception):
  	代码
    
    # 设置抛出异常的描述信息
    def __str__(self):
      return ...


# 2. 抛出异常
raise 异常类名()

# 捕获异常
except Exception...
  • 导入模块方法
import 模块名

from 模块名 import 目标

from 模块名 import *
  • 导入包
import 包名.模块名

from 包名 import *   必须有__all__
  • __all__ = [] :允许导入的模块或功能列表

__dict__ 返回类内部所有属性和方法对应的字典 或者 返回实例属性和值组成的字典

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值