Python从入门到实践:函数基础知识(函数定义、形参与实参)

目录

一、函数引入

二、函数的定义

三、函数的调用

 四、形参与实参

 五、形参与实参的使用

5.1位置参数

5.2关键字参数

5.3默认参数

5.4可变长参数

5.5组合使用

六、名称空间

6.1内建名称空间

6.2全局名称空间

6.3局部名称空间

七、作用域


一、函数引入

很多时候,我们需要重复的应用一个功能,比如,我们在设计网页的时候,我们会重复用到“登录”功能,我们就可以把它写成一个函数,把它封装起来,这样方便我们随时调用,这在一定程度上可以增强程序的可读性,让程度看起来更清晰。

二、函数的定义

函数的使用必须遵循先定义,后调用的原则函数的定义就相当于事先将函数体代码保存起来,然后将内存地址赋值给函数名,函数名就是对这段代码的引用,这和变量的定义是相似的。没有事先定义函数而直接调用,就相当于在引用一个不存在的变量名。

def 函数名(参数1,参数2,...):
    """文档描述"""
    函数体
    return 值

 上面的定义有几点需要说明:

1. def:定义函数的关键字;

2.函数名:函数名指向函数内存地址,是对函数体代码的引用。函数的命名应该反映出函数的功能;

3.括号:括号内定义参数,参数是可有可无的,且无需指定参数的类型;

4.冒号:括号后要加冒号,然后在下一行开始缩进编写函数体的代码;

