python函数与变量作用域

理念:一个函数最好只负责处理一项任务,并通过函数间调用来协同完成多项任务

一、创建函数:

创建函数也称为定义函数,通过def关键字实现,语法格式如下:

def functionname([paramerlist]):
  ['''comments''']
  [functionbody]

参数说明:

  1. functionname:函数名字,在调用时候使用
  2. parameterlist:可选参数,用于指定向函数中传递的参数,如果有多个参数,通过逗号分隔,如果没有指定,表示该函数没有参数,调用的时候无需指定
  3. comments:可选参数,表示为函数指定注释,注释内容通常说明函数功能,要传递的参数等等。
  4. functionbody:可选参数,表示函数体,函数被调用后执行的功能代码,如果有返回值,可通过return语句返回。

注意:函数中没有参数的时候,也要保留(),否则会报错,如果定义了注释内容,在调用的时候,会出现注释提示,注意注释和函数体相对于def要有一定的缩进。

二、调用函数:

调用函数也就是使用函数,执行函数中的功能代码,语法格式如下:

functionname([parametervalue])

参数说明:

  1. functionname:表示函数名称,已经创建好的
  2. parametervalue:可选参数,用于指定参数的值,如果有多个参数要传,用逗号分隔,如果没有参数,不写即可。

例如:在test.py中定义函数testtime函数,打印当前星期,然后调用,如图:

注意:调用函数的时候,如果加了小括号表示调用函数,如果不加小括号表示获取函数对象

三、参数传递:

在调用函数时,大多数情况下都是有参数传递的,函数接受到传来的参数进行具体的操作。在使用参数的时候,会用到形式参数和实际参数,区别如下:

形式参数:在定义函数的时候,直接写在函数后面的括号中的参数

实际参数:在调用函数的时候,传递给函数的参数为实际参数。

根据实际参数类型不同,可以分为实际参数的值传递给形式参数和将实际参数的引用传递给形式参数两种情况,其中,当实际参数为不可变对象时,进行值传递,当实际参数为可变对象时,进行的是引用传递,值传递和引用传递的本质区别是,进行值传递后,改变形式参数的值,实际参数的值不变,进行引用传递后,实际参数和形式参数的值都发生了改变

例如:定义一个函数demo,然后为该函数传递一个字符串类型的变量作为参数(表示值传递),并在函数调用前后分别输入该字符串变量,再为demo()函数传递一个列表类型的变量作为参数(表示引用传递),并在函数调用前后输出该列表,如图:

1、位置参数:

也称为必备参数,必须按照正确的顺序传到函数中,调用时的数量和位置必须和定义的时候一样的,如果不一样将会抛出TypeError异常。

例如:定义函数demo()并设置三个形式参数,调用的时候只传递两个参数,报错情况如图:

2、关键字参数:(推荐使用关键字参数的形式)

关键字参数是指在使用形式参数的名字来确定输入的参数值,通过该方式指定实际参数的时候,不再需要与形式参数的位置一致,只要将参数名写正确即可,使得参数的调用和传递更加灵活。

例如:定义函数demo()函数,通过关键字参数的形式调用函数,可以不用按照位置参数那样严格指定位置,如图:

3、为参数设置默认值:

在定义函数的时候,可以设置形式参数的默认值,在调用函数的时候,当没有参数传入时将使用此默认值(每个参数都可以设置默认值)

例如:定义demo()函数,设置三个形式参数,并设置默认值,在调用的时候可以不传参数,如图:

注意:在定义函数的时候,指定默认值的参数必须放在所有参数的最后,否则将产生语法错误,如果调用的时候传入了参数,将会覆盖设置的默认值,通过print(demo.__defaults__)可以打印当前设置的默认值,默认参数必须指定为不可变对象,如果是可变对象,多次调用将产生异常

4、设置可变参数:

在Python中可以定义可变参数,即为不定长参数,传入的实际参数可以是任意多个,定义可变参数时主要有两种形式,一种是*parameter,一种是**parameter

*parameter表示接收任意多个实际参数,并将其放入元祖中,然后遍历元祖即可。

例如:定义一个函数demo(),并让其可以一次性接收多个实际参数,如图:

