函数(三)
闭包 closure
将内嵌函数的语句和这些语句的执行环境打包在一起后,得到的函数对象称为闭包(closure)闭包必须满足一下三个条件
1、必须有一个内嵌函数
2、内嵌函数必须引用外部函数中的变量
3、外部函数的返回值必须是内嵌函数
示例:#! /usr/bin/python3
# 此程序示意闭包的用法
# 1、fn为内嵌函数
# 2、fn用到了fn外部的变量y
# 3、make_power将fn绑定的函数对象返回给调用者
def make_power(y):
def fn(x):
return x ** y
return fn
# pow2 等同于
# def pow2(x):
# return x**2
pow2 = make_power(2)
print('5的平方是:', pow2(5))
说明:
如果一个内嵌函数访问了外部嵌套函数作用域内的变量,则这个内嵌函数就是闭包。
装饰器 decorators(专业提高篇)
什么是装饰器:装饰器是一个函数,这个函数的主要作用是包装另一个函数或类
包装的目的是在不改变原函数名的情况下改变被包装对象的行为
函数装饰器 function decorators
函数装饰器是指装饰器是一个函数,传入的是一个函数,返回的也是一个函数语法:
@函数名
示例
#! /usr/bin/python3
def mydeco(fn): # <<==装饰器函数
def fx():
print('++++++++++++++++++++++')
fn()
print('----------------------')
return fx
@mydeco # <<==等同于hello = mydeco(hello)
def hello(): # <<==被装饰函数
print('hello tarena!')
# 将hello变量绑定在了mydeco返回的函数上
# hello = mydeco(hello) # 此种做法可以用装饰器@语法解决
hello() # 调用者
-------------------实际应用---------------------
#! /usr/bin/python3
# 以下是一个装饰器函数,在fn调用之前加一个权限验证的功能
def priv_check(fn):
def fx(name, x): # 定义闭包时参数要和被装饰的函数相同
print('正在权限验证...')
fn(name, x)
return fx
# 存钱对应的函数
@priv_check
def save_money(name, x):
print(name, '存钱', x, '元')
# 取钱对应的函数
@priv_check
def withdraw(name, x):
print(name, '正在办理取钱', x, '元的业务')
save_money('小张', 200)
save_money('小赵', 500)
withdraw('小李', 300)
-------------------------使用两个或两个以上的装饰器----------------------------------
#! /usr/bin/python3
# 以下是一个装饰器函数,在fn调用之前加一个权限验证的功能
def priv_check(fn):
def fx(name, x): # 定义闭包时参数要和被装饰的函数相同
print('正在权限验证...')
fn(name, x)
return fx
#
def message_send(fn):
def fy(name, x):
# 先办其他业务
fn(name, x)
print('短信:',name, '发生了', x, '元的操作,余额是xxx')
return fy
# 存钱对应的函数
@priv_check
def save_money(name, x):
print(name, '存钱', x, '元')
# 取钱对应的函数
@message_send
@priv_check
def withdraw(name, x):
print(name, '正在办理取钱', x, '元的业务')
save_money('小张', 200)
save_money('小赵', 500)
withdraw('小李', 300)
函数的文档字符串:
语法def 函数名(参数)
'''函数的文档字符串'''
函数语句块
说明:
文档字符串通常用来说明本函数的功能和使用方法
在交互模式下,输入help(函数名)可以查看函数的"文档字符串"
示例:#! /usr/bin/python3
def myfunction(a, b):
'''这是文档字符串
第二行
最后一行
'''
pass
help(myfunction)
# 结果:
# Help on function myfunction in module __main__:
# myfunction(a, b)
# 这是文档字符串
# 第二行
# 最后一行
函数的__doc__属性
函数内第一次未赋值给任何变量的字符串是此函数的文档字符串次文档字符串会自动赋值给函数的__doc__属性示例:
def cba():
'这是一个文档字符串'
pass
print(cba.__doc__) # 这是一个文档字符串
函数定义语句的完整语法:
[@装饰器1][@装饰器2]
[...]
def 函数名([位置形参],[*元组形参],[命名关键字形数],[**字典形参]):
'文档字符串'
语句块
模块 module
什么是模块:
模块是一个包含一系列变量,函数,类等组成的程序组模块是一个文件,模块文件通常以.py结尾
作用:
1、让一些相关的变量,函数,类等有逻辑的组织在一起,是逻辑结构更加清晰
2、模块中的变量,函数和类可提供给其他模块使用
模块的分类:
内置模块(birltins),在解释执行器的内部可以直接使用
标准库模块,安装python时已安装且可直接使用
第三方模块(通常开源),需要自己安装
用户自己编写的模块(可以作为其他人的第三方模块)
模块的导入 import
import语句
语法:import 模块名1 [as 模块新名1][,模块名2 [as 模块新名2],……]
示例:
import math #导入数学模块
import sys, os #导入sys,os模块
作用:
将某模块整体导入到当前模块中
用法:
模块名.属性名
help(模块名) 查看模块内的变量,函数,类等
from import语句
语法:form 模块名 import 模块属性名1 [as 模块属性新名1],模块属性名2 [as 模块属性新名2],……
作用:
将某模块内的一个或多个属性导入到当前模块的作用域
示例:
from math import pi, sqrt
from math import factorial as fac
from math import sin
# 可以直接使用导入的函数名或变量名
area = pi * 10 ** 2
from import * (少用)
语法:from 模块名 import *
作用:
将某模块的所有属性导入到当前模块
示例:
from math import *
print(sin(pi / 2))
print(factorial(10))
dir 函数
格式:dir([对象]) -> 返回一个字符串列表
说明:
如果没有参数调用,则返回当前作用域的所有变量的列表
如果给定一个对象作为参数,则返回这个对象的所有变量的列表
1、对于模块,返回这个模块的全部属性
2、对于一个类对象,返回类对象的所有变量,并递归基类的所有属性
3、对于其它对象返回所有变量,类变量和基类变量
数学模块 math
模块名math数学模块用法:
import math # 或 from math import *
常见函数:
变量 | 描述 |
---|---|
math.e | 自然对数的底e |
math.pi | 圆周率pi |
函数名 | 描述 |
---|---|
math.ceil(x) | 对x向上取整,比如x=1.2,返回2 |
math.floor(x) | 对x向下取整,比如x=1.2,返回1 |
math.sqrt(x) | 返回x的平方根 |
math.factorial(x) | 求x的阶乘 |
math.log(x[, base]) | 返回以base为底x的对数, 如果不给出base,则以自然对数e为底 |
math.log10(x) | 求以10为底x的对数 |
math.pow(x, y) | 返回 x**y (x的y次方) |
math.fabs(x) | 返回浮点数x的绝对值 |
角度和弧度degrees互换 | |
math.degree(x) | 将弧度x转换为角度 |
math.radians(x) | 将角度x转换为弧度 |
三角函数 | |
math.sin(x) | 返回x的正弦(x为弧度) |
math.cos(x) | 返回x的余弦(x为弧度) |
math.tan(x) | 返回x的正切(x为弧度) |
math.asin(x) | 返回x的反正弦(返回值为为弧度) |
math.acos(x) | 返回x的反余弦(返回值为为弧度) |
math.atan(x) | 返回x的反正切(返回值为为弧度) |
#! /usr/bin/python3
import math
'''
请编写函数fun(n)其功能是计算并输出下列多项式的和
sn = 1 + 1 / 1! + 1 / 2! + 1 / 3! + …… + 1 / n!
'''
# 方法一
def fun(n):
s = 0
for i in range(n + 1):
s += 1 / math.factorial(i)
print(s)
fun(10)
# 方法二
def fun(n):
return sum(map(lambda x: 1 / math.factorial(x), range(n + 1)))
print(fun(10))
'''
请编写fun(x,n)他的功能是计算下列多项式的和并返回
sn = 1 + x + x ** 2 / 2! + x ** 3 / 3! + …… + x ** n / n!
'''
def fun(x, n):
return sum(map(lambda i: x ** i / math.factorial(i), range(n + 1)))
print(fun(3.1, 10))
练习:
一直有五位朋友在一起
第五位朋友比第四位大2岁
第四位朋友比第三位大2岁
第三位朋友比第二位大2岁
第二位朋友比第一位大2岁
第一个人说他10岁,
编写程序算出第五个人几岁
2、改写之前的学生信息管理项目源码,要求带操作界面
+--------------------------------------------------+
|1)添加学生信息 |
|2)显示所有学生的信息 |
|3)删除学生信息 |
|4)修改学生信息 |
|5)按学生成绩高-低显示学生信息添加学生信息 |
|6)按学生成绩低-高显示学生信息添加学生信息 |
|7)按学生年龄高-低显示学生信息添加学生信息 |
|8)按学生年龄低-高显示学生信息添加学生信息 |
|q)退出 |
+--------------------------------------------------+
请选择:
要求,每个功能至少写一个函数与之呼应