快捷搜索:  汽车  科技

python接口编程(后端编程Python3-函数)

python接口编程(后端编程Python3-函数)在Windows上,文档是以Windows帮助文件形式提供的。依次单击开始、所有程序、Python 3.x、Python手册 可以启动该帮助文件。该工具包含了 Index与Search 功能,使得寻找适当的文档比较容易。在UNIX系统上,文档是以HTML文件格式存在的。除超链接外,还有很多索引页,在每个HTML页的左部,还提供了方便的快速搜索功能。Python在线文档提供的数量可观的索引文档仍具有很大的参考价值,这些索引文档既包括关于语言本身的,更有关于Python的广泛的标准库的。这些文档可以在docs.python.org处存取,Python本身也提供了这些文档。Lambda函数是表达式,因此可以在需要使用的地方创建,不过,这类函数要比通常的函数受更多的限制。方法是与特定数据类型关联的函数,并且只能与数据类型关联在一起使用.Python提供了很多内置函数,其标准库与第三方库又增加了数百

本节是第五讲的第十小节,上节为大家介绍了Python语言的控制结构包括条件分支和循环以及异常处理,本节将为大家介绍Python语言的函数。

自定义函数(Custom Functions)

函数可用于将相关功能打包并参数化。在Python中,可以创建4种函数:全局函数、局部函数、lambda函数、方法。

迄今为止,我们所创建的函数都是全局函数。全局对象(包括函数)可以由创建该对象的同一个模块(同一个.py文件)中的任意代码存取。局部函数(也称为嵌套函数)定义在其他函数之内,本地函数只对对其进行定义的函数是可见的。对于创建不在其他地方使用的小helper函数,本地函数尤其有用。

Lambda函数是表达式,因此可以在需要使用的地方创建,不过,这类函数要比通常的函数受更多的限制。

方法是与特定数据类型关联的函数,并且只能与数据类型关联在一起使用.

