ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
# Python 函数 > 原文: [http://zetcode.com/lang/python/functions/](http://zetcode.com/lang/python/functions/) 在 Python 编程教程的这一部分中,我们介绍了 Python 中的函数。 ## Python 函数定义 函数是用于执行特定操作的可重用代码块。 使用函数的优点是: * 减少代码重复 * 将复杂的问题分解成更简单的部分 * 提高代码的清晰度 * 重用代码 * 信息隐藏 Python 中的函数是一等公民。 这意味着函数与 Python 中的其他对象具有同等的状态。 可以将函数分配给变量,存储在集合中或作为参数传递。 这给语言带来了额外的灵活性。 ## Python 函数类型 函数有两种基本类型:内置函数和用户定义函数。 内置函数是 Python 语言的一部分; 例如`dir()`,`len()`或`abs()`。 用户定义的函数是使用`def`关键字创建的函数。 ## Python 创建函数 使用`def`关键字创建一个函数。 函数块中的语句必须缩进。 ```py def function(): pass ``` `def`关键字后跟带有圆括号和冒号的函数名称。 缩进语句形成函数的主体。 该函数稍后在需要时执行。 我们说我们调用函数。 如果我们调用一个函数,则会执行函数体内的语句。 在调用函数之前,它们不会执行。 ```py myfunc() ``` 要调用函数,我们用圆括号指定函数名称。 `ret.py` ```py #!/usr/bin/env python """ The ret.py script shows how to work with functions in Python. Author: Jan Bodnar ZetCode, 2019 """ def show_module_name(): print(__doc__) def get_module_file(): return __file__ a = show_module_name() b = get_module_file() print(a, b) ``` 脚本顶部的字符串称为文档字符串。 它记录了当前脚本。 我们放入 Python 代码的文件称为模块。 我们定义两个函数。 第一个函数打印模块文档字符串。 第二个返回模块的路径。 函数可能会或可能不会返回值。 如果函数没有返回值,则它隐式返回`None`。 `__doc__`和`__file__`是特殊的状态属性。 请注意,属性的两侧都有两个下划线。 ```py $ ./ret.py The ret.py script shows how to work with functions in Python. Author: Jan Bodnar ZetCode, 2019 None C:/Users/Jano/PycharmProjects/Simple/simple.py ``` 这是程序的输出。 函数的定义必须先于其用法。 否则,口译员会抱怨`NameError`。 `func_prec.py` ```py #!/usr/bin/env python # func_prec.py def f1(): print("f1()") f1() #f2() def f2(): print("f2()") ``` 在上面的示例中,我们有两个函数定义。 一行被注释。 函数调用不能超出其定义。 ```py #f2() def f2(): print("f2()") ``` 仅在定义后才能调用`f2()`。 取消注释该行,我们得到一个`NameError`。 ## 在哪里定义函数 可以在模块,类或其他函数中定义函数。 在类内部定义的函数称为方法。 `defining.py` ```py #!/usr/bin/env python # defining.py class Some(): @staticmethod def f(): print("f() method") def f(): print("f() function") def g(): def f(): print("f() inner function") f() Some.f() f() g() ``` 在此示例中,我们在三个不同的位置定义了`f()`函数。 ```py # defining.py class Some(): @staticmethod def f(): print("f() method") ``` 静态方法在`Some`类中用装饰器定义。 ```py def f(): print("f() function") ``` 该函数在模块中定义。 ```py def g(): def f(): print("f() inner function") f() ``` 此处,`f()`函数在另一个`g()`函数内部定义。 这是一个内部函数。 ```py Some.f() f() g() ``` 通过使用方括号指定类名称,点运算符和函数名称来调用静态方法。 其他函数使用其名称和方括号来调用。 ```py $ ./defining.py f() method f() function f() inner function ``` 这是输出。 ## Python 函数是对象 Python 中的函数是对象。 它们可以像 Python 中的其他对象一样进行操作。 因此,职能被称为头等公民。 在其他 OOP 语言(例如 Java 或 C# )中,情况并非如此。 `fun_obj.py` ```py #!/usr/bin/env python # fun_obj.py def f(): """This function prints a message """ print("Today it is a cloudy day") print(isinstance(f, object)) print(id(f)) print(f.__doc__) print(f.__name__) ``` 在此脚本中,我们表明我们的函数也是一个对象。 ```py def f(): """This function prints a message """ print("Today it is a cloudy day") ``` 我们定义一个`f()`函数。 它将消息打印到控制台。 它还具有一个文档字符串。 ```py print(isinstance(f, object)) ``` `isinstance()`函数检查`f()`函数是否是`object`的实例。 Python 中的所有对象均从该基本实体继承。 ```py print(id(f)) ``` Python 中的每个对象都有一个唯一的 ID。 `id()`函数返回对象的 ID。 ```py print(f.__doc__) print(f.__name__) ``` 对象可能具有属性; 我们打印函数的两个属性:`__doc__`和`__name__`。 ```py $ ./fun_obj.py True 140353774014536 This function prints a message f ``` 这是程序的输出。 函数可以存储在集合中并传递给其他函数。 `fun_coll.py` ```py #!/usr/bin/env python # fun_coll.py def f(): pass def g(): pass def h(f): print(id(f)) a = (f, g, h) for i in a: print(i) h(f) h(g) ``` 我们定义了三个函数。 我们将它们放在一个元组中,然后将它们传递给函数。 ```py a = (f, g, h) for i in a: print(i) ``` 我们将三个函数对象放在一个元组中,并使用`for`循环遍历它。 ```py h(f) h(g) ``` 我们将`f()`和`g()`函数传递给`h()`函数。 ```py $ ./fun_coll.py <function f at 0x0000015B998E9D08> <function g at 0x0000015B998E9E18> <function h at 0x0000015B998E9840> 1492929912072 1492929912344 ``` 这是`fun_coll.py`程序的输出。 ## Python 中的三种函数 从特定的角度来看,我们可以辨别出三种函数。 始终可供使用的函数,必须导入的外部模块中包含的函数以及由程序员使用`def`关键字定义的函数。 `three_kinds.py` ```py #!/usr/bin/env python from math import sqrt def cube(x): return x * x * x print(abs(-1)) print(cube(9)) print(sqrt(81)) ``` 上面的代码中存在三种函数。 ```py from math import sqrt ``` `sqrt()`函数是从数学模块导入的。 ```py def cube(x): return x * x * x ``` `cube()`函数是一个自定义函数。 ```py print(abs(-1)) ``` `abs()`函数是易于访问的内置函数。 它是语言核心的一部分。 ## Python `return`关键字 创建一个函数来执行特定任务。 通常,这种任务会产生结果。 `return`关键字用于从函数返回值。 函数可能会也可能不会返回值。 如果一个函数没有`return`关键字,它将发送`None`。 `returning.py` ```py #!/usr/bin/env python # returning.py def show_message(msg): print(msg) def cube(x): return x * x * x x = cube(3) print(x) show_message("Computation finished.") print(show_message("Ready.")) ``` 我们定义了两个函数。 一个使用`return`关键字,另一个则不使用。 ```py def show_message(msg): print(msg) ``` `show_message()`函数不会显式返回值。 它在控制台上显示一条消息。 ```py def cube(x): return x * x * x ``` `cube()`函数计算一个表达式,并使用`return`关键字返回其结果。 ```py x = cube(3) ``` 在这一行中,我们称为`cube()`函数。 返回`cube()`函数的计算结果,并将其分配给`x`变量。 现在保存结果值。 ```py show_message("Computation finished.") ``` 我们以消息为参数调用`show_message()`函数。 该消息将打印到控制台。 我们不期望此函数有值。 ```py print(show_message("Ready.")) ``` 此代码产生两行。 一种是通过`show_message()`函数打印的消息。 另一个是`None`值,该值由没有`return`语句的函数隐式发送。 ```py $ ./returning.py 27 Computation finished. Ready. None ``` 这是示例输出。 我们可以从函数中发送多个值。 `return`关键字之后的对象用逗号分隔。 `returning2.py` ```py #!/usr/bin/env python # returning2.py n = [1, 2, 3, 4, 5] def stats(x): _mx = max(x) _mn = min(x) _ln = len(x) _sm = sum(x) return _mx, _mn, _ln, _sm mx, mn, ln, sm = stats(n) print(stats(n)) print(mx, mn, ln, sm) ``` 有`stats()`函数的定义。 此函数返回四个值。 ```py return _mx, _mn, _ln, _sm ``` `return`关键字发回四个数字。 这些数字用逗号分隔。 实际上,我们已经发送了包含这四个值的元组。 我们也可以返回列表而不是元组。 ```py mx, mn, ln, sm = stats(n) ``` 返回的值分配给局部变量。 ```py $ ./returning2.py (5, 1, 5, 15) 5 1 5 15 ``` 这是输出。 ## Python 函数重新定义 Python 本质上是动态的。 可以重新定义已经定义的函数。 `redefinition.py` ```py #!/usr/bin/env python # redefinition.py from time import gmtime, strftime def show_message(msg): print(msg) show_message("Ready.") def show_message(msg): print(strftime("%H:%M:%S", gmtime())) print(msg) show_message("Processing.") ``` 我们定义一个`show_message()`函数。 稍后,我们提供相同函数的新定义。 ```py from time import gmtime, strftime ``` 从时间模块中,我们导入两个函数,用于计算当前时间。 ```py def show_message(msg): print(msg) ``` 这是函数的第一个定义。 它仅将消息打印到控制台。 ```py def show_message(msg): print(strftime("%H:%M:%S", gmtime())) print(msg) ``` 在源代码的后面,我们设置了`showMessage()`函数的新定义。 该消息之前带有时间戳。 ```py $ ./redefinition.py Ready. 23:49:33 Processing. ``` 这是输出。 ## Python 函数参数 大多数函数接受参数。 参数是发送到函数的值。 这些函数处理这些值并有选择地返回一些值。 `fahrenheit.py` ```py #!/usr/bin/env python # fahrenheit.py def C2F(c): return c * 9/5 + 32 print(C2F(100)) print(C2F(0)) print(C2F(30)) ``` 在我们的示例中,我们将摄氏温度转换为华氏温度。 `C2F()`函数接受一个参数`c`,即摄氏温度。 ```py $ ./fahrenheit.py 212 32 86 ``` Python 函数中的参数可能具有隐式值。 如果未提供任何值,则使用隐式值。 `fun_implicit.py` ```py #!/usr/bin/env python # fun_implicit.py def power(x, y=2): r = 1 for i in range(y): r = r * x return r print(power(3)) print(power(3, 3)) print(power(5, 5)) ``` 在这里,我们创建了幂函数。 该函数有一个带有隐式值的参数。 我们可以使用一个或两个参数来调用该函数。 ```py $ ./fun_implicit.py 9 27 3125 ``` Python 函数可以使用关键字指定其参数。 这意味着在调用函数时,我们同时指定了关键字和值。 当我们有多个参数并且不使用关键字而使用它们时,传递这些参数的顺序至关重要。 如果我们期望在没有关键字的函数中使用名称,年龄或性别,则无法更改其顺序。 如果使用关键字,我们可以。 `fun_keywords.py` ```py #!/usr/bin/env python # fun_keywords.py def display(name, age, sex): print("Name: ", name) print("Age: ", age) print("Sex: ", sex) display("Lary", 43, "M") display("Joan", 24, "F") ``` 在此示例中,我们指定参数的顺序很重要。 否则,我们将得到错误的结果。 ```py $ ./fun_keywords.py Name: Lary Age: 43 Sex: M Name: Joan Age: 24 Sex: F ``` `fun_keywords2.py` ```py #!/usr/bin/env python # fun_keywords2.py def display(name, age, sex): print("Name: ", name) print("Age: ", age) print("Sex: ", sex) display(age=43, name="Lary", sex="M") display(name="Joan", age=24, sex="F") ``` 现在我们用它们的关键字来调用函数。 可以更改顺序,尽管不建议这样做。 请注意,我们不能在关键字参数之后使用非关键字参数。 这将导致语法错误。 ```py display("Joan", sex="F", age=24) ``` 这是法律构想。 非关键字参数后可以跟关键字参数。 ```py display(age=24, name="Joan", "F") ``` 这将导致语法错误。 非关键字参数不能跟在关键字参数之后。 Python 中的函数可以接受任意数量的参数。 `arbitrary_args.py` ```py #!/usr/bin/env python # arbitrary_args.py def do_sum(*args): """Function returns the sum of all values""" r = 0 for i in args: r += i return r print(do_sum.__doc__) print(do_sum(1, 2, 3)) print(do_sum(1, 2, 3, 4, 5)) ``` 我们使用`*`运算符表示该函数接受任意数量的参数。 `do_sum()`函数返回所有参数的总和。 函数主体中的第一个字符串称为函数文档字符串。 用于记录函数。 该字符串必须用三引号引起来。 ```py $ ./arbitrary_args.py Function returns the sum of all values 6 15 ``` 我们还可以在函数中使用`**`构造。 在这种情况下,该函数将接受字典。 字典有任意长度。 然后,我们通常可以照常解析字典。 `details.py` ```py #!/usr/bin/env python # details.py def display(**details): for i in details: print(f"{i}: {details[i]}") display(name="Larry", age=43, sex="M") ``` 本示例说明了这种情况。 我们可以提供任意数量的键值参数。 该函数将处理所有这些。 ```py $ ./details.py age: 43 name: Larry sex: M ``` ## Python 通过引用传递参数 函数的参数通过引用传递。 一些语言将对象的副本传递给函数。 通过引用传递对象有两个重要结论:a)与传递对象副本相比,此过程更快。 b)在函数中修改的可变对象将永久更改。 `passing_by_reference.py` ```py #!/usr/bin/env python # passing_by_reference.py n = [1, 2, 3, 4, 5] print("Original list:", n) def f(x): x.pop() x.pop() x.insert(0, 0) print("Inside f():", x) f(n) print("After function call:", n) ``` 在我们的示例中,我们将整数列表传递给函数。 该对象在函数体内被修改。 调用该函数(原始对象)后,将修改整数列表。 ```py def f(x): x.pop() x.pop() x.insert(0, 0) print("Inside f():", x) ``` 在函数主体中,我们使用原始对象。 不带对象的副本。 在许多编程语言中,默认情况下,我们将收到对象的副本。 ```py $ ./passing_by_reference.py Original list: [1, 2, 3, 4, 5] Inside f(): [0, 1, 2, 3] After function call: [0, 1, 2, 3] ``` 一旦列表被修改,它就被永久修改了。 ## Python 全局和局部变量 接下来,我们将讨论如何在 Python 函数中使用变量。 `local_variable.py` ```py #!/usr/bin/env python # local_variable.py name = "Jack" def f(): name = "Robert" print("Within function", name) print("Outside function", name) f() ``` 在函数体中定义的变量具有局部范围。 它仅在函数体内有效。 ```py $ ./local_variable.py Outside function Jack Within function Robert ``` 这是示例输出。 `global_variable.py` ```py #!/usr/bin/env python # global_variable.py name = "Jack" def f(): print("Within function", name) print("Outside function", name) f() ``` 默认情况下,我们可以在函数体内获取全局变量的内容。 ```py $ ./global_variable.py Outside function Jack Within function Jack ``` 但是,如果要更改函数中的全局变量,则必须使用`global`关键字。 `global_variable2.py` ```py #!/usr/bin/env python # global_variable2.py name = "Jack" def f(): global name name = "Robert" print("Within function", name) print("Outside function", name) f() print("Outside function", name) ``` 现在,我们将在函数内部更改全局名称变量的内容。 ```py global name name = "Robert" ``` 使用`global`关键字,我们引用在函数主体外部定义的变量。 该变量被赋予一个新值。 ```py $ ./global_variable2.py Outside function Jack Within function Robert Outside function Robert ``` ## Python 匿名函数 可以在 Python 中创建匿名函数。 匿名函数没有名称。 使用`lambda`关键字,几乎无法创建任何匿名函数。 Python 程序员也将匿名函数称为 lambda 函数。 它们是 Python 中合并的函数示例的一部分。 Lambda 函数仅限于单个表达式。 它们可以在可以使用常规函数的任何地方使用。 ZetCode 上有一个 [Python lambda 函数](http://zetcode.com/python/lambda/)教程。 `lambda_fun.py` ```py #!/usr/bin/env python # lambda_fun.py y = 6 z = lambda x: x * y print(z(8)) ``` 这是 lambda 函数的一个小例子。 ```py z = lambda x: x * y ``` `lambda`关键字创建一个匿名函数。 `x`是传递给 lambda 函数的参数。 参数后跟一个冒号。 冒号旁边的代码是在调用 lambda 函数时执行的表达式。 lambda 函数被分配给`z`变量。 ```py print(z(8)) ``` lambda 函数被执行。 数字 8 传递给匿名函数,结果返回 48。 请注意,`z`不是此函数的名称。 它只是分配了匿名函数的变量。 ```py $ ./lambda_fun.py 48 ``` 这是示例的输出。 lambda 函数可以与`map()`或`filter()`函数之类的 Python 语言的其他函数部件完美地结合使用。 `lambda_fun2.py` ```py #!/usr/bin/env python # lambda_fun2.py cs = [-10, 0, 15, 30, 40] ft = map(lambda t: (9.0/5)*t + 32, cs) print(list(ft)) ``` 在示例中,我们列出了摄氏温度。 我们创建一个包含华氏温度的新列表。 ```py ft = map(lambda t: (9.0/5)*t + 32, cs) ``` `map()`函数将匿名函数应用于`cs`列表的每个元素。 它返回计算出的华氏温度的可迭代值。 ```py $ ./lambda_fun2.py [14.0, 32.0, 59.0, 86.0, 104.0] ``` 这是示例输出。 本章是关于 Python 中的函数的。