Python的函数和自定义模块
一个函数只做一件事情, Python 编码规范建议一个函数的函数体不超过20行代码。如果超过了,说明这个函数做了不止一件事情,就应该把这个函数拆分为更小的函数。这也就暗示了在函数体里面也可以调用其他的函数。
Python函数的注意事项
(1)函数参数的类型决定了它的作用范围
函数外面的容器类作为参数传递到函数中以后,如果函数修改了这个容器里面的值,那么函数外面的容器也会受到影响。
(2)默认参数陷阱,这个问题涉及Python底层的实现
1 | def default_para_trap(para=[], value=0): |
函数格式
def 函数名(参数列表):
函数体
函数参数说明:
不可改变类型变量为实参时,被调函数执行结束后,形参的值可能发生变化,但返回后,形参的值不会带到对应得实参。数据的单向传递。可改变类型变量,形参的变化会带到对应实参。数据的双向传递。
位置参数
默认参数
函数定义时,参数列表可以包含默认参数。默认参数需放置在非默认参数后面,默认参数必须是可变对象。默认参数可以省略,省略时采用默认值。
例:def testDefaultParms(stdno,name1,grade="2017"):
关键字参数
关键字参数之间不存在先后顺序,*后面的参数被视为关键字参数。如果函数定义中已经有了一个可变参数,后面跟着的命名关键字参数不需要一个特殊分隔符*了
例:def testKeyWordPrams(stdno,name1,grade="2017",*,city,zipcode):
可变参数
可变参数允许调用函数时传入的参数是可变的,可以是1个实参,2个实参或者多个实参,也可以是0个实参。可用包裹packing位置参数(简称args参数),或包裹关键字参数(简称*kwargs参数)进行参数传递
包裹位置参数(元组可变参数)。调用函数时传入的相关参数会被args变量收集,根据传入参数的位置合并为一个元组tuple,args是元组类型
例:def testVarParms1(*hobby):
包裹关键字传递(字典可变参数)。调用函数时传入的相关字典数据会被kwargs变量收集,根据传入参数的位置合并成一个字典dict,args是元组类型。
例:def testVarParms2(**birthplace):
解包裹参数
args和*kwargs形式也可以在函数调用的时候使用,称为解包裹unpacking
传递元组时,让元组的每个元素对应一个位置参数
例:1
2
3
4
5
6def testUnpackingParms1(basketball, music, reading):
..........
hobby1=("篮球","音乐","看书")
x=testUNpackingParms1(*hobby1)
传递词典字典时,让词典的每个键值对作为一个关键字参数传递给函数
例:1
2
3
4
5
6def testUnpackingParms2(province, city, zipcode):
..........
birthplace1={"province":"湖北","city":"孝感","zipcode":"432100"}
x = testUnpackingParm2(**birthplace1)
参数次序
位置参数、默认参数、包裹参数、包裹关键字
变量作用域
Python中只有模块(module)、类(class)、以及函数(def、lambda)才会有作用域的概念,
其他的代码块(如if/elif/else try/except for/while
等)语句内定义的变量,外部可以访问
作用域的4中类型
L(local)局部作用域:对定义在函数中的定义的变量,为局部变量。函数内部使用global关键字来声明变量的作用域为全局
E(enclosing)嵌套作用域:E是定义一个函数的上一层的父级函数的局部作用域,主要为实现Python的闭包
G(global)全局作用域:即在模块层次中定义的变量,每一个模块都是一个全局作用域。在模块文件顶层声明的变量具有全局作用域。模块的全局变量就是一个模块对象的属性。(仅限单个模块文件)
B(built-in)内置作用域:系统内固定模块例定义的变量,如预定义在builtin模块内的变量
变量名LEGB法则:
搜索变量名的优先级:局部作用域>嵌套作用域>全局作用域>内置作用域
LEGB法则为:当在函数中使用为确定的变量名时,Python会按照优先级依次搜索4个作用域。
不同作用域变量的修改
non-L变量相对L而言,默认只读而不能修改,否则会在L中引入一个同名的新变量。
注意:在L中对新变量的修改不会影响到non-L。希望在L中修改non-L中的变量时,可以使用global,nonlocal关键字。
局部变量和全局变量
三个典型函数
1、lambda表达式(lambda expression)是一个匿名函数,lambda表达式基于数学中的$λ$演算得名,直接对应于其中的lambda抽象(lambda abstraction)
Python用lambda关键字创造匿名函数
lambda [arg1[,arg2,...,argN]]:expression
参数时可选的,lambda可定义匿名函数,def定义函数必须有名字
lambda是表达式而不是语句,只可以包含一个表达式,该表达式的计算结果可以看作是函数的返回值,
不允许包含复合语句,但在表达式中可以调用其他函数
2、map()函数 是Python内置的高阶函数,使用格式为map(function,Itera)
第一个参数为某个函数,第二个为可迭代对象。作用是接收一个函数function和可迭代对象Itera,通过函数function依次作用在Itera的每个元素上,得到一个新的可迭代的map对象并返回。
3、reduce()函数
标准库functools中的函数reduce()可以将一个接收2个参数的函数以迭代累积的方式从左到右依次作用到一个序列或迭代器对象的所有元素上,并且允许指定一个初始值。
reduce(function, iterable[, initializer])
参数function必须有两个参数,initializer是可选的。
通过取出序列的头两个元素,将它们传入二元函数获得一个单一的值来实现。然后用这个值和下一个元素来获得又一个值,继续直到整个序列的内容都遍历完毕。
函数递归:直接递归和间接递归
常用函数
使用内置函数dir()可以查看所有内置函数和内置对象:
dir(_builtins_)
使用help
(函数名)可以查看某个函数的用法。
常见内置函数
1 | abs() delattr() hash() memoryview() set() all() |
进制转换函数
1 | bin(n):将十进制数n转换为二进制数 |
数学函数
math模块
1 | abs(x):返回数字的绝对值 |
模块
模块是一组Python代码的集合,主要定义了一些公有函数和变量。使用者通过import命令引入模块,
使用其中的函数和变量。在Python中,一个.py文件就是一个模块(Module)。
模块的分类
1、自定义模块:用户自己编写的实现包含一些函数变量的.py文件
2、内置模块:Python自身提供的模块,如:sys、os、random等模块
3、开源模块:第三方提供的模块
模块的好处
1、提高代码的可维护性和开发效率
2、使用模块还可以避免函数名和变量名冲突
模块文件的管理
为避免模块名冲突,Python引入包(Package)来管理模块文件。包是一个有层次的文件目录结构,
它定义了由若干个模块、子包组成的Python应用程序执行环境。包是一个包含_init_.py
文件的目录,
该目录下一定得有这个_init_.py
文件和其他模块或子包
因此只要将模块放在不同的包,就可避免模块名冲突。
注意:包目录下必须有_init_.py
文件,否则就被Python当普通目录。
模块的引用
1、import module_name
module_name为模块名
2、from module_name
from module_name import function_name
3、应用多个模板,模板之间用逗号
注意:在引入模板前要求配置好模块所在的目录。可以将该目录加入到PATHPYTHON环境变量,也
可以通过下列方式配置
自定义模块
将一系列常用功能放在一个.py文件中。自定义模块应用一般包括以下几个步骤:
1、编辑并调试好模块文件,如mymath.py
2、规划模块文件存放的目录,如d:\myLearn\Python\lib
3、配置模块文件目录,即将模块文件目录加到PATHPYTHON环境变量或在某应用该模块的文件中引
用该模块前加入如下语句:
import sys #引用系统内置模块sys
sys.append(“d:\myLearn\Python\lib”)
4、引用模块
import mymath
#引用自定义模块mymath