Python提供了很多内置函数,其标准库与第三方库又增加了数百个函数(如果对所有方法进行计数,就有数千个),因此,很多时候,我们所需要的函数实际上已经写好了。由于这一原因,检测Python的在线文档(以便了解有哪些可用的函数或方法总是值得的。参考“在线文档”工具条。

Python在线文档提供的数量可观的索引文档仍具有很大的参考价值,这些索引文档既包括关于语言本身的,更有关于Python的广泛的标准库的。这些文档可以在docs.python.org处存取,Python本身也提供了这些文档。

在Windows上,文档是以Windows帮助文件形式提供的。依次单击开始、所有程序、Python 3.x、Python手册 可以启动该帮助文件。该工具包含了 Index与Search 功能,使得寻找适当的文档比较容易。在UNIX系统上,文档是以HTML文件格式存在的。除超链接外,还有很多索引页,在每个HTML页的左部,还提供了方便的快速搜索功能。

解释器本身也提供了一些有用的帮助信息。不带参数调用help()函数,就会进入在线帮助系统一一之后简单地遵循指令,就可以获取关心的信息,使用完毕后, 输入“q”或“quit”就会返回到解释器。如果知道自己需要获取哪个模块或数据类型的帮助信息,就可以将模块名或数据类型作为参数调用help()函数。比如, help(str)提供了关于str数据类型的信息,包括其所有方法;help(dict.update)提供了 dict这一组合数据类型的update()方法的信息,help(os)显示os模块的信息(假定 该模块已导入)。

熟悉Python后,通常只需要关注某数据类型提供了哪些属性(比如方法)就已足够,这一信息可以使用dir()函数获取——比如,dir(str)可以列出所有字符串方法, dir(os)列出os模块的所有常量与函数(假定该模块已导入)。

创建一个全局函数或局部函数的通用语法格式如下:

def functionName(parameters):

suite

其中,parameters是可选的,如果有多于一个参数,就可以写成逗号分隔的标识符序列,或identifier=value对序列(稍后进行讨论)。

比如,下面是一个使用heron公式计算三角形面积的实例:

def heron(a b c):

s = (a b c)/2

return math.sqrt(s * (s - a) * (s - b) * (s - c))

在该函数内部,每个参数a、b与c都会使用传递的相应参数值进行初始化。调用该函数时,必须提供全部的参数值,比如,heron(3 4 5)。如果提供的参数值不足或过多,就会产生一个TypeError异常。

Python中的每个函数都有一个返回值,尽管忽略返回值是完全可以的(也是通常的做法)。返回值可以是单独的一个值,也可以是一组值,还可以是组合类型的值,因此对于返回值的类型实际上没有限制。我们可以在函数任意位置使用return语句返回, 如果return不带参数,或者根本就没有使用return语句,那么函数将返回None。

有些函数的参数具有明显的默认值,比如,下面给出的函数用于计算字符串中的字母数,明显地默认为ASCII字母:

def letter_count(text letters=string.ascii_letters):

letters = frozenset(letters)

count = 0

for char in text:

if char in letters:

count = 1

return count

使用parameter=default语法,我们指定了参数letters的默认值,这使得我们可以只使用一个参数来调用 letter_count() 比如,letter_count("Maggie and Hopey")。 这里, 在函数内部,letters将被赋值为以默认值形式给定的字符串。但是,我们也可以改变这种默认值,比如,使用一个额外的位置参数,letter_count(“Maggie and Hopey" ”aeiouAEIOU“),或使用一个关键字参数(接下来会讲述),比如,letter_count("Maggie and Hopey" letters="aeiouAEIOU")。

需要注意的是,参数语法不允许在没有默认值的参数后面跟随默认值,因此,def bad(a b=1 c):不能生效。另一方面,在传递参数时,并不是必须严格按照函数定义时的参数顺序——我们也可以使用关键字参数,以name=value的形式进行参数传递。

下面给出一个小函数,该函数的作用是返回给定的字符串,如果超过了指定的长度,就返回缩减版并附加一个indicator:

def shorten(text length=25 indicator="..."):

if len(text) > length:

text = text[:length - len(indicator)] indicator

return text

下面是使用不同字符串调用该函数的一些实例:

shorten("The Road") # returns: 'The Road'

shorten(length=7 text="The Road") # returns: 'The …'

shorten("The Road" indicator="&" length=7) # returns: 'The Ro&'

shorten("The Road" 7 "&") # returns: 'The Ro&'

由于length与indicator都有默认值,因此都可以完全忽略,这时使用的就是在函数定义中的默认值——比如在上面的第一个函数调用中。在第二个函数调用中,为两个指定的参数都使用了关键字参数,因此可以根据需要对其指定。第三个函数调用混合使用了位置参数与关键字参数,首先指定的是第一个位置参数(位置参数必须总是在关键字参数之前) 之后是两个关键字参数。第四个调用则简单地使用了关键字参数。

必备参数与可选参数的区别在于,带默认值的参数是可选的(因为Python可以使用默认值),没有默认值的参数是必备的(因为Python不能猜测)。巧妙地使用默认值可以简化代码,并使得函数调用更清晰。

给定默认值时,实际上是在执行def语句的时候创建的(也就是说,在创建该函数的时候),而不是在调用该函数的时候创建的。对固定变量,比如数字与字符串,这没有什么区别,但对于可变的参数,就存在一个微妙的陷阱。

def append_if_even(x lst=[]): # WRONG!

if x%2 ==0:

Ist.append(x)

return lst

在创建上面的函数时,lst参数被设置为引用一个新的列表,之后,在仅使用第一 个参数调用该函数时,默认的列表都将是函数本身创建时指定的那个列表——因此将不会再有新的列表得以创建。通常,这并不是我们所期待的程序行为——我们所期待的是,在每次仅使用第一个参数调用该函数时,都会创建一个新的空列表。

下面给出该函数的一个新版本,其中使用了针对默认的可变参数的惯用法:

def append_if_even(x lst=None):

if lst is None:

lst =[]

if x % 2 == 0:

Ist.append(x)

return lst

在每次仅使用第一个参数调用这一函数时,将创建一个新的列表,而如果给定了lst参数,则使用该参数指定的列表,就像前面的函数一样。这种惯用法(有一个默认的None 并创建一个新对象)应该用于需要使用默认参数的字典、列表、集合以及任何其他可变的数据类型。

下面这个函数版本稍短一些,其行为与上面完全一样:

def append_if_even(xt lst=None):

lst = [] if lst is None else lst

if x%2 ==0:

Ist.append(x)

return lst

使用条件表达式,可以减少一行用于每个参数(拥有可变的默认参数值)的代码。

名称与Docstrings(Name and Docstrings)

对函数及其参数进行合理的命名可以使得其他程序员更容易理解函数的用途和用法——对我们自己而言也是如此,尤其在函数创建了一段时间之后。下面给出了一些值得考虑的经验。

■ 使用命名框架,并保持一致性。我们对常量使用UPPERCASE 对类(包括异常)使用TitleCase 对GUI (图形用户界面)函数与方法使用camel-Case 对其他对象则使用lowercase或lowercase_with_underscores 。

■ 对所有名称,要避免使用缩略,除非是标准化并广泛使用的。

■ 合理地使用变量与参数名:x非常适合用作x坐标参数,i适合于用作循环计数器等。通常情况下,名称应该足够长以具备很好的描述性,名称应该描述数据的含义,而不是其类型(比如,amount_due 而非money) 除非某种使用对特定类型是通用的,比如,shorten()实例的text参数。

■ 函数名与方法名应该可以表明其行为或返回值(依赖于其关心的重点),但绝不应该是为了表示如何实现的——因为实现方法因人而异。

下面给出一些命名实例:

def find(l s i=0): # BAD

def linear_search(l s i=0): # BAD

def first_index_of(sorted_name_Iist name start=0): # GOOD

这3个函数的功能都是返回名称列表中出现的第一个名称的索引位置,从给定的起点位置开始査找,并假定列表是经过排序的。

第一个函数不好的地方在于,名称没有给岀要寻找的对象的相关线索,参数(大概)也只是给出了需要的类型(列表、字符串、整数)而没有给出其内涵。第二个函数不好的地方在于,函数名描述了使用的原始算法——但这是可能改变的,对函数的使用者来说这或许没有很大影响,但如果函数名代表的是线性搜索,而实际上的算法已经变更为二叉搜索,那么对维护者而言会带来困惑。第三个函数是理想的,因为函数名表明了应该返回什么信息,参数名则明确地指出了需要的是什么。

上面的3个函数都没有指出如果没有找到搜索的名称应该怎么处理——是返回比如-1 还是产生异常?这样的信息需要形成文档,并供函数的使用者使用。

通过使用docstring 我们可以为任何函数添加文档信息,docstring可以是简单地添加在def行之后、函数代码开始之前的字符串。比如,下面给出的是前面展示过的 shorten()函数,但这里给出的是完整版:

def shorten(text length=25 indicator="..."):

"""Returns text or a truncated copy with the indicator added

text is any string; length is the maximum length of the returned

string (including any indicator); indicator is the string added at

the end to indicate that the text has been shortened

>>> shorten("The Road")

'The Road'

>>> shorten("No Country for Old Men" 20)

'No Country for Ol...'

>>> shorten("Cities of the Plain" 15 "*")

'Cities of the *'

"""

if len(text) > length:

text = text[:length - len(indicator)] indicator

return text

对函数文档而言,如果比函数本身还长,也并非不同寻常。常规的做法是,docstring 的第一行只是一个简短的描述,之后是一个空白行,再之后跟随的就是完整的描述信息,如果是交互式输入再执行的程序,还会给出一些实例。后面我们将看到函数文档中的实例怎样用于单元测试。

参数与参数拆分(Argument and Parameter Unpacking)

前面章节中讲过,我们可以使用序列拆分操作符(*)来提供位置参数。比如,如果需要计算某个三角形的面积,并且各个边的长度存放在一个列表中,就可以进行类似于如下的调用:heron(sides[0] sides[1] sides[2]) 或简单地对列表进行拆分,并使用更简单的调用方式heron(*sides)。如果列表(或其他序列)包含比函数参数更多的项数,就可以使用分片提取出合适的参数。

我们也可以在函数参数列表中使用序列拆分操作符,在创建使用可变数量的位置参数的函数时,这种方法是有用的。下面给出了一个product()函数,用于计算给定参数的积:

def product(*args):

result = 1

for arg in args:

result *= arg

return result

这一函数有一个名为args的参数,在args前面有一个*这意味着,在函数内部 参数args可以是一个元组,其项数随着给定的位置参数个数的变化而变化,下面给出 了几个该函数的调用实例:

product(1 2 3 4) # args == (1 2 3 4); returns: 24

product(5 3 8) # args == (5 3 8); returns: 120

product(11) # args == (11 ); returns: 11

我们可以将关键字参数跟随在位置参数后面,如下面这个用于计算参数和的函数 其中每个参数被按给定的幂进行运算,例如:

def sum_of_powers(*args power=1):

result = 0

for arg in args:

result = arg ** power

return result

这一函数可以只使用位置参数进行调用,比如sum_of_powers(1 3 5) 也可以同时使用位置参数与关键字参数,比如sum_of_powers(1 3 5 power=2)。将*本身作为参数也是可能的,用于表明在*后不应该再出现位置参数,但关键字参数是允许的。

下面给出的是heron()函数的修改版,其中,该函数接收恰好3个位置参数,还有一个可选的关键字参数。

def heron2(a b c * units="meters"):

s = (a b c)/2

area = math.sqrt(s * (s - a) * (s - b) * (s - c))

return "{0}{1}".format(area units)

#下面给出几个调用实例:

heron2(25 24 7) # returns: '84.0 meters'

heron2(41 9 40 units="inches") # returns: '180.0 inches'

heron2(25 24 7 "inches") # WRONG! raises TypeError

在上面第三个调用中,我们尝试传递第四个位置参数,但*不允许这样做,并因此产生TypeError异常。

如果将*作为第一个参数,那么不允许使用任何位置参数,并强制调用该函数时使用关键字参数,下面给出一个(构想的)这样的函数:

def print_setup(* paper="Letter" copies=1 color=False):

我们可以不使用任何参数调用print_setup() 并接受默认值。或者我们可以改变某些或全部默认值,比如print_setup(paper="A4" color=True) 但如果我们试图使用位置参数,比如print_setup("A4") 就会产生TypeError异常。

就像我们可以对序列进行拆分来产生函数的位置参数一样,我们也可以使用映射拆分操作符(**)来对映射进行拆分我们可以使用**将字典传递给pririt_setup()函数,比如:

options = dict(paper="A4" color=True)

print_setup(**options)

这里,options字典的键-值对在拆分时,每个键的值被赋予适当的参数,参数的名称与键相同。如果该字典包含没有对应参数的键,就会产生TypeError异常。任何参数,如果字典没有相应的项,则将其设置为默认值——如果没有默认值,就产生TypeError 异常。

我们也可以在参数中使用映射拆分操作符,通过这种方式创建的函数可以接受给定的任意数量的关键字参数。下面给出了一个add_person_details()函数,该函数接受社会安全号参数ssn和位置参数surname 以及任意数量的关键字参数:

def add_person_details(ssn surname **kwargs):

print("SSN =" ssn)

print(" surname=" surname)

for key in sorted(kwargs):

print(" {0} = {1}".format(key kwargs[key]))

这个函数可以仅使用两个位置参数进行调用,也可以附带额外的信息,比如, add_person_details(83272171 "Luther” forename="Lexis" age=47) 这种方式带来了很大的灵活性,比如,我们可以接受可变数量的位置参数与关键字参数:

def print_args(*args **kwargs):

for i arg in enumerate(args):

print("positional argument {0} = {1}".format(i arg))

for key in kwargs:

print("keyword argument {0} = {1}".format(key kwargs[key]))

上面的函数只是打印出给定的参数,该函数可以不带参数调用,也可以是有任意数量的位置参数与关键字参数。

存取全局范围的变量(Accessing Variables in the Global Scope)

有时候,设置一些可以由程序中不同参数存取的全局变量会带来很多便利。对于 “常量”,这不会有什么问题,但对于变量,这不是一个好做法——尽管对短小的仅供自己使用的程序而言,这种做法并非完全不合理。

digit_names.py程序接受命令行中输入的可选的语言(“en”或"fr")和一个数字作为参数,并输出给定的每个数字对应的名称。因此,如果在命令行中给定“123”作为参数,那么该程序将输出“one two three”。该程序有3个全局变量:

Language = "en"

ENGLISH ={0: "zero" 1: "one" 2: "two" 3: "three”,4: “four”,5: "five" 6: ”six”,7: ''seven" 8: "eight" 9: "nine"}

在上面的定义中,我们遵循了命名约定:全部大写的变量名代表常量。此外,将默认语言设置为英语(Python不提供创建变量的直接方式,而是依赖于程序员对命名约定的遵从)。程序的其他位置,我们访问Language变量,并用其选择要使用的适当的字典。

def print_digits(digits):

dictionary = ENGLISH if Language == "en" else FRENCH

for digit in digits:

print(dictionary[int(digit)] end=" ")

print()

Python处理到本函数中的Language变量时,会在局部(function)范围内进行査找 由于没有找到,因此又继续在全局(.py文件)内进行査找,并找到其定义位置。第一个print()调用中使用的关键字参数end在下面的“print()函数”工具条中进行了解释。

print()函数可以接受任意数量的位置参数,还有3个关键字参数,即sep end与 file。所有关键字参数都有默认值,sep参数的默认值为空格。如果给定了两个或更多的位置参数,那么在打印这些参数时,参数之间以空格分隔。如果只有一个位置参数 那么sep参数不起实际作用。end参数的默认值为\n,这也是为什么在调用print()的末尾会打印一个换行。file参数的默认值为sys.stdout 标准输出流,通常为控制台。

对任意的关键字参数,都可以为其指定需要的值,而不使用默认值。比如,file 可以设置为一个打开并进行写入与追加操作的文件对象 sep与end都可以设置为其他字符串,包括空字符串。

如果需要在同一行打印几个项,一种通常的做法是调用print()打印项时将end 设置为适当的分隔符,之后在最后不带参数调用print(),因为这只是打印一个换行。 要查看实例,参阅print_digits()函数。

下面是程序的main()函数的代码,可以在必要的时候改变Language变量的值,并调用print_digits()生成输出信息。

def main():

if len(sys.argv) == 1 or sys.argv[1] in "--help"}:

print("usage: {0} [en|fr] number".format(sys.argv[0]))

sys.exit()

args = sys.argv[1:]

if args[0] in {"en" "fr"}:

global Language

Language = args.pop(0)

print_digits(args.pop(0))

这里需要注意的是global语句的使用 该语句的作用是告知Python 某个变量的作用范围是全局(文件)范围,对变量的赋值应该应用于全局变量,而不是创建一个同名的本地变量。

如果不使用global语句 程序也可以运行,但Python在if语句中遇到变量Language 时,将在局部(函数)范围内査找,由于找不到就创建一个新的名为Language的局部变量,而不改变全局的Language变量。只有在程序以参数“fr"运行时,这一微妙的 bug才会表现为一个错误,因为局部的Language变量将被创建并设置为“fr",而 print_digits()函数中使用的全局Language变量仍保持为“en”。

Lambda 函数(Lambda Functions)

Lambda函数是使用如下语法格式创建的:

lambda parameters: expression

parameters是可选的,如果提供,通常是逗号分隔的变量名形式,也就是位置参数,当然,def语句支持的完整参数语法格式也可以使用。expression不能包含分支或循环(但允许使用条件表达式),也不能包含return (或yield)语句,lambda表达式的结果是一个匿名函数。调用lambda函数时,返回的结果是对表达式计算产生的结果。 如果expression是一个元组,就应该使用圆括号将其包含起来。

下面给出一个简单的lambda函数,其作用是根据参数是否为1决定是否添加s:

s = lambda x:"" if x == 1 else "s"

lambda表达式会返回一个匿名函数,我们将该函数赋值给变量s。任何(可调用的)变量都可以使用圆括号进行调用,因此,给定某一操作处理的文件数,我们可以使用函数s()输出一条消息,类似于如下的方式:

print("{0} file{1} processed".format(count s(count)).

对内置的sorted()函数与list.sort()方法,Lambda函数通常用作键值函数。假定有一个元素列表,其中每个元素都是三元组(group number name) 我们想以不同的方式对这一列表进行排序。下面是这种列表的一个实例:

elements = [(2 12 "Mg") (1 11 "Na") (1 3 "Li") (2 4 "Be")]

对列表进行排序,可以得到如下的结果:

[(1 3 'Li') (1 11 'Na') (2 4 'Be') (2 12 'Mg')]

前面讲述sorted()函数时我们知道,我们可以提供键值函数来更改排序顺序。比如, 根据number与name对列表进行排序,而不是根据group、number与name的自然序。 我们可以写一个小函数:"def ignore0(e): return e[1] e[2]”,该函数可用作键值函数, 但创建大量这样的小函数会带来很多不便,因此,经常使用的替代方法是lambda函数:

elements.sort(key=lambda e: (e[1] e[2]))

这里,键值函数为lambda e:(e[1] e[2]) 其中e为列表中每个三元组元素。在表达式是元组并且lambda函数创建为一个函数的参数时,lambda表达式的圆括号是必需的。我们也可以使用分片达到同样的效果:

elements.sort(key=lambda e: e[1:3])

下面给出一个更精巧的版本,其中根据大小写不敏感的名称与编号顺序进行排序:

elements.sort(key=lambda e: (e[2].lower() e[1]))

下面给出两种等价的方法,其目标都是创建一个函数,用于使用常规的计算公式来计算三角形的面积:

area = lambda b h: 0.5 * b * h

def area(b h):

return 0.5 * b * h

我们可以调用area(6 5) 而不管函数是使用lambda表达式创建还是使用def语句创建,所得结果都是一样的。

另一种适宜使用lambda函数的场合是在需要创建默认字典时,回想上一章,如果需要使用不存在的键存取一个默认字典,就会创建一个适当的项(使用给定的键与默认值)。

minus_one_dict = collections.defaultdict(lambda: -1)

point_zero_dict = collections.defaultdict(lambda: (0 0))

message_dict = collections.defaultdict(lambda: "No message available")

如果我们使用一个不存在的键存取minus_one_dict字典,就会创建一个新项,其键就是这个不存在的键,值则为-1。类似地,对point_zero_dict字典,默认值则为元组(0 0);对 message_dict 字典,默认值为字符串"No message available"。

断言(Assertions)

函数如果接受了带无效数据的参数会发生什么?在算法实现时出现错误或进行不正确计算会导致怎样的结果?或许,最坏的结果就是程序继续执行,而没有任何(明显的)问题,没有谁能够察觉。一种有助于避免这种暗中危害问题的途径是编写测试,另一种方式是声明前提与后果,并在任何一方无法满足时提示错误信息。理想情况下,我们应该使用测试,同时也声明前提与后果。

前提与后果可以使用assert语句指定,其语法格式如下:

assert boolean_expression optional_expression

如果boolean_expression评价为False 就产生一个AssertionError异常。如果给定了可选的optional_expression 就将其用作AssertionError异常的参数-对提供错误消息而言,这种做法是有用的。要注意的是,断言是为开发者设计的,而不是面向终端用户的。通常程序使用中发生的问题(如丢失文件或无效的命令行参数)应该釆用其他途径处理,比如提供错误或日志消息。

下面给出product()函数的两个新版本。两个版本是等价的,都要求所有参数为非0值,并将使用参数0进行的调用视为编码错误。

def product(*args): # pessimistic

assert all(args) "0 argument"

result = 1

for arg in args:

result *= arg

return result

def product(*args): # optimistic

result = 1

for arg in args:

result *= arg

assert result "0 argument"

return result

左边的“pessimistic”版本对每个调用检査所有参数(或至多头0个参数);右边的 “optimistic”版本只对结果进行检查,毕竟,如果有任意参数为0 那么结果必然为0。

如果某个product()函数使用参数0进行调用,就会产生一个AssertionError异常, 并向错误流(sys.stderr 通常为控制台) 写入类似于如下的输出:

Traceback (most recent call last):

File "program.py" line 456 in <module>

x = product(1 2 0 4 8)

File "program.py" line 452 in product

assert result "0 argument"

AssertionError: 0 argument

Python自动地提供了回溯信息,其中给出了文件名、函数与行号,以及我们指定的错误消息。

在程序就绪并可以公开发布之后(当然,应该已经通过了所有测试,并且不违背 任何断言),应该怎样处理assert语句?我们可以通告Python不执行assert语句——在效果上,就是在运行时摒弃这些语句。这可以通过在运行程序时在命令行中指定-O选项来实现,比如,python -O program.py。另一种方法是将环境变量PYTHONOPTIMIZE 设置为0。如果docstrings对用户没用(通常没用),就可以使用-OO选项,其效果是摒弃assert语句与docstrings:注意没有哪个环境变量用于设置这一选项。有些开发者釆用一种简单的方法:产生程序的一个副本,其中所有assert语句被注释掉,如果可以通过测试,就发布这个注释了assert语句的版本。

以上内容部分摘自视频课程05后端编程Python-10函数,更多实操示例请参照视频讲解。跟着张员外讲编程,学习更轻松,不花钱还能学习真本领。

python接口编程(后端编程Python3-函数)(1)

猜您喜欢: