Python 简明教程

Python - Functions

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

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

python functions

Types of Python Functions

Python 提供以下类型的函数 -

Defining a Python Function

您可以定义自定义函数来提供所需的功能。以下是 Python 中定义函数的简单规则−

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

  2. 任何输入参数或参数都应放置在这些括号内。您还可以在这些括号内定义参数。

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

  4. 每个函数中的代码块以冒号 (:) 开头,并以缩进开头。

  5. 语句 return [expression] 退出函数,可选择将表达式传递回调用方。不带参数的 return 语句与 return None 相同。

Syntax to Define a Python Function

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

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

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

Example to Define a Python Function

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

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

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

Calling a Python Function

定义函数仅给它一个名称,指定要包含在函数中的参数,并构造代码块。一旦函数的基本结构最终确定,您可以使用函数名本身来调用它。如果函数需要任何参数,则应将其放在括号内传递。如果函数不需要任何参数,则应保留括号为空。

Example to Call a Python Function

以下是调用 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

Pass by Reference vs Value

在 C 和 C++ 等编程语言中,有两种向函数传递变量的主要方式,即按值调用和按引用调用(也称为按引用传递和按值传递)。然而,我们在 Python 中向函数传递变量的方式不同于其他方式。

  1. call by value − 在调用时将 variable 传递给函数时,实际参数的值会被复制到表示形式参数的变量中。因此,形式参数中的任何更改都不会反映在实际参数中。这种传递变量的方式称为按值调用。

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

pass by reference vs value

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

Example

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

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

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

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

ID before passing: 1996838294128
ID inside the function: 1996838294128

行为还取决于传递的对象是可变的还是不可变的。Python 数值对象是不可变的。传递数值对象时,如果该函数更改了形式参数的值,它实际上会创建一个新的内存对象,使原始变量保持不变。

Example

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

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)

它将生成以下 output

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

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

Example

在这里,我们传递一个列表,附加一个新项目,然后查看原始列表对象的内容,我们会发现它已更改。

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)

它将生成以下 output

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

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

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

function arguments

Example

让我们修改 greetings 函数,并将 name 设置为参数。作为实际参数传递给函数的字符串将在函数内变成 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

Types of Python Function Arguments

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

Positional or Required Arguments

必需参数是按正确的位置顺序传递给函数的参数。在这里,函数调用中的参数数量应与函数定义完全匹配,否则代码会给出一个语法错误。

Example

在下面的代码中,我们调用函数 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)

Keyword Arguments

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

Example 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

Example 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

Default Arguments

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

Example

以下示例给出了有关默认参数的思路,如果未传递默认年龄,则打印默认年龄:

# 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

Positional-only arguments

那些只能通过它们在函数调用中的位置来指定的参数被称为仅限位置的参数。它们是通过在函数的参数列表中所有仅限位置的参数后面放置“/”来定义的。此功能是随着 Python 3.8 的发布而引入的。

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

Example

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

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

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

它将生成以下 output

Evaluating positional-only arguments:
66

Keyword-only arguments

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

Example

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

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

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

它将生成以下 output

Evaluating keyword-only arguments:
240

Arbitrary or Variable-length Arguments

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

具有非关键词可变参数的函数的语法如下 −

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

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

Example

以下是 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

在下一章中,我们将详细讨论这些函数参数。

Order of Python Function Arguments

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

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

  2. 紧随其后的是常规位置参数,可以或不可以作为关键字参数调用。

  3. 然后可能有一个或多个具有默认值的参数。

  4. 接下来,由带有单个星号前缀的变量表示的任意位置参数,该变量被视为元组。这是下一步。

  5. 如果函数有任何仅限关键字的参数,请在它们的名称之前加上星号。一些仅限关键字的参数可能具有默认值。

  6. 方括号中的最后一个参数是用两个星号 ** 接受任意数量的关键字参数。

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

order of formal arguments

Python Function with Return Value

函数定义中最后一个语句作为 return 关键字表示函数块的结束,并且程序流返回到调用函数。尽管块中最后一个语句之后的缩进减少也意味着返回,但使用显式返回是一种良好的做法。

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

Example

让我们定义 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

The Anonymous Functions

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

  1. Lambda 表达式可以获取任意数量的参数,但仅以表达式的形式返回一个值。它们不能包含命令或多个表达式。

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

  3. Lambda 函数具有自己的本地命名空间,并且除了其参数列表中的那些变量和全局命名空间中的那些变量之外,无法访问其他变量。

  4. 尽管 lambda 看起来是函数的单行版本,但它们并不等同于 C 或 C++ 中的内联语句,其目的是在调用期间绕过函数堆栈分配以提高性能的原因。

Syntax

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

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

Example

以下示例演示函数的 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

Scope of Variables

程序中的所有变量可能无法在该程序的所有位置访问。这取决于变量的声明位置。

scope of a variable 确定可以在其中访问特定标识符的程序部分。Python 中变量有两个基本范围 −

  1. Global variables

  2. Local variables

Global vs. Local variables

在函数主体内部定义的变量具有局部范围,而在函数外部定义的变量具有全局范围。

这意味着仅可以在声明它们的函数内访问局部变量,而可以在整个程序体中通过所有函数访问全局变量。当调用函数时,将在其中引入声明的变量。

Example

以下是局部范围和全局范围的一个简单示例 −

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