由若干语句组成的语句块,函数名称,参数列表构成,它是组织代码的最小单元,完成一定功能。
def 语句定义函数
def 函数名(参数列表: 函数体()代码块 [return 返回值] # 函数名就是标识符,命名要求一样 #语句块必须缩进,约定4 个空格 #Python 的函数没有return 语句,隐式会返回一个None值 #定义中的参数列表成为形式参数,只有一种符号表达,简称 形参 #调用 函数定义,只是声明了一个函数,它不会被执行,需要调用 调用的方式,就是函数名加上小括号,括号内写上参数 调用时写的参数是实际参数,是实实在在传入的值,就是 实参
(1)位置参数:按照参数定义顺序传入实参
(2)关键字参数定义顺序传入实参
# 要求位置参数必须在关键字参数之前传入,位置参数是按位置对应的
(3)参数默认值
# 参数的默认值可以在未传入足够的实参的时候,对没有给定的参数赋值为默认值
(4) 可变参数
# 从传入一个可迭代对象,迭代元素求和
# 一个形参可以匹配任意个参数
def add(nums):
sum = 0
for x in nums:
sum += x
return sum
def add(*nums):
sum = 0
print(type(nums)) #------> 收集多个参数为一个tuple
for x in nums:
sum += x
return sum
(5) 可变参数
def showconfig(**kwargs):
print(type(kwargs)) #------> 收集为一个字典
for k,v in kwargs.items():
print('{} = {}'.format(k,v))
(6) 高级应用,可变参数的混合使用(多加练习)
(7)Python 3 引入keyword-only 参数
# 如果在一个星号参数后面,或者一个位置可变参数后,出现的普通参数,实际上已经不是普通参数了,而是keyword-only参数
# 特别注意此处的语法错误:
def fn(**kwargs,x):
print(x)
print(kwargs)
(8)参数小规则
# 参数列表参数一般顺序是,普通参数,缺省参数,可变参数,可变位置参数,keyword-only参数(可带缺省值),可变关键字参数
(9)参数结构
def add(x,y):
return x + y
t = (4,5)
add(t[0],t[1])
add(*t)
d = {'x':5,'y':6}
add(**d)
给函数提供实参的时候,可以在集合类型前使用*或者**,把集合类型的结构解开,提取出所有元素作为函数的实际参数,非字典类型使用 * 解构成为位置参数,字典类型使用 ** 解构成为关键字参数
编写一个函数,能够接收至少两个参数,返回最小值和最大值
def fn(*nums):
return max(nums),min(nums)
输入一个整数左右对齐打印
def show(n):
tail = ' '.join([str(i) for i in range(n,0,-1)])
width = len(tail)
for i in range(1,n):
print("{:>{}}".format(' '.join([str(j) for j in range(i,0,-1)]),width))
print(tail)
show(12)
def showtail(n):
tail = ' '.join([str(i) for i in range(n,0,-1)])
print(tail)
for i in range(len(tail)):
if tail[i] == ' ':
print(' '*i,tail[i+1:]) # -----> 切片的使用
showtail(12)
# Python 函数使用return语句返回 “返回值”
# 所有函数都有返回值,如果没有return 语句,隐式调用 return None
# return 语句并不一定是函数的语句块的最后一条语句
# 一个函数可以存在多个return 语句,但是只有一条可以执行。如果没有一条return 语句被执行到,隐式调用return None
# 如果有必要,可以显示调用return None, 可以简写为return
# 如果函数执行了return 语句,函数就会返回,当前被执行的return 语句之后的其它语句就不会被执行
# 函数有可见范围,这就是作用域的概念
# 内部函数不能被外部直接使用,会抛NameError 异常
# 一个标识符的可见范围,这就是标识符的作用域。一般常说的是变量的作用域
# 在整个程序运行环境中都可见
# 在函数,类等内部可见
# 局部变量使用范围不能超过其所在的局部作用域
# python 3 nonlocal 关键字的使用
def counter():
count = 0
def inc():
nonlocal count
count += 1
return count
return inc
foo = counter()
foo()
foo()
# 划重点
# 使用了nonlocal 关键字,将变量标记为不在本地作用域定义,而在上级的某一级局部作用域中定义,但不能是全局作用域中定义
属性__defaults__ 中使用元组保存所有位置参数默认值,它不会因为在函数体内使用了它而发生改变
# Local, 本地作用域,局部作用域的local 命名空间。函数调用时创建,调用结束消亡
# Enclosing ,Python2.2 时引入了嵌套函数,实现了闭包,这个就是嵌套函数的外部函数的命名空间
# Global , 全局作用域,即一个模块的命名空间。模块被import 时创建,解释器退出时消亡
# Build-in, 内置模块的命名空间,生命周期从python 解释器启动时创建到解释器退出时消亡。
# 全局函数销毁
重新定义同名函数
del 语句删除函数对象
程序结束时
#局部函数销毁
重新在上一级作用域定义同名函数
del 语句删除函数对象
上级作用域销毁时
非线性结构,每个元素可以有多个前驱和后继
# 有序树:节点的子树是有顺序的,不能交换
# 无序树:结点的子树是无序的,可以交换
每个结点最多2课子树
左斜树,所有结点都只有左子树
右斜树,所有节点都自由右子树
# 一颗二叉树的所有分支结点都存在左子树和右子树,并且所有叶子结点只存在在最下面一层
# 满二叉树一定是完全二叉树,但完全二叉树不是满二叉树
# 若二叉树的深度为k, 二叉树的层数从1到k-1层的结点数都达到了最大个数,在第k 层的所有结点都集中在最左边,这就是完全二叉树。
(流程演示: http://pythontutor.com/visualize.html#mode=display )
函数直接或者间接调用自身就是递归
递归需要有边界条件,递归前进段,递归返回段
递归一定要有边界条件
当边界条件不满足的时候,递归前进
当边界条件满足的时候,递归返回
# 小练习:
def fib(n):
return 1 if n < 2 else fib(n-1) + fib(n-2)
for i in range(5):
print(fib(i),end=' ')
注意:
递归有深度限制,如果递归复杂,函数反复压栈,栈内存很快就溢出
pre = 0
cur = 1
print(pre,cur,end=' ')
def fib(n,pre=0,cur=1):
pre,cur = cur,pre + cur
print(cur,end=' ')
if n == 2:
return
fib(n-1,pre,cur)
fib(7)
# 添加判断条件,类循环写法
# 通过别的函数调用了函数自身
(要用代码的规范来避免这种递归调用的发生)
Python 借助 Lamdba 表达式构建匿名函数
lamdba 表达式(匿名函数) 只能写在一行上,被称为单行函数
主要就是在高阶函数传参数时候,使用lamdba 表达式,往往能简化代码
(lambda x,y=3:x + y)(5)
[x for x in (lambda *args:map(lambda x:x+1,args))(*range(5))]
[x for x in (lambda *args:(x+1 for x in args))(*range(5))]
[x for x in (lambda *args:map(lambda x:(x+1,args),args))(*range(5))]
# 生成器指的是生成器对象,可以由生成器表达式得到,也可以使用yied关键字得到一个生成器函数,调用这个函数得到一个生成器对象
#函数体中包含yield语句的函数,返回生成器对象
# 生成器对象,是一个可迭代对象,是一个迭代器
# 生成器对象,是延迟计算,惰性求值的
普通的函数调用fn() ,函数会立即执行完毕,但是生成器函数可以使用next函数多次执行
生成器函数等价于生成器表达式,只不过生成器函数可以更加的复杂
# 小练习:
def fib():
x = 0
y = 1
while True:
yield y
x,y = y,x+y
foo = fib()
for _ in range(5):
print(next(foo))
for _ in range(10):
next(foo)
print(next(foo))
pre = 0
cur = 1
print(pre,cur,end=' ')
def fib1(n,pre=0,cur=1):
pre,cur = cur,pre + cu
print(cur,end=' ')
if n == 2:
return
fib1(n-1,pre,cur)
fib1(10)
yield from 是Python 3.3 出现的新语法
yield from iterable 是 for item in iterable:yield item 形式的语法糖
def inc():
for x in range(1000):
yield x
foo = inc()
print(next(foo))
print(next(foo))
print(next(foo))
def inc():
yield from range(1000)
foo = inc()
next(inc())
id(foo),id(inc)
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。