声明:本人的所有博客皆为个人笔记,作为个人知识索引使用,因此在叙述上存在逻辑不通顺、跨度大等问题,希望理解。分享出来仅供大家学习翻阅,若有错误希望指出,感谢!
Python条件控制
Python 条件语句是通过一条或多条语句的执行结果(True 或者 False)来决定执行的代码块
if 语句
Python中if语句的一般形式如下所示:
if condition_1:
statement_block_1
elif condition_2:
statement_block_2
else:
statement_block_3
- Python 中用 elif 代替了 else if,所以if语句的关键字为:if – elif – else。
注意:
- 每个条件后面要使用冒号 :,表示接下来是满足条件后要执行的语句块
- 使用缩进来划分语句块,相同缩进数的语句在一起组成一个语句块
- 在Python中没有switch – case语句
以下为if中常用的操作运算符:
| 操作符 | 描述 |
|---|---|
< | 小于 |
<= | 小于或等于 |
> | 大于 |
>= | 大于或等于 |
== | 等于,比较两个值是否相等 |
!= | 不等于 |
if 嵌套
在嵌套 if 语句中,可以把 if…elif…else 结构放在另外一个 if…elif…else 结构中
if 表达式1:
语句
if 表达式2:
语句
elif 表达式3:
语句
else:
语句
elif 表达式4:
语句
else:
语句
Python循环语句
Python 中的循环语句有 for 和 while
while 循环
Python 中 while 语句的一般形式:
while 判断条件:
执行语句1
执行语句2
在 Python 中没有 do…while 循环
无限循环
- 我们可以通过设置条件表达式永远不为 false 来实现无限循环
- 可以使用 CTRL+C 来退出当前的无限循环
- 无限循环在服务器上客户端的实时请求非常有用
while 循环使用 else 语句
在 while … else 在条件语句为 false 时执行 else 的语句块
语法格式如下:
while 条件:
执行语句1
else:
执行语句2
简单语句组
类似if语句的语法,如果你的while循环体中只有一条语句,你可以将该语句与while写在同一行中
while 条件: 执行语句
for 语句
Python for循环可以遍历任何序列的项目,如一个列表或者一个字符串
for循环的一般格式如下:
for 变量 in 序列: #使用一个变量迭代序列中的元素
执行语句1
else:
执行语句2
range()函数
如果你需要遍历数字序列,可以使用内置range()函数。它会生成数列
range(start, stop[, step])
参数说明:
- start:计数从 start 开始,默认是从 0 开始
- 例如:range(5)等价于range(0,5)
- stop:计数到 stop 结束,但不包括 stop
- 例如:range(0,5) 是[0,1,2,3,4],没有5
- step:步长,默认为1
- 例如:range(0,5) 等价于 range(0,5,1)
break 和 continue 语句及循环中的 else 子句
break 语句可以跳出 for 和 while 的循环体。如果你从 for 或 while 循环中终止,任何对应的循环 else 块将不执行
continue 语句被用来告诉 Python 跳过当前循环块中的剩余语句,然后继续进行下一轮循环
循环语句可以有 else 子句,它在穷尽列表(以for循环)或条件变为 false (以while循环)导致循环终止时被执行,但循环被 break 终止时不执行
pass 语句
pass是空语句,是为了保持程序结构的完整性
pass 不做任何事情,一般用做占位语句
if a==1:
pass #a==1时什么也不执行
else:
执行语句
Python迭代器与生成器
迭代器
迭代是Python最强大的功能之一,是访问集合元素的一种方式
- 迭代器是一个可以记住遍历的位置的对象
- 迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退
- 迭代器有两个基本的方法:iter() 和 next()
- 字符串,列表或元组对象都可用于创建迭代器
>>> list = [1,2,3,4]
>>> it = iter(list) # 创建迭代器对象
>>> print(next(it)) # 输出迭代器的下一个元素
1
>>> print(next(it))
2
迭代器对象可以使用常规for语句进行遍历:
list=[1,2,3,4]
it = iter(list) # 创建迭代器对象
for x in it:
print (x, end=" ")
执行以上程序,输出结果如下:
1 2 3 4
也可以使用 next() 函数:
import sys # 引入sys模块
list=[1,2,3,4]
it = iter(list) # 创建迭代器对象
while True: # 死循环
try:
print (next(it),end=" ") # 使用next输出迭代器内容
except StopIteration: #迭代器遍历完后调用next将抛出该异常
sys.exit() #退出程序
执行以上程序,输出结果如下:
1 2 3 4
创建一个迭代器
把一个类作为一个迭代器使用需要在类中实现两个方法 __iter__() 与 __next__()
__iter__()方法返回一个特殊的迭代器对象, 这个迭代器对象实现了 next() 方法并通过 StopIteration 异常标识迭代的完成__next__()方法会返回下一个迭代器对象
创建一个返回数字的迭代器,初始值为 1,逐步递增 1:
class MyNumbers: #创建迭代器类
def __iter__(self):
self.a = 1
return self
def __next__(self):
x = self.a
self.a += 1
return x
myclass = MyNumbers()
myiter = iter(myclass)
print(next(myiter))
print(next(myiter))
print(next(myiter))
执行输出结果为:
1
2
3
StopIteration异常
StopIteration 异常用于标识迭代的完成,防止出现无限循环的情况,在 next() 方法中我们可以设置在完成指定循环次数后触发 StopIteration 异常来结束迭代
实例:在 10 次迭代后停止执行:
import sys
class MyNumbers:
def __iter__(self):
self.a = 1
return self
def __next__(self):
if self.a <= 10:
x = self.a
self.a += 1
return x
else:
raise StopIteration #抛出StopIteration异常
myclass = MyNumbers()
myiter = iter(myclass)
while True:
try:
print (next(myiter),end=" ")
except StopIteration: #捕获到异常后停止
sys.exit()
执行输出结果为:
1 2 3 4 5 6 7 8 9 10
生成器
在 Python 中,使用了 yield 的函数被称为生成器(generator)
- 跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器
- 在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行
- 调用一个生成器函数,返回的是一个迭代器对象
以下实例使用 yield 实现斐波那契数列:
import sys
def fibonacci(n): # 生成器函数
a, b, counter = 0, 1, 0
while True:
if (counter > n):
return
yield a
a, b = b, a + b
counter += 1
f = fibonacci(10) # f是一个迭代器,由生成器返回生成
while True:
try:
print (next(f), end=" ")
except StopIteration:
sys.exit()
执行以上程序,输出结果如下:
0 1 1 2 3 5 8 13 21 34 55
Python函数
函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段
定义一个函数
- 函数代码块以 def 关键词开头,后接函数标识符名称和圆括号 ()
- 任何传入参数和自变量必须放在圆括号中间,圆括号之间可以用于定义参数
- 函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明
- 函数内容以冒号起始,并且缩进
- return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回 None
语法
Python 定义函数使用 def 关键字,一般格式如下:
def 函数名(参数列表):
函数体
默认情况下,参数值和参数名称是按函数声明中定义的顺序匹配起来的
函数调用
接收返回值 = 函数名(传入参数)
参数传递
在 python 中,类型属于对象,变量是没有类型的
可更改(mutable)与不可更改(immutable)对象
在 python 中,strings, tuples, 和 numbers 是不可更改的对象,而 list,dict 等则是可以修改的对象
- **不可变类型:**变量赋值 a=5 后再赋值 a=10,这里实际是新生成一个 int 值对象 10,再让 a 指向它,而 5 被丢弃,不是改变a的值,相当于新生成了a
- **可变类型:**变量赋值 la=[1,2,3,4] 后再赋值 la[2]=5 则是将 list la 的第三个元素值更改,本身la没有动,只是其内部的一部分值被修改了
python 函数的参数传递:
- **不可变类型:**类似 c++ 的值传递,如 整数、字符串、元组。如fun(a),传递的只是a的值,没有影响a对象本身。比如在 fun(a)内部修改 a 的值,只是修改另一个复制的对象,不会影响 a 本身
- **可变类型:**类似 c++ 的引用传递,如 列表,字典。如 fun(la),则是将 la 真正的传过去,修改后fun外部的la也会受影响
python 中一切都是对象,严格意义我们不能说值传递还是引用传递,我们应该说传不可变对象和传可变对象
参数
以下是调用函数时可使用的正式参数类型:
- 必需参数
- 关键字参数
- 默认参数
- 不定长参数
必需参数
必需参数须以正确的顺序传入函数,调用时的数量必须和声明时的一样
关键字参数
关键字参数和函数调用关系紧密,函数调用使用关键字参数来确定传入的参数值
使用关键字参数允许函数调用时参数的顺序与声明时不一致,因为 Python 解释器能够用参数名匹配参数值
默认参数
调用函数时,如果没有传递参数,则会使用默认参数
不定长参数
你可能需要一个函数能处理比当初声明时更多的参数。这些参数叫做不定长参数,和上述 2 种参数不同,声明时不会命名
def functionname([普通参数,] *不定长参数 ):
function_suite
return [expression]
- 加了星号 ***** 的参数会以元组(tuple)的形式导入,存放所有未命名的变量参数
- 如果在函数调用时没有指定参数,它就是一个空元组
- 还有一种参数带两个星号 **
- 加了两个星号 ** 的参数会以字典的形式导入
def functionname([普通参数,] **不定长参数 ):
function_suite
return [expression]
# 可写函数说明
def printinfo( arg1, **vardict ):
print (arg1)
print (vardict)
printinfo(1,a=2,b=3) # 对**不定长参数传值时,必须用关键字传入,需写成:键=值 的形式
以上实例输出结果:
1
{'a': 2, 'b': 3}
声明函数时,参数中星号 ***** 可以单独出现
如果单独出现星号 ***** ,则后面的参数必须用关键字传入
def f(a,b,*,c):
return a+b+c
f(1,2,3) #错误
f(1,2,c=3) #正确
匿名函数
python 使用 lambda 来创建匿名函数
所谓匿名,意即不再使用 def 语句这样标准的形式定义一个函数
- lambda 只是一个表达式,函数体比 def 简单很多
- lambda的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去
- lambda 函数拥有自己的命名空间,且不能访问自己参数列表之外或全局命名空间里的参数
lambda语法
lambda 函数的语法只包含一个语句,如下:
lambda [arg1 [,arg2,.....argn]]:expression
如下实例:
sum = lambda arg1, arg2 : arg1 + arg2 # 调用sum函数
print ("相加后的值为 : ", sum( 10, 20 )) # 输出30
return语句
return [表达式] 语句用于退出函数,选择性地向调用方返回一个表达式。不带参数值的return语句返回None
强制位置参数
Python3.8 新增了一个函数形参语法: / ,用来指明函数形参必须使用指定位置参数,不能使用关键字参数的形式
在以下的例子中,形参 a 和 b 必须使用指定位置参数,c 或 d 可以是位置形参或关键字形参,而 e 或 f 要求为关键字形参:
def f(a, b, /, c, d, *, e, f):
print(a, b, c, d, e, f)
f(10, 20, 30, d=40, e=50, f=60) # 正确调用方法
f(10, b=20, c=30, d=40, e=50, f=60) # 错误,b 不能使用关键字参数的形式
f(10, 20, 30, 40, 50, f=60) # 错误,e 必须使用关键字参数的形式
Python3 模块
模块是一个包含所有你定义的函数和变量的文件,其后缀名是.py。模块可以被别的程序引入,以使用该模块中的函数等功能。这也是使用 python 标准库的方法
下面是一个使用 python 标准库中模块的例子
import sys
print('命令行参数如下:')
for i in sys.argv:
print(i)
print('\n\nPython 路径为:', sys.path, '\n')
- import sys 引入 python 标准库中的 sys.py 模块;这是引入某一模块的方法
- sys.argv 是一个包含命令行参数的列表
- sys.path 包含了一个 Python 解释器自动查找所需模块的路径的列表
import 语句
想使用 Python 源文件,只需在另一个源文件里执行 import 语句,语法如下:
import module1[, module2[,... moduleN]
- 当解释器遇到 import 语句,如果模块在当前的搜索路径就会被导入
- 搜索路径是一个解释器会先进行搜索的所有目录的列表
- 一个模块只会被导入一次,不管你执行了多少次import,这样可以防止导入模块被一遍又一遍地执行
搜索路径是在Python编译或安装的时候确定的,安装新的库应该也会修改。搜索路径被存储在sys模块中的path变量,做一个简单的实验,在交互式解释器中,输入以下代码:
>>> import sys
>>> sys.path
['', '/usr/lib/python3.4', '/usr/lib/python3.4/plat-x86_64-linux-gnu', '/usr/lib/python3.4/lib-dynload', '/usr/local/lib/python3.4/dist-packages', '/usr/lib/python3/dist-packages']
>>>
- sys.path 输出是一个列表,其中第一项是空串’’,代表当前目录(若是从一个脚本中打印出来的话,可以更清楚地看出是哪个目录),或执行python解释器的目录(对于脚本的话就是运行的脚本所在的目录)
- 如果当前目录下存在与要引入模块同名的文件,就会把要引入的模块屏蔽掉
- 可以在脚本中修改sys.path来引入一些不在搜索路径中的模块
可以使用模块名称来访问函数
如果你打算经常使用一个函数,你可以把它赋给一个本地的名称
import 模块名
模块名.方法名() #直接调用模块中的方法
本地方法名 = 模块名.方法名 #为模块中的方法指定一个本地名称,注意不要加括号
本地方法名() #使用本地方法名调用函数
from … import 语句
Python 的 from 语句让你从模块中导入一个指定的部分到当前命名空间中,语法如下:
from 模块名 import 函数名1[, 函数名2[, ... 函数名N]]
函数名1() #可以直接使用模块中的函数,而不用写 模块名.函数名
这个声明不会把整个模块导入到当前的命名空间中,它只会将模块里的指定函数引入进来
from 模块名 import * #导入一个模块中的所有函数,不建议这么做
这将把模块中的所有名字都导入进来,但是那些由单一下划线(_)开头的名字不在此例。大多数情况, Python程序员不使用这种方法,因为引入的其它来源的命名,很可能覆盖了已有的定义
深入模块
模块除了方法定义,还可以包括可执行的代码
- 这些代码一般用来初始化这个模块
- 这些代码只有在第一次被导入时才会被执行
每个模块有各自独立的符号表,在模块内部为所有的函数当作全局符号表来使用
模块的作者可以在模块内部使用这些全局变量,而不用担心把其他用户的全局变量搞混
模块是可以导入其他模块的。在一个模块(或者脚本,或者其他地方)的最前面使用 import 来导入一个模块,当然这只是一个惯例,而不是强制的,被导入的模块的名称将被放入当前操作的模块的符号表中
__name__属性
一个模块被另一个程序第一次引入时,其主程序将运行。如果我们想在模块被引入时,模块中的某一程序块不执行,我们可以用__name__属性来使该程序块仅在该模块自身运行时执行
if __name__ == '__main__':
print('程序自身在运行')
else:
print('我来自另一模块')
说明: 每个模块都有一个__name__属性,当其值是'__main__'时,表明该模块自身在运行,否则是被引入
dir() 函数
内置的函数 dir() 可以找到模块内定义的所有名称。以一个字符串列表的形式返回:
>>> import fibo, sys
>>> dir(fibo)
['__name__', 'fib', 'fib2']
>>> dir(sys)
['__displayhook__', '__doc__', '__excepthook__', '__loader__', '__name__',
'__package__', '__stderr__', '__stdin__', '__stdout__',
'_clear_type_cache', '_current_frames', '_debugmallocstats', '_getframe',
'_home', '_mercurial', '_xoptions', 'abiflags', 'api_version', 'argv',
'base_exec_prefix', 'base_prefix', 'builtin_module_names', 'byteorder',
'call_tracing', 'callstats', 'copyright', 'displayhook',
'dont_write_bytecode', 'exc_info', 'excepthook', 'exec_prefix',
'executable', 'exit', 'flags', 'float_info', 'float_repr_style',
'getcheckinterval', 'getdefaultencoding', 'getdlopenflags',
'getfilesystemencoding', 'getobjects', 'getprofile', 'getrecursionlimit',
'getrefcount', 'getsizeof', 'getswitchinterval', 'gettotalrefcount',
'gettrace', 'hash_info', 'hexversion', 'implementation', 'int_info',
'intern', 'maxsize', 'maxunicode', 'meta_path', 'modules', 'path',
'path_hooks', 'path_importer_cache', 'platform', 'prefix', 'ps1',
'setcheckinterval', 'setdlopenflags', 'setprofile', 'setrecursionlimit',
'setswitchinterval', 'settrace', 'stderr', 'stdin', 'stdout',
'thread_info', 'version', 'version_info', 'warnoptions']
如果没有给定参数,那么 dir() 函数会罗列出当前定义的所有名称
标准模块
有些模块直接被构建在解析器里,这些虽然不是一些语言内置的功能,但是他却能很高效的使用,甚至是系统级调用也没问题
这些组件会根据不同的操作系统进行不同形式的配置,比如 winreg 这个模块就只会提供给 Windows 系统
应该注意到这有一个特殊的模块 sys ,它内置在每一个 Python 解析器中。变量 sys.ps1 和 sys.ps2 定义了主提示符和副提示符所对应的字符串:
>>> import sys
>>> sys.ps1
'>>> '
>>> sys.ps2
'... '
包
- 包是一种管理 Python 模块命名空间的形式,采用"点模块名称",比如一个模块的名称是 A.B, 那么他表示一个包 A中的子模块 B
- 采用点模块名称这种形式就不用担心不同库之间的模块重名的情况
- 在导入一个包的时候,Python 会根据 sys.path 中的目录来寻找这个包中包含的子目录
- 目录只有包含一个叫做 _init_.py 的文件才会被认作是一个包,主要是为了避免一些滥俗的名字(比如叫做 string)不小心的影响搜索路径中的有效模块
- 最简单的情况,放一个空的文件
__init__.py就可以了,当然这个文件中也可以包含一些初始化代码或者为 __all__变量赋值
注意当使用 from package import item 这种形式的时候,对应的 item 既可以是包里面的子模块(子包),或者包里面定义的其他名称,比如函数,类或者变量
import 语法会首先把 item 当作一个包定义的名称,如果没找到,再试图按照一个模块去导入,如果还没找到,抛出一个 :exc:ImportError 异常
反之,如果使用形如 import item.subitem.subsubitem 这种导入形式,除了最后一项,都必须是包,而最后一项则可以是模块或者是包,但是不可以是类,函数或者变量的名字
从一个包中导入*
导入语句遵循如下规则:如果包定义文件 __init__.py存在一个叫做 __all__ 的列表变量,那么在使用 from package import * 的时候就把这个列表中的所有名字作为包内容导入
如果__all__没有定义,则 from 包名 import * 语法不会导入任何子模块
__all__ = ["echo", "surround", "reverse"]
- 这表示当你使用from 包名 import * 这种用法时,你只会导入包里面这三个子模块
记住,使用 from 包名 import 模块名 这种方法永远不会有错。这也是推荐的方法。除非是你要导入的子模块有可能和其他包的子模块重名
如果在结构中包是一个子包(比如这个例子中对于包sound来说),而你又想导入兄弟包(同级别的包)你就得使用导入绝对的路径来导入。比如,如果模块sound.filters.vocoder 要使用包 sound.effects 中的模块 echo,你就要写成 from sound.effects import echo
无论是隐式的还是显式的相对导入都是从当前模块开始的。主模块的名字永远是__main__,一个Python应用程序的主模块,应当总是使用绝对路径引用
Python错误和异常
Python 有两种错误很容易辨认:语法错误和异常
Python assert(断言)用于判断一个表达式,在表达式条件为 false 的时候触发异常
异常
- 即便 Python 程序的语法是正确的,在运行它的时候,也有可能发生错误。运行期检测到的错误被称为异常
- 大多数的异常都不会被程序处理,都以错误信息的形式展现
- 异常以不同的类型出现,这些类型都作为信息的一部分打印出来
- 错误信息的前面部分显示了异常发生的上下文,并以调用栈的形式显示具体信息
异常处理
try/except
异常捕捉可以使用 try/except 语句
try:
执行代码
except 异常类型1: #可以有多个except子句
异常处理代码1
except 异常类型2:
异常处理代码2
except: #接收任意类型异常
raise #将异常向上抛出
try 语句按照如下方式工作
- 首先执行 try 子句(在关键字 try 和关键字 except 之间的语句)
- 如果没有异常发生,忽略 except 子句,try 子句执行后结束
- 如果在执行 try 子句的过程中发生了异常,那么 try 子句余下的部分将被忽略,如果异常的类型和 except 之后的名称相符,那么对应的 except 子句将被执行
- 如果一个异常没有与任何的 excep 匹配,那么这个异常将会传递给上层的 try 中
注意:
-
一个 try 语句可能包含多个except子句,分别来处理不同的特定的异常。最多只有一个分支会被执行
-
处理程序将只针对对应的 try 子句中的异常进行处理,而不是其他的 try 的处理程序中的异常
-
一个except子句可以同时处理多个异常,这些异常将被放在一个括号里成为一个元组,例如:
except (RuntimeError, TypeError, NameError): 异常处理代码 -
最后一个except子句可以忽略异常的名称,它将被当作通配符使用。你可以使用这种方法打印一个错误信息,然后再次把异常抛出
-
异常处理并不仅仅处理那些直接发生在 try 子句中的异常,而且还能处理子句中调用的函数(甚至间接调用的函数)里抛出的异常
try/except…else
try/except 语句还有一个可选的 else 子句,如果使用这个子句,那么必须放在所有的 except 子句之后
else 子句将在 try 子句没有发生任何异常的时候执行
# 在try语句中判断文件是否可以打开,如果打开文件时正常的没有发生异常则执行else部分的语句,读取文件内容
for arg in sys.argv[1:]:
try:
f = open(arg, 'r')
except IOError:
print('cannot open', arg)
else: # 若未发生异常则执行以下语句
print(arg, 'has', len(f.readlines()), 'lines')
f.close()
- 使用 else 子句比把所有的语句都放在 try 子句里面要好,这样可以避免一些意想不到,而 except 又无法捕获的异常
try-finally 语句
try-finally 语句无论是否发生异常都将执行最后的代码,既 finally 子句中的内容一定会被执行
如果一个异常在 try 子句里(或者在 except 和 else 子句里)被抛出,而又没有任何的 except 把它截住,那么这个异常会在 finally 子句执行后被抛出
抛出异常
Python 使用 raise 语句抛出一个指定的异常
raise语法格式如下:
raise [异常类型[(参数)]] #[]内为可选参数
raise 唯一的一个参数指定了要被抛出的异常。它必须是一个异常的实例或者是异常的类(也就是 Exception 的子类)
用户自定义异常
可以通过创建一个新的异常类来拥有自己的异常。异常类继承自 Exception 类,可以直接继承,或者间接继承,例如:
class MyError(Exception):
def __init__(self, value):
self.value = value
def __str__(self):
return repr(self.value)
当创建一个模块有可能抛出多种不同的异常时,一种通常的做法是为这个包建立一个基础异常类,然后基于这个基础类为不同的错误情况创建不同的子类
class Error(Exception):
pass
class InputError(Error):
def __init__(self, expression, message):
self.expression = expression
self.message = message
class TransitionError(Error):
def __init__(self, previous, next, message):
self.previous = previous
self.next = next
self.message = message
大多数的异常的名字都以"Error"结尾,就跟标准的异常命名一样
预定义的清理行为with
一些对象定义了标准的清理行为,无论系统是否成功的使用了它,一旦不需要它了,那么这个标准的清理行为就会执行
关键词 with 语句 就可以保证诸如文件之类的对象在使用完之后一定会正确的执行他的清理方法
with open("myfile.txt") as f:
for line in f:
print(line, end="")
以上这段代码执行完毕后,就算在处理过程中出问题了,文件 f 总是会关闭
本文详细介绍了Python编程中的条件控制语句,包括if、elif和else的使用,以及if语句的嵌套。接着,文章探讨了Python的循环语句,讲解了while循环和for循环的语法,特别是无限循环、while循环的else子句以及for循环中的break和continue语句。此外,还提到了pass语句的作用。文章进一步讨论了Python的迭代器和生成器,解释了如何创建和使用迭代器和生成器。最后,简述了Python函数的基本概念,包括定义函数、函数调用、参数传递和返回值。
1051

被折叠的 条评论
为什么被折叠?



