day12
装饰器 decorator(专业提高篇)
什么是装饰器:
装饰器是一个函数,主要作用是用来包装一个函数或类
包装的目的是在不改变原函数(或类名)的情况下改变被包装对象的行为
(不改变原有函数的基础上改变其功能)
函数装饰器
是指装饰器是一个函数,传入的是一个函数,返回的是一个函数
语法:
def 装饰器函数(参数):
语句块
return 函数对象
@装饰器函数名<换行>
def 函数名(形参列表):
语句块
函数装饰器原理:
被装饰函数的变量(函数名)绑定装饰器函数调用后的返回的函数
示例见:
#mydecol.py代码
def mydeco(fn): #------->装饰器函数
def fx():
print("fx被调用")
return fx
@mydeco
def myfun():
print("myfun被调用")
myfun() #调用myfun
myfun()
myfun()
#mydecol2.py代码
def mydeco(fn): #------->装饰器函数
def fx():
print("---这是被装饰函数调用之前---")
fn()
print("+++这是被装饰函数调用之后+++")
return fx
@mydeco
def myfun():
print("myfun被调用")
#上述@mydeco的原理是在def myfun语句调用之后加了如下语句
#myfun = mydeco(myfun)
myfun() #调用myfun
myfun()
myfun()
# mydecol3.py代码
#此示例示意装饰器的应用场合及功能
#-----------以下是小李写的装饰器----------
def privileged_check(fn):
print("zzzzzzzzzzzzzzzzzzzzzzz")#无savemoney调用多少次,这个只打印一次
def fx(name,x):
print("正在进行权限验证...")
if True:
fn(name,x)
else:
print("权限验证失败")
return fx
#-----------以下是魏老师写的程序----------
@privileged_check
def savemoney(name,x): #存钱业务
print(name,'存钱',x,'元')
@privileged_check
def withdraw(name,x):
print(name,'取钱',x,'元')
# -----------以下是调用者写的程序----------
savemoney('小张',200)
savemoney('小赵',400)
withdraw('小李',500)
# mydecol4.py
#此示例示意装饰器的应用场合及功能
#-----------以下是小李写的装饰器----------
def privileged_check(fn):
print("zzzzzzzzzzzzzzzzzzzzzzz")
#无savemoney调用多少次,这个只打印一次
def fx(name, x):
print("正在进行权限验证...")
if True:
fn(name, x)
else:
print("权限验证失败")
return fx
def message_send(fn):
def fy(n,money):
fn(n,money) #调用被装饰函数
print("正在发送短信给", n, '...')
return fy
#-----------以下是魏老师写的程序----------
@message_send
@privileged_check
def savemoney(name, x): #存钱业务
print(name, '存钱', x, '元')
#实质:
#savemoney = privileged_check(savemoney)
#savemoney = message_send(savemoney)
@privileged_check
def withdraw(name, x):
print(name,'取钱', x, '元')
# -----------以下是调用者写的程序----------
savemoney('小张', 200)
savemoney('小赵', 400)
# withdraw('小李', 500)
函数的文档字符串:
函数内第一次为赋值给任何变量的字符串是此函数的文档字符串
语法:
def 函数名(参数列表):
'函数文档字符串'
语句块
说明:
1.文档字符串通常用来说明函数的功能和使用方法
2.在交互模式下,输入
>>>help(函数名) 可以查看函数的文档字符串
3.函数的文档字符串绑定在函数的_doc_属性上
示例:
def mysum(n):
'''mysum 函数用来求
1+2+3+....+n的和
'''
retrun 100
>>>help(mysum)
函数的_doc_属性
_doc_属性是用于记录文档字符串(mysum._doc_)
注: >>>mysum._ (查看mysum函数的全部属性)
函数的_name_属性
_name_属性用与记录函数名
说明:
以双下划线开头,以双下划线结尾的标识符通常代表pyhthon的特殊变量
函数定义的完整语法:
[@装饰器1]
[@装饰器2]
[@装饰器3]
...
def 函数名(位置形参, *元组参数名, 命名关键字形参, **字典形参):
'文档字符串'
语句块
面试题:
L = [1, 2, 3]
def f(n=0,lst=[]):
lst.append(n)
print(lst)
f(4, L) [1,2,3,4]
f(5, L)
f(100)
f(200) #打印结果是什么?为什么?
#缺省参数[] 在def语句执行时床键此列表,并一直被f函数所绑定
#缺省参数不是调用的每一回都创建的,会保留之前的结果
模块 Module
什么是模块
模块是一个包含有一系列数据,函数,类等组成的程序组
模块是一个文件,模块文件名通常以.py结尾
作用:
让一些相关的数据,函数,类等有逻辑的组织在一起,使逻辑结构更加清晰
模块中的数据,函数,类等可以提供给其他模块或程序使用
模块的分类:
1.内置模块,再解释执行器内部定义,可以直接使用
2.标准库模块,安装python时已安装且可以直接使用
3.第三方模块(通常为开源),需要自己安装
4.用户自定义模块(可以作为其他人的第三方模块)
模块的导入import
import语句
语法:
import 模块名1[as 模块新名1],模块名2[as 模块新名2],
...
作用:
将某模块整体导入到当前模块中
示例见:
import math #导入数学模块
import sys, time #导入系统模块和时间模块
import1.py
用法:
模块名.属性名
如:
print(math.factorial(5))
print(math.cos(0))
函数:
dir(obj) 函数,返回所有属性的字符串列表
help(obj)函数,可以查看模块的字符串文档
dir(math):
['__doc__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh', 'degrees', 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'gcd', 'hypot', 'inf', 'isclose', 'isfinite', 'isinf', 'isnan', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'log2', 'modf', 'nan', 'pi', 'pow', 'radians', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'trunc']
练习一:
写程序:
1.输入一个圆的半径,打印这个圆的面积
2.输入一个圆的面积,打印出这个圆的半径
(要求用math模块内的函数和数据)
#方法一:
import math
r = float(input("请输入圆的半径:"))
print("圆的面积是:",math.pi*r**2)
s = float(input("请输入圆的面积:"))
print("圆的半径是:",math.sqrt(s / math.pi))
#方法二(别名)
import math as m #给模块写别名
r = float(input("请输入圆的半径:"))
print("圆的面积是:",m.pi*r**2)
s = float(input("请输入圆的面积:"))
print("圆的半径是:",m.sqrt(s / m.pi))
from import 语句
语法:
from 模块名1 import 模块属性名1 [as 属性新名1],
模块属性名2 [as 属性新名2],....
作用:
将某模块内的一个或多个属性导入到当前模块的作用域
示例:
from math import factorial as fac
#只从math模块中导入了factorial重新命名为fac
from math import sqrt,sin,cos
#从math模块中导入了sqrt,sin,cos
from math import pi
#只从math模块中导入了pi
print("5的阶乘:",fac(5))
print("9的平方根:",sqrt(9))
print("圆周率是:",pi)
from import*语句 (不推荐使用,会造成变量覆盖)
语法:
from 模块名 import *
作用:
将某模块的所有属性导入到当前模块
示例:
from math import *
print(sin(pi / 2))
print(factorial(5)) #可以直接使用math里的全部属性
>>> from math import *
>>> pi/2
1.5707963267948966
>>> from math import *
>>> pi
3.141592653589793
dir函数
dir([对象]) 返回一个字符串列表
作用:
1.如果没有参数调用,则返回当前作用域内所有变量的列表
2.如果给定一个对象作为参数,则返回这个对象的所有变量的列表
(1)对于一个模块,返回这个模块的全部属性
(2)对于一个类对象,返回这个对象的所有变量并递归基类对象的所有变量
(3)对于其他对象返回所有的变量,类变量和基类变量
数学模块 math
文档参见:
数学模块math.HTML
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的反正切(返回值为为弧度)
时间模块 time
此模块提供了时间相关的参数
文档参见:
时间模块time.html
注: CST为中国标准时间(China Standard Time UTC+8:00)
time.time()
返回从计算机元年至当前时间的秒数的浮点数(UTC时间为准)
time.sleep(secs)
让程序按给定秒数的浮点数睡眠一段时间
time.gmtime([secs])
用给定秒数转换为用UTC表达的时间元组
(缺省返回当前时间元组)
time.asctime([tuple])
将时间元组转换为日期时间字符串
time.mktime(tuple)
如:time.mktime((2018, 8, 16, 16, 0, 0, 0))
将本地日期时间元组转换为新纪元秒数时间(UTC为准)
time.localtime([secs]) 将UTC秒数时间转换为日期元组(以本地时间为准)
练习二:
写一个程序,输入你的出生日期
1.算出你已经出生了多少天?
2.算出你出生那天是星期几?
import time
a = int(input("年"))
b = int(input("月"))
c = int(input("日"))
#出生的秒数(计算机元年开始)
brith_second = time.mktime((a, b, c, 0, 0, 0, 0, 0, 0))
#计算当前秒数(计算机元年开始)
cur_second = time.time()
lift_second = cur_second - brith_second
days = lift_second // 60 // 60 //24
print("您共出生了%d天" % days )
#得到出生那天的而时间元组
t = time.localtime(brith_second)
weeks = {0:'星期一',
1:'星期二',
2:'星期三',
3:'星期四',
4:'星期五',
5:'星期六',
6:'星期日'}
print("出生的那天是:",weeks[t[6]])
课后练习:
1.写一个程序,打印电子时间
格式为: HH:MM:SS 每过一秒钟刷新一次
#方法一:
import time
while True:
time.sleep(1)
s = time.time()
s1 = time.gmtime(s + 8*60*60)
print(s1[3], ':', s1[4], ':', s1[5])
#方法二:
import time
i = time.localtime()
s = time.mktime(i)
while True:
s += 1
d = time.localtime(s)
print(d[3], ':', d[4], ':', d[5])
time.sleep(1)
2.编写一个闹钟程序,启动时设置定时间,到时间打印一句:"时间到"
然后程序退出
#方法一:
import time
hour = int(input("请输入设定时间的小时:"))
minute = int(input("请输入设定时间的分钟:"))
second = int(input("请输入设定时间的秒钟:"))
while True:
time.sleep(1)
s = time.time()
s1 = time.gmtime(s+8*60*60)
if s1[3] == hour and s1[4] == minute and s1[5] == second:
print("定时时间到")
break
#方法二:
import time
i = time.mktime(time.localtime())
print(i)
h = int(input("请输入设定时间的小时:"))
m = int(input("请输入设定时间的分钟:"))
s= int(input("请输入设定时间的秒钟:"))
x = time.localtime()
t = (x[0],x[1],x[2],h,m,s,0,0,0)
n = time.mktime(t)
while True:
time.sleep(1)
i += 1
if i == n:
break
print('时间到')