如果要使用一个已经存在的列表作为函数的可变参数,可在调用函数的时在列表前加*(称为解包),如图:

**parameter:表示接收多个类似关键字参数一样显示赋值的实际参数,并将其放入字典中,在遍历字典将其打印即可。

例如:定义函数demo(),让其可以接收任意多个显示赋值的实际参数,如图:

如果要使用一个已经存在的字典作为可变参数,需要在字典名前面加**,如图:

注:解包适用于元组、列表、字典等其他可迭代对象

四、返回值

在Python中可以在函数体内使用return语句为函数指定返回值,该返回值可以是任意类型,无论return出现在函数的什么位置,只要得到执行,就会直接结束函数的执行。语法格式如下:

return  value

参数说明:

  1. value:用于指定的返回的值,可以返回一个值,也可以返回多个值。
  2. 为函数指定返回值后,在调用函数的时候,可以将其赋值给一个变量(如result),用于保存函数的返回值,如果返回一个值那么result中就保存一个值,如果返回多个值,那么result保存的就是一个元祖.

例如:定义函数demo(),设置三个形式参数,并通过return设置返回值,如图:

因为return返回多个参数,因此打印结果为一个元祖,如图:

如果函数没有显示的指定返回值,默认的返回值为None,如图:

五、变量的作用域

1、局部变量:

局部变量是指在函数内部定义并使用的变量,只在函数内部有效,如果在函数外部使用函数内部定义的变量,将会出现NameError异常

例如:定义函数demo(),在内部定义局部变量,并打印,如图:

2、全局变量:

全局变量是可以作用于函数内外部的变量,全局变量主要有以下两种情况,如下:

第一种:在函数外部定义的变量,在函数内部以及外部进行访问,如图:

第二种:在函数体内定义变量,并使用global关键字修饰后,此变量也变为全局变量,在函数内外都可以访问,并可在函数内部修改,如图:

当局部变量与全局变量重名时,对函数体内的变量赋值后,不影响函数体外的变量

注意:python允许全局变量和局部变量重名,但是实际开发时不建议这么做,这样做容易造成代码混乱

六、函数注解

函数注解也称为类型提示,可用于帮助快速的知道函数的参数类型以及返回类型,函数注解只是文档,给程序员读的,不是程序读的,因此可自定义,函数注解特点:

  • 可选,可根据需要自定义,不写也可以(python3才有注解功能)
  • 可提供函数的一些信息,比如参数类型以及返回值类型,减少阅读代码的时间
  • 函数注解的类型可以自定义来写,没有强制必须为str、int等

1、下面定义一个函数test,接收一个参数,期望参数为字符串,返回也为字符串,如图:

注意:上图中的返回值为单返回值

2、下面修改上述代码,接收两个参数并且有多个返回值(符合pep8编码规范),如图:

注意:除了Tuple还有Dict、List等,可参考官方文档https://docs.python.org/zh-cn/3.6/library/typing.html

3、修改上述代码,将函数注解修改为自己想写的类型,如图:

运行结果没有影响,如图:

七、函数的其余操作

1、函数嵌套在函数中,如图:

2、从函数中返回函数,如图:

打印结果与上面一样

3、将函数作为参数传递给函数,如图:

4、使用 * 接收一个任意参数,如图:

上图中的hello函数可以接受任意数量的参数,任意数量是指0个或者多个,可以是字符串、整数、函数等,*表示任意数量,这里的参数名按照惯例使用args,其实参数名可自定义,不过一般习惯使用args,调用函数传递参数,如图:

从上图看出,其实args的类型为一个元素,可以理解为接收到的参数都转为了元组中的元素

5、 使用**接收任意多个关键字参数,然后调用hello函数,如图:

Python也提供了**来接收多个关键字参数,也可以为0个,按照约定,参数习惯写为kwargs,为关键字参数的缩写,然后调用hello函数,指定关键字参数,打印结果如图:

从上图中可以看出,kwargs参数类型实际为一个字典,因此传递参数的时候也要指定关键字参数

也可以先定义好字典文件,然后使用**来调用,如图:

如上图,在函数hello中的参数params前面加上**前缀,告诉解释器将此字典处理为键以及关联值的集合,运行结果如下:

标签