本章主要讲述了函数的相关概念,函数是构成程序的基本单元,所以本章是python3的一个重点。
一、函数的概念
1、函数的定义
函数是可以重复执行的语句块, 可以重复调用
2、函数的作用
1、用于封装语句,提高代码的重用性
2、用于定义(创建)用户级别的函数
3、函数语法
def 函数名(形参列表):
语句块
4、说明
1. 函数名是语句块的名称
2. 函数名的命脉规则与变量名相同(标识符)
3. 函数的名字是一个变量,是绑定代码块的名称
4. 函数有自己名字空间,在函数外部不可以访问函数内部的变量,在函数内部可以访问函数外部的变量,要让函数处理外部数据需要用参数给函数传入一些数据
5. 参数列表可以为空
6. 语句部分不能为空,如果为空需要用pass语句填充
5、函数调用
函数名(实际调用传递参数)
说明:
1、函数调用是一个表达式
2、如果没有return 语句,函数执行完毕后返回None对象
3、如果函数需要返回其它的对象需要用到return语句
6、return 语句
语法
return [表达式]
注: [] 代表内容可省略
作用: 结束当前的函数的执行,返回到调用该函数的地方,同时返回表达式的引用关系
说明:
1、return语句后跟的表达式可以省略,省略后相当于return None
2、如果函数内没有return语句,则函数执行完最后一条语句后返回None(相当于在最后加了一条 return None语句)
3、函数的return可以返回一个值或一组值
7、示例
定义两个函数:
sum3(a,b,c) 用于返回三个数的和
pow3(x) 用于返回x的三次方
用以上两个函数计算:
1.计算1的立方+2的立方+3的立方的和
2.计算1+2+3的和的立方
def sum3(a,b,c):
return a + b + c
def pow3(x):
return x**3
print(sum3(pow3(1),pow3(2),pow3(3)))
print(pow3(sum3(1,2,3)))
二、函数的参数传递
四种传递方式:
位置传参
* 序列传参(属于位置传参)
关键字传参
** 字典关键字传参(也可以说是关键字传参的一种)
1、位置传参
实际传递参数(以下简称"实参")与形式参数(形参)的对应关系按位置来依次对应
示例:
def sum3(a,b,c):
return a + b + c
x = sum3(1,2,3)
说明:
1、实参和形参通过位置进行对应和传递
2、实参和形参的个数必须完全相同
2、序列传参
序列传参是指在函数调用过程中用"*"将序列拆解后按位置进行传递的传参方式
示例:
L = [11,12,13] # 列表序列
sum(*L) # 等同于 sum3(L【0】,L【1】,L【2】)
T = (1.1, 2.2, 3.3) # 元组序列
sum(*T)
S = “ABC” # 字符串序列
sum(*S)
3、关键字传参
关键字传参是指传参时,按着形参的名称给形参赋值
实参和形参按名称进行匹配
示例:
sum3(a = 100 , b = 200, c = 300)
sum3(b = 200 , c = 300, a = 100)
4、字典关键字传参
是指实参为字典,将字典用 "**" 拆解后进行关键传参的传参方式
实参和形参通过字典进行传递和匹配,字典的值传递给键对应的形参
示例:
d = {“c”:3,“a”:1,“b”:2}
sum3(**d)
说明:
1、字典传参的键名和形参名必须一致
2、键名必须为字符串
3、键名要在形参中存在
5、函数的综合传参
函数的传参方式在能确定形参能唯一匹配到应当实参的情况下可以任意组合
要求:
位置传参在前,关键字传参在后
示例:
def myfun(a, b, c):
print('a =', a)
print('b =', b)
print('c =', c)
myfun(1, c=3, b=2) # 正确
#myfun(b=2, a=1, 3) # 错的
myfun(100, *[200, 300]) # 正确
myfun(*"AB", 300) # 正确
myfun(*[100], c=300, b=200) # 正确
myfun(*"AB", **{"c":300}) # 正确
三、函数的缺省参数
1、语法格式
def 函数名(形参1 = 默认参数1,形参2 = 默认参数2,.....)
语句
2、缺省参数说明
1、缺省参数(缺省值)必须自右至左依次存在,如果一个参数有缺省值,则其右侧的所有参数都必须有缺省值
2、 缺省参数可以有0个或多个,甚至全部都是缺参参数
3、示例
def info (name, age = 18, addr = “不详”)
print(“姓名”,name ,“年龄”,age, “地址”,addr)
#调用时
info(“xxx”,23,“地球”)
info(“小明”,14)
info(“文天祥”)
四、函数形参的定义方式
1、位置形参
语法:def 函数名(形参名1, 形参名2, ...):
语句块
2、星号元组形参
语法:def 函数名(*元组形参名):
语句块
作用:收集多余的位置传参
示例:
def star_args(*args):
print(“实参个数是”,len(args))
print(args)
star_args(1 , 2)
star_args(“100” , 200 , “three” , 4.4)
3、命名关键字形参
语法:def 函数名(*, 命名关键字形参):
语句块
或
def 函数名(*args, 命名关键字形参):
语句块
作用:强制所有的传参都必须用关键字传参
示例:
def fa(a, b, *, c, d):
'''强制c,d必须用关键字传参 '''
print(a, b, c, d)
fa(1, 2, d=400, c=300) # 对的
def fb(a, b, *args, c, d):
print(a, b, args, c, d)
fb(1, 2, 3, 4, d=400, c=200)
fb(1,2,3,4,5, **{'d':400, 'c':300})
# fb(1,2,3,4, c=400, d=300, e=500) # 出错,e是多余的
# fa(1, 2, 3, 4) # 错的
4、双星号字典形参
语法:def 函数名(**字典形参名):
语句
作用:收集多余的关键字传参
示例:
def double_f(**kwargs):
print("双星号字典传参的个数:", len(kwargs))
for k,v in kwargs.items():
print(k,"-->",v)
double_f(name="苏东坡", age=20)
double_f(a=10, b="xxx", c=True,d = [1,2,3,4])
def fb(*args, a, **kwargs):
print(args, a, kwargs)
fb(1,2,3, b=20, c=30, a=10)
5、函数的参数列表顺序
位置形数,缺省参数,星号元组形参,双星号字典形参,命名关键字参数可以混合使用函数参数自左至右的顺序:
位置形数,星号元组形参,命名关键字参数,双星号字典形参
示例:
def fn(a, b, *args, c, **kwargs):
pass
fn(100, 200, 300, 400, c=”C”, d=”d”, e =”e”)
五、函数的实参
可变/不可变类型 的实参的参数作为形参传递给函数的区别
可变类型:
列表list,集合set,字典dict
不可变类型:
frozenset,tuple,str,float,int ....
可变类型的数据作为形参参数传入时,函数内部可以改变原数据,多用来返回更多数据结果
不可变的类型的数据作为函数形参参数传入时,函数内部不会改变变量的原始数据值,是安全的
通俗来讲,局部变量作为可变类型的形参传入到函数中,函数中对形参的修改是会影响到外面的内容
def fa(LL):
LL["name"] = "ccc"
def fb(M):
M = 2
def main():
# 往fa函数传入一个可变实参
L = {}
fa(L)
for k in L:
print(k) # name L被改变
# 往fb函数传入一个不可变实参
m = 0
fb(m)
print(m) # 0 m的值没有被改变
main()
六、函数综合
1、函数变量
函数名是变量,它是创建函数时绑定一个函数
例:
def fn():
print(“hello world”)
f1 = fn
f1() #等同于调用函数fn()
注释:函数fn作为一个变量绑定到f1;当调用f1()函数时,等同于调用fn()函数
2、函数嵌套
函数嵌套是指一个函数里用语句来创建其他函数的情况
def fun_outer(): # 外部函数
print("外部函数被调用...")
def fun_inner():
print("fun_inner被调用")
fun_inner() # 调用一次
fun_inner() # 调用二次...
print("外部函数调用结束")
fun_outer() # 调用函数
3、函数作为函数的返回值
例:
def getfn():
def print_hello():
print(“hello”)
return print_hello # 返回的时内部定义的函数
fn = getfn()
fn() # 调用的时print_hello()函数
注:
return print_hello # 返回的是函数(函数不执行)
return print_hello() # 返回的是函数执行的结果(执行整个函数)
4、函数作为参数的参数传递
示例:
def tab(x, y):
return “|” + x.center(13) + y.center(13) + “|”
def string(x, y):
return “姓名” + x + “年龄” + y
def myprint(fx , x ,y):
print(fx(x, y))
myprint(tab,“tarena”,“15”)
myprint(tab,“abc”,“18”)
myprint(string,“tarena”,“15”)
myprint(string,“abc”,“18”)
七、全局变量和局部变量
1、全局变量
定义在函数外部,模块内部的变量称为全局变量
所有的函数都可以直接访问"全局"变量,但函数内部不能直接通过赋值语句来改变全局变量
2、局部变量
定义在函数内部的变量称为局部变量(函数的形参也是局部变量)局部变量只能在函数内部使用
局部变量在函数调用时才能够被创建,在函数调用结束之后会自动销毁
说明:
在函数内首次对变量赋值是创建局部变量,再次为变量赋值是修改局部变量的绑定关系
在函数内部的赋值语句不会对全局变量造成影响
局部变量只能在其被声明的函数内部访问,而全局变量可以在整个模块同访问
八、函数的属性
__doc__ 属性用于记录文档字符串
函数内第一次未赋值给任何变量的字符串是此函数的文档字符串
语法
def 函数名(形参列表):
'''函数的文档字符串'''
函数语句块
示例
def hello():
'''此函数用来打招呼...
这是函数的文档字符串
'''
pass
>>> help(hello)
说明
a、文档字符串通常用来说明本函数的功能和使用方法
b、在交互模式下,输入:help(函数名) 可以查看函数的文档字符串
2、函数的 __name__ 属性
__name__ 用于记录函数的名称
示例
def abc():
pass
a = abc
print(a.__name__) # abc
def xxx(fn):
if fn.__name__ == “abc”
pass
elif fn.__name__ == “max”
pass
九、补充
1、函数式编程
函数式编程是指用一系列函数解决问题
函数是一等公民(Guido)
1、函数本身可以赋值给变量,赋值后变量绑定函数
2、允许将函数本身作为参数传入另一个函数
3、允许函数返回一个函数
好处:用每一个函数完成细小的功能,一系列函数在任意组合可以完成大问题
2、函数的可重入性
当一个函数在运行时不读取和改变除局部作用域以外的变量时,此函数为可重入函数
可重入函数在每次调用时,如果参数一定,则结果必然一定
3、示例
可重入函数:
def add1(x, y):
return x + y
不可重入函数示例
y = 200
def add2(x):
return x + y
print(add2(10)) # 210
y = 300
print(add2(10)) # 310
十、练习集
1、第一题
prime(质数/素数)
1、写一个函数isprime(x),判断x是否为素数。如果是素数,返回True,否则返回False。
2、写一个函数prime_m2n(m,n)返回从m开始,到n结束范围内的质数,返回这些质数的列表,并在主程序中打印
L = prime_m2n(5, 10)
print(L) # 【 5, 7】
3、写一个函数primes(n),返回指定范围内的全部素数的列表,并在主程序中打印这些素数
L = primes(100)
print(L) # 【2, 3, 5, 7, .... 97】
def isprime(x):
for j in range(2,x):
if x % j == 0 :
return False
return True
def prime_m2n(m,n):
L_mn = list()
for x in range(m,n):
if isprime(x):
L_mn.append(x)
return L_mn
def primes(n):
return prime_m2n(2,n)
n = int(input("请输入整数数:"))
L = primes(n)
print(L)
2、第二题
算出100~999之间的水仙花数(Narcissistic number)水仙花数是指百位的3次方加上十位的3次方加上个位的3次方等于原数的整数
例如:153 等于 1 ** 3 + 5 ** 3 + 3 ** 3
建议:先写一个了数is_narcissistic(n) 来判断n是否为水仙花数,如果是返回True,否则返回False;再调用此函数进行判断
def is_narcissistic(number):
s = str(number)
if number == int(s[0])**3 + int(s[1])**3 + int(s[2])**3:
return True
return False
for x in range(100,1000):
if is_narcissistic(x):
print(x)