Python - 函数



Python 函数是一块组织好的、可重用的代码块,用于执行单个相关的操作。函数为您的应用程序提供了更好的模块化和高度的代码重用。

构建处理逻辑的自顶向下方法涉及定义独立的可重用函数块。可以通过传递所需数据(称为参数实参)从任何其他函数调用 Python 函数。被调用的函数将其结果返回到调用环境。

python functions

Python 函数类型

Python 提供以下类型的函数:

序号 类型 & 描述
1

内置函数

Python 的标准库包含许多内置函数。一些 Python 的内置函数有 print()、int()、len()、sum() 等。这些函数始终可用,因为它们在您启动 Python 解释器时就会加载到计算机的内存中。

2

内置模块中定义的函数

标准库还捆绑了许多模块。每个模块都定义了一组函数。这些函数并非随时可用。您需要从其各自的模块导入它们到内存中。

3

用户定义函数

除了内置函数和内置模块中的函数外,您还可以创建自己的函数。这些函数称为用户定义函数。

定义 Python 函数

您可以定义自定义函数以提供所需的功能。以下是定义 Python 函数的一些简单规则:

  • 函数块以关键字 def 开头,后跟函数名称和括号 ()。

  • 任何输入参数或实参都应放在这些括号内。您也可以在这些括号内定义参数。

  • 函数的第一条语句可以是可选语句;函数的文档字符串或文档字符串。

  • 每个函数内的代码块以冒号 (:) 开头并缩进。

  • 语句 return [expression] 退出函数,可以选择将表达式传回给调用方。没有参数的 return 语句与 return None 相同。

定义 Python 函数的语法

def function_name( parameters ):
   "function_docstring"
   function_suite
   return [expression]

默认情况下,参数具有位置行为,您需要按其定义的顺序告知它们。

定义函数后,您可以通过从另一个函数或直接从 Python 提示符调用它来执行它。

定义 Python 函数的示例

以下示例演示如何定义函数 greetings()。括号为空,因此没有任何参数。这里,第一行是文档字符串,函数块以 return 语句结束。

def greetings():
   "This is docstring of greetings function"
   print ("Hello World")
   return

调用此函数时,将打印 Hello world 消息。

调用 Python 函数

定义函数只会赋予它一个名称,指定要包含在函数中的参数并构造代码块。一旦函数的基本结构确定,您就可以使用函数名称本身来调用它。如果函数需要任何参数,则应将它们放在括号内。如果函数不需要任何参数,则应将括号留空。

调用 Python 函数的示例

下面是调用 printme() 函数的示例:

# Function definition is here
def printme( str ):
   "This prints a passed string into this function"
   print (str)
   return;

# Now you can call the function
printme("I'm first call to user defined function!")
printme("Again second call to the same function")

当执行上述代码时,会产生以下输出:

I'm first call to user defined function!
Again second call to the same function

传值与传引用

在像 C 和 C++ 这样的编程语言中,将变量传递给函数主要有两种方式,分别是 传值调用传引用调用(也称为按引用传递和按值传递)。但是,我们在 Python 中将变量传递给函数的方式与其他语言不同。

  • 传值调用 - 当调用函数时将 变量 传递给函数时,实际参数的值会被复制到表示形式参数的变量中。因此,形式参数的任何更改都不会反映到实际参数中。这种传递变量的方式称为传值调用。

  • 传引用调用 - 在这种传递变量的方式中,会传递对内存中对象的引用。形式参数和实际参数(调用代码中的变量)都引用同一个对象。因此,形式参数的任何更改都会反映到实际参数中。

Pass By Reference Vs Value

Python 使用传引用机制。由于 Python 中的变量是内存中对象的标签或引用,因此用作实际参数和形式参数的变量实际上都引用内存中的同一个对象。我们可以通过检查传递变量的 id() 在传递前后是否相同来验证这一事实。

示例

在下面的示例中,我们正在检查变量的 id()。

def testfunction(arg):
   print ("ID inside the function:", id(arg))

var = "Hello"
print ("ID before passing:", id(var))
testfunction(var)

如果执行上述代码,则会显示传递之前和函数内部的 id()。

ID before passing: 1996838294128
ID inside the function: 1996838294128

这种行为还取决于传递的对象是可变的还是不可变的。Python 数值对象是不可变的。当传递数值对象,然后函数更改形式参数的值时,它实际上会在内存中创建一个新对象,而原始变量保持不变。

示例

以下示例显示了不可变对象在传递给函数时的行为。

def testfunction(arg):
   print ("ID inside the function:", id(arg))
   arg = arg + 1
   print ("new object after increment", arg, id(arg))

var=10
print ("ID before passing:", id(var))
testfunction(var)
print ("value after function call", var)

它将产生以下输出

ID before passing: 140719550297160
ID inside the function: 140719550297160
new object after increment 11 140719550297192
value after function call 10

现在让我们将可变对象(例如列表或字典)传递给函数。它也是按引用传递的,因为列表在传递之前和之后的 id() 是相同的。但是,如果我们在函数内部修改列表,则其全局表示也会反映出更改。

示例

这里我们传递一个列表,追加一个新项目,并查看原始列表对象的内容,我们会发现它已经改变了。

def testfunction(arg):
   print ("Inside function:",arg)
   print ("ID inside the function:", id(arg))
   arg=arg.append(100)
   
var=[10, 20, 30, 40]
print ("ID before passing:", id(var))
testfunction(var)
print ("list after function call", var)

它将产生以下输出

ID before passing: 2716006372544
Inside function: [10, 20, 30, 40]
ID inside the function: 2716006372544
list after function call [10, 20, 30, 40, 100]

Python 函数参数

函数参数是在调用函数时传递给函数的值或变量。函数的行为通常取决于传递给它的参数。

在定义函数时,您会在括号内指定一个变量列表(称为形式参数)。这些参数充当将传递给函数的数据的占位符,当函数被调用时。当函数被调用时,必须为每个形式参数提供值。这些称为实际参数。

function arguments

示例

让我们修改 greetings 函数,并将其名称作为参数。作为实际参数传递给函数的字符串在函数内部成为 name 变量。

def greetings(name):
   "This is docstring of greetings function"
   print ("Hello {}".format(name))
   return
   
greetings("Samay")
greetings("Pratima")
greetings("Steven")

此代码将产生以下输出:

Hello Samay
Hello Pratima
Hello Steven

Python 函数参数的类型

根据在定义 Python 函数时参数的声明方式,它们被分为以下几类:

位置参数或必选参数

必选参数是按正确的顺序传递给函数的参数。这里,函数调用中的参数数量必须与函数定义完全匹配,否则代码会报错。

示例

在下面的代码中,我们调用函数 printme() 没有任何参数,这会导致错误。

# Function definition is here
def printme( str ):
   "This prints a passed string into this function"
   print (str)
   return;

# Now you can call printme function
printme()

当执行上述代码时,会产生以下结果:

Traceback (most recent call last):
   File "test.py", line 11, in <module>
      printme();
TypeError: printme() takes exactly 1 argument (0 given)

关键字参数

关键字参数与函数调用相关。当您在函数调用中使用关键字参数时,调用者通过参数名称识别参数。这允许您跳过参数或将其放置在错误的顺序,因为 Python 解释器能够使用提供的关键字将值与参数匹配。

示例 1

以下示例演示如何在 Python 中使用关键字参数。

# Function definition is here
def printme( str ):
   "This prints a passed string into this function"
   print (str)
   return;

# Now you can call printme function
printme( str = "My string")

当执行上述代码时,会产生以下结果:

My string

示例 2

以下示例提供了更清晰的图片。请注意,参数的顺序无关紧要。

# Function definition is here
def printinfo( name, age ):
   "This prints a passed info into this function"
   print ("Name: ", name)
   print ("Age ", age)
   return;

# Now you can call printinfo function
printinfo( age=50, name="miki" )

当执行上述代码时,会产生以下结果:

Name:  miki
Age  50

默认参数

默认参数是指如果在函数调用中未为该参数提供值,则假设为默认值的参数。

示例

以下示例说明了默认参数,如果未传递,则打印默认年龄:

# Function definition is here
def printinfo( name, age = 35 ):
   "This prints a passed info into this function"
   print ("Name: ", name)
   print ("Age ", age)
   return;

# Now you can call printinfo function
printinfo( age=50, name="miki" )
printinfo( name="miki" )

当执行上述代码时,会产生以下结果:

Name:  miki
Age  50
Name:  miki
Age  35

仅限位置参数

只能通过其在函数调用中的位置指定的参数称为 仅限位置参数。它们通过在函数的参数列表中所有仅限位置参数之后放置一个 "/" 来定义。此功能是在 Python 3.8 版本中引入的。

使用这种类型参数的好处是它确保函数以正确的顺序使用正确的参数调用。仅限位置参数应该作为位置参数传递给函数,而不是关键字参数。

示例

在以下示例中,我们定义了两个仅限位置的参数,即“x”和“y”。此方法应该按参数声明的顺序使用位置参数调用,否则,我们将收到错误。

def posFun(x, y, /, z):
    print(x + y + z)

print("Evaluating positional-only arguments: ")
posFun(33, 22, z=11) 

它将产生以下输出

Evaluating positional-only arguments: 
66

仅限关键字参数

在调用函数时必须通过其名称指定的参数称为 仅限关键字参数。它们通过在函数的参数列表中任何仅限关键字参数之前放置一个星号(“*”)来定义。这种类型的参数只能作为关键字参数传递给函数,而不是位置参数。

示例

在下面的代码中,我们定义了一个具有三个仅限关键字参数的函数。要调用此方法,我们需要传递关键字参数,否则,我们将遇到错误。

def posFun(*, num1, num2, num3):
    print(num1 * num2 * num3)

print("Evaluating keyword-only arguments: ")
posFun(num1=6, num2=8, num3=5) 

它将产生以下输出

Evaluating keyword-only arguments: 
240

任意参数或可变长度参数

您可能需要为函数处理比定义函数时指定的更多参数。这些参数称为 可变长度参数,与必选参数和默认参数不同,它们在函数定义中没有命名。

带有非关键字可变参数的函数的语法如下:

def functionname([formal_args,] *var_args_tuple ):
   "function_docstring"
   function_suite
   return [expression]

一个星号 (*) 放在保存所有非关键字可变参数值的变量名称之前。如果在函数调用期间未指定其他参数,则此元组保持为空。

示例

以下是 Python 可变长度参数的一个简单示例。

# Function definition is here
def printinfo( arg1, *vartuple ):
   "This prints a variable passed arguments"
   print ("Output is: ")
   print (arg1)
   for var in vartuple:
      print (var)
   return;

# Now you can call printinfo function
printinfo( 10 )
printinfo( 70, 60, 50 )

当执行上述代码时,会产生以下结果:

Output is:
10
Output is:
70
60
50

在接下来的几章中,我们将详细讨论这些函数参数。

Python 函数参数的顺序

一个函数可以包含上面定义的任何类型的参数。但是,参数必须按以下顺序声明:

  • 参数列表以仅限位置的参数开头,后跟斜杠 (/) 符号。

  • 后面跟着常规位置参数,这些参数可能也可能不被调用为关键字参数。

  • 然后可能有一个或多个具有默认值的 args。

  • 接下来,由以单个星号为前缀的变量表示的任意位置参数,该变量被视为元组。它是下一个。

  • 如果函数有任何仅限关键字的参数,请在其名称开始之前放置一个星号。一些仅限关键字的参数可能具有默认值。

  • 括号中的最后一个是带有两个星号 ** 的参数,用于接受任意数量的关键字参数。

下图显示了形式参数的顺序:

Order Of Formal Arguments

带有返回值的 Python 函数

在函数定义中,return 关键字作为最后一个语句表示函数块的结束,程序流程返回到调用函数。虽然在块中的最后一个语句之后缩进减少也意味着返回,但使用显式返回是一个好习惯。

除了流程控制之外,函数还可以将表达式的值返回给调用函数。返回表达式的值可以存储在一个变量中以供进一步处理。

示例

让我们定义 add() 函数。它将传递给它的两个值相加并返回加法结果。返回值存储在一个名为 result 的变量中。

def add(x,y):
   z=x+y
   return z
a=10
b=20
result = add(a,b)
print ("a = {} b = {} a+b = {}".format(a, b, result))

它将产生以下输出:

a = 10 b = 20 a+b = 30

匿名函数

当函数不是以标准方式使用 def 关键字声明时,这些函数称为 匿名 函数。相反,它们是使用 lambda 关键字 定义的。

  • Lambda 表达式可以接受任意数量的参数,但只返回一个表达式的值。它们不能包含命令或多个表达式。

  • 匿名函数不能直接调用 print,因为 lambda 需要一个表达式

  • Lambda 函数有自己的局部命名空间,不能访问其参数列表和全局命名空间之外的变量。

  • 虽然看起来 lambda 是函数的一行版本,但它们并不等同于 C 或 C++ 中的内联语句,内联语句的目的是通过在调用期间传递函数堆栈分配来提高性能。

语法

lambda 函数的语法只包含一个语句,如下所示:

lambda [arg1 [,arg2,.....argn]]:expression

示例

以下示例说明了 lambda 函数的工作原理:

# Function definition is here
sum = lambda arg1, arg2: arg1 + arg2;

# Now you can call sum as a function
print ("Value of total : ", sum( 10, 20 ))
print ("Value of total : ", sum( 20, 20 ))

当执行上述代码时,会产生以下结果:

Value of total :  30
Value of total :  40

变量的作用域

程序中的所有变量可能无法在程序的所有位置访问。这取决于您在何处声明了一个变量。

变量的作用域确定可以在程序的哪个部分访问特定标识符。Python 中变量有两个基本作用域:

  • 全局变量
  • 局部变量

全局变量与局部变量

在函数体内部定义的变量具有局部作用域,在外部定义的变量具有全局作用域。

这意味着局部变量只能在声明它们的函数内部访问,而全局变量可以在整个程序体中被所有函数访问。当您调用一个函数时,它内部声明的变量会被带入作用域。

示例

以下是一个局部和全局作用域的简单示例:

total = 0; # This is global variable.
# Function definition is here
def sum( arg1, arg2 ):
   # Add both the parameters and return them."
   total = arg1 + arg2; # Here total is local variable.
   print ("Inside the function local total : ", total)
   return total;

# Now you can call sum function
sum( 10, 20 );
print ("Outside the function global total : ", total) 

当执行上述代码时,会产生以下结果:

Inside the function local total :  30
Outside the function global total :  0
广告