5.""文档描述""":描述函数功能,参数介绍等信息的文档,非必要,但是建议加上,从而增强函数的可读性;

6.函数体:由语句和表达式组成;

7. return值:定义函数的返回值, return是可有可无的。

#有参函数
def my_min(x,y):
    res=x if x < y else y
    return res

#无参函数
def interactive():
    user=input('user>>: ').strip()
    pwd=input('password>>: ').strip()
    return (user,pwd)

我们使用有参函数还是无参函数主要看我们的需求

函数体为pass代表什么都不做,称之为空函数。定义空函数通常是有用的,因为在程序设计的开始,往往是先想好程序都需要完成什么功能,然后把所有功能都列举出来用pass充当函数体”占位符”,这将使得程序的体系结构立见,清晰且可读性强。

三、函数的调用

函数的使用分为定义阶段与调用阶段,定义函数时只检测语法,不执行函数体代码,函数名加括号即函数调用,只有调用函数时才会执行函数体代码

#定义阶段
def foo():
    print('in the foo')
    bar()
 
def bar():
    print('in the bar')
 
#调用阶段
foo()

若需要将函数体代码执行的结果返回给调用者,则需要用到return, return后无值或直接省略return,则默认返回None, return的返回值无类型限制,且可以将多个返回值放到一个元组内

return是一个函数结束的标志,函数内可以有多个return,但只执行一次函数就结束了,并把returm后定义的值作为本次调用的结果返回。

>>> def test(x,y,z):
...     return x,y,z #等同于return (x,y,z)
... 
>>> res=test(1,2,3)
>>> print(res)
(1, 2, 3)

 四、形参与实参

函数的参数分为形式参数和实际参数,简称形参和实参:形参即在定义函数时,括号内声明的参数。形参本质就是一个变量名,用来接收外部传来的值。

 五、形参与实参的使用

5.1位置参数

1.在定义函数时,按照从左到右的顺序依次定义形参,称为位置形参,凡是按照这种形式定义的形参都必须被传值

2.在调用函数时,按照从左到右的顺序依次定义实参,称为位置实参,凡是按照这种形式定义的实参会按照从左到右的顺序与形参——对应

5.2关键字参数

在调用函数时,实参可以是key=value的形式,称为关键字参数,凡是按照这种形式定义的实参,可以完全不按照从左到右的顺序定义,但仍能为指定的形参赋值,需要注意在调用函数时,实参也可以是按位置或按关键字的混合使用,但必须保证关键字参数在位置参数后面,且不可以对一个形参重复赋值

5.3默认参数

在定义函数时,就已经为形参赋值,这类形参称之为默认参数,当函数有多个参数时,需要将值经常改变的参数定义成位置参数,而将值改变较少的参数定义成默认参数。例如编写一个注册学生信息的函数,如果大多数学生的性别都为男,那完全可以将形参sex定义成默认参数。

定义时就已经为参数sex赋值,意味着调用时可以不对sex赋值,这降低了函数调用的复杂度

需要注意:1.默认参数必须在位置参数之后2.默认参数的值仅在函数定义阶段被赋值一次

>>> x=1
>>> def foo(arg=x):
...     print(arg)
... 
>>> x=5 #定义阶段arg已被赋值为1,此处的修改与默认参数arg无任何关系
>>> foo()
1

默认参数的值通常应设为不可变类型 

>>> def foo(n,arg=[]):
...     arg.append(n)
...     return arg
... 
>>> foo(1)
[1]
>>> foo(2)
[1, 2]
>>> foo(3)
[1, 2, 3]

5.4可变长参数

主要是*和**的使用,参考我的上篇博客,做了详细的说明:*和**的使用

5.5组合使用

综上所述所有参数可任意组合使用,但定义顺序必须是:位置参数、默认参数、*args、**kwargs。可变参数*args与关键字参数*kwargs通常是组合在一起使用的,如果一个函数的形参为args与**kwargs,那么代表该函数可以接收任何形式、任意长度的参数

>>> def wrapper(*args,**kwargs):
...     pass
...

六、名称空间

名称空间即存放名字与对象映射/绑定关系的地方。对于x=3, Python会申请内存空间存放对象3,然后将名字x与3的绑定关系存放于名称空间中,delx表示清除该绑定关系。

6.1内建名称空间

伴随python解释器的启动/关闭而产生/回收,因而是第一个被加载的名称空间,用来存放一些内置的名字,比如内建函数名

6.2全局名称空间

伴随python文件的开始执行/执行完毕而产生/回收,是第二个被加载的名称空间,文件执行过程中产生的名字都会存放于该名称空间中,如下名字

6.3局部名称空间

伴随函数的调用/结束而临时产生/回收,函数的形参、函数内定义的名字都会被存放于该名称空间中

名称空间的加载顺序是:内置名称空间->全局名称空间->局部名称空间,而查找一个名字,必须从三个名称空间之一找到,查找顺序为:局部名称空间->局名称空间->内置名称空间。

七、作用域

按照名字作用范围的不同可以将三个名称空间划分为两个区域:

1.全局作用域:位于全局名称空间、内建名称空间中的名字属于全局范围,该范围内的名字全局存活(除非被删除,否则在整个文件执行过程中存活)、全局有效(在任意位置都可以使用) ;

2.局部作用域:位于局部名称空间中的名字属于局部范围。该范围内的名字临时存活(即在函数调用时临时生成,函数调用结束后就释放)、局部有效(只能在函数内使用)

作用域的优先级

在局部作用域查找名字时,起始位置是局部作用域,所以先查找局部名称空间,没有找到,再去全局作用域查找:先查找全局名称空间,没有找到,再查找内置名称空间,最后都没有找到就会抛出异常

x=100 #全局作用域的名字x
def foo():
    x=300 #局部作用域的名字x
    print(x) #在局部找x
foo()#结果为300
x=100
def foo():
    x=300 #在函数调用时产生局部作用域的名字x
foo()
print(x) #在全局找x,结果为100

提示:可以调用内建函数locals()和globals0来分别查看局部作用域和全局作用域的名字,查看的结果都是字典格式。在全局作用域查看到的locals0的结果等于globals()

当实参的值为可变类型时,函数体内对该值的修改将直接反应到原值

num_list=[1,2,3]
def foo(nums):
    nums.append(5)
 
foo(num_list)
print(num_list)
#结果为
[1, 2, 3, 5]

 对于嵌套多层的函数,使用nonlocal关键字可以将名字声明为来自外部嵌套函数定义的作用域(非全局)

def  f1():
    x=2
    def f2():
        nonlocal x
        x=3
    f2() #调用f2(),修改f1作用域中名字x的值
    print(x) #在f1作用域查看x
 
f1()
 
#结果
3

猜你喜欢

转载自blog.csdn.net/weixin_43507744/article/details/126580494