Python学习之高阶函数--嵌套函数、函数装饰器、含参函数装饰器
玩了一晚上王者,突然觉得该学习,然后大晚上的搞出来这道练习题,凌晨一点写博客(之所以这么晚就赶忙写是因为怕第二天看自己程序都忘了咋写的了),我太难了o(╥﹏╥)o
言归正传,练习题要求:构造类似京东的一个网站首页(超级简化),实现函数装饰器的设计(主要设计),装饰的内容为,无论添加什么商品进购物车,最终付款的时候都需要登录才能支付,且无论在哪个页面下登录过一次都不需要再次登录,即做一个函数装饰器,实现登录功能(装饰到所有商品界面)。
我的实现:商品分类页面进行函数话,即一个类别构造一个函数,选择商品类别即执行函数,至于函数的内容就是简单的打印下商品名称,毕竟重点在登录,商品类别函数内具体有什么不重要。当第一次登录时,可选择登录方式:京东或者微信,在项目文件夹中创建了两个txt文件,里面没啥东西,就一个TXT存一个字典,字典里面预设两个key当做用户名及密码。登录一次后再运行程序(我给设成自动的了),即选择其他商品类别,将不会再让登录验证。
具体实现效果图:
具体代码:
login_type = "jingdong"#用于初始化带参装饰器,然而我没用上
juge_login = False#用于判断登录状态,直接全局 def login(type):#装饰器为两层def,带参装饰器为三层def,但说实话,我的这个带参装饰器其实并没有在这个程序中起到什么作用,但提供了一个可用参数,我没用到,但这个参数是可以用的,可以做个判断加个功能啥的
def auth_method(fuction):
def really_login():
global juge_login
if(juge_login == False):
login_type = input('''请选择登录的方式:
1、京东
2、微信
''')
if(login_type == "1"):login_type = "jingdong"
if(login_type == "2"):login_type = "weixin"
username = input("请输入你的用户名:")
password = input("请输入你的密码:")
f = open(login_type,"r")#f.readline()返回的是一行,类型为str;f.readlines()返回的是所有行,返回类型是list(一行一个元素,因为我存了两个键用了一行,所以直接取第一个元素)
key = eval(f.readlines()[0])#虽然我存储的是字典形式的文本,但提取出来后只是长得跟字典一模一样的字符串,eval的功能就是将长得一模一样的str转为dict
for m,n in key.items():#遍历查找文本所有账户寻找匹配项
if(username == m and password == n):
print("登陆成功")
juge_login = True#置位 f.close()
if(juge_login == False):
print("用户名或密码错误,请重新输入:")
return really_login() fuction()#当登录完成或者登录过一次后,就不会执行上面的if判断(if判断含return,如果登不成功永远停留在登录上而无法执行下一步)
print("程序尚未完成,请选择继续测试功能:")
Start_main()#为了测试而专门放在这循环的,这个不是装饰的一部分,讲道理登录的装饰完就完了,这个可以加在main里搞个循环啥的,太懒了,就这样吧
return really_login#注意,返回的是函数(函数的内存地址,后面加上()是可以执行返回函数的,而不是结果(类似str,int等类型结果))
return auth_method @login(login_type)#@login() == @auth_method
def jiaju():
print('''请选择你要购买的商品:
1、海尔电冰箱
2、格力空调
3、席梦思床垫''') @login(login_type)#带参装饰,被装饰函数为@的下一行定义函数,用于装饰的函数为@后面紧跟的函数(带参函数略有不同)
def shipin():
print('''请选择你要购买的商品:
1、盼盼鸡味块
2、乐事薯片
3、伊利安慕希''') @login(login_type)
def yiwu():
print('''请选择你要购买的商品:
1、耐克球鞋
2、波司登棉袄
3、阿迪达斯帽子''') def Start_main():
print('''欢迎来到京东购物商城:
1、家具
2、食品
3、衣物''')
choose = input("请选择你要购买的类别:")
if(choose == "1"):
jiaju()
elif(choose == "2"):
shipin()
elif(choose == "3"):
yiwu()
else:print("输入错误,请输入商品类别前面的数字代码。") if __name__ == '__main__':#主函数调用开始界面函数(首页)
Start_main() 解析:装饰函数最大的特点在于返回值,返回的是函数本题(函数内存地址,相当于变量,指向的一块地址),而不是函数执行过后的结果,比如
def add(a,b):
return a+b
add与add(1,2)的区别在于什么?不是1,2带不带参数的区别,而是add是一个“变量”,指向一个内存地址,当访问(执行)这块地址时(执行方法为地址+());而add(1,2)是执行后返回的结果(无返回值为None),是动态的,会自己运行的。所以当return add时是返回add的内存地址,返回add()是返回add执行的结果,前者在返回值后面加上()就可以再次作为函数执行,后者是结果,加上()会报错,就像字符串后面加()
一样,无意义。
装饰函数就是利用了上述的返回内存地址这一特点产生的:
def decorat(f):
def inner(f):
return abs(f())
return inner
def add(x,y): 其中这三行等同于:@decorat
return x+y def add(x,y):
add = decorat(add) return x+y
上面的装饰器完成加完后取绝对值(写程序时有点迷装饰器卡了下看了篇文章他就是用这个例子,我借用下),装饰器的意义在于,不修改add这个函数,但却给add做了调整(装饰,给add加了些功能),关键点在于内层既执行了add(目标函数)又有其他的语句,然后又将内层函数的地址传给目标函数的“变量“,毕竟函数的名称是什么不重要,重要的是名称背后的地址。至于带参装饰函数更简单了,没有想象的那么好用或者说神奇,@XX这种形式的装饰明白的话,你就想,能不能在@XX后面加括号做手脚带个参数啥的,答案是可以,但带了参数就相当于执行函数了,即@和XX()是分开的东西,你的所要达到的效果是让XX()执行的结果等于函数装饰器的外层函数的内存地址,即XX()的返回值为第二层函数地址本身,明白这一点,则带参装饰器包括装饰器都明白了。
都两点了,赶紧睡觉,我太难了o(╥﹏╥)o
Python学习之高阶函数--嵌套函数、函数装饰器、含参函数装饰器的更多相关文章
- Python学习笔记 - 高阶函数
高阶函数英文叫Higher-order function.什么是高阶函数?我们以实际代码为例子,一步一步深入概念. 变量可以指向函数 以Python内置的求绝对值的函数abs()为例,调用该函数用以下 ...
- python学习笔记——高阶函数map()
满足以下两点中任意一点,即为高阶函数: 1.函数接收一个或多个函数作为参数 2.函数返回一个函数 1 描述 用函数和可迭代对象中每一个元素作为参数,计算出新的迭代对象 map() 会根据提供的函数对指 ...
- python学习之高阶函数
filter函数:filter()为已知的序列的每个元素调用给定的布尔函数,调用中,返回值为非零的元素将被添加至一个列表中 list = filter(调用函数名,可迭代对象)——调用函数名自动传参— ...
- Python入门篇-高阶函数
Python入门篇-高阶函数 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.高级函数 1>.First Class Object 函数在Python中是一等公民 函数也 ...
- Python 函数式编程 & Python中的高阶函数map reduce filter 和sorted
1. 函数式编程 1)概念 函数式编程是一种编程模型,他将计算机运算看做是数学中函数的计算,并且避免了状态以及变量的概念.wiki 我们知道,对象是面向对象的第一型,那么函数式编程也是一样,函数是函数 ...
- Python中的高阶函数与匿名函数
Python中的高阶函数与匿名函数 高阶函数 高阶函数就是把函数当做参数传递的一种函数.其与C#中的委托有点相似,个人认为. def add(x,y,f): return f( x)+ f( y) p ...
- python进阶学习之高阶函数
高阶函数就是把函数当做参数传递的一种函数, 例如: 执行结果: 1.map()函数 map()接收一个函数 f 和一个list, 并通过把函数 f 依次作用在 list 的每个元素上,得到一个新的 l ...
- 匿名函数python内置高阶函数以及递归
匿名函数 python定义一个函数通常使用def关键词,后面跟函数名,然后是注释.代码块等. def func(): '''注释''' print('from func') 这样就在全局命名空间定义了 ...
- 说说 Python 中的高阶函数
高阶函数(higher-order function)指的是:接受一个函数为参数,或者把函数作为结果值返回的函数. 1 sorted() 比较常见的高阶函数是 sorted(),其内部的关键字参数 k ...
随机推荐
- Hamilton回路 旅行商TSP问题 /// dp oj1964
题目大意: 给出一个n个顶点的无向图,请寻找一条从顶点0出发,遍历其余顶点一次且仅一次.最后回到顶点0的回路——即Hamilton回路. Input 多测试用例.每个测试用例: 第一行,两个正整数 n ...
- java_JDK8中新增的时间API
java.time 包含值对象的基础包 java.time.chrono 提供对不同的日历系统的访问 java.time.format 格式化和解析时间的日期 java.time.temporal 包 ...
- MFC 窗口刷新防止闪烁方法
防止窗口闪烁的方法 1.将Invalidate()替换为InvalidateRect(). Invalidate()会导致整个窗口的图象重画,需要的时间比较长,而InvalidateRect()仅仅重 ...
- h5对接jssdk支付分并调用开启支付分页面
1.ws.config签名 调用ticket等获取ws.config的签名,下面会调用方法再调用方法时需要再次按照调用方法的签名 wx.config({ debug: true, // 开启调试模 ...
- Android开发 ExpandableListView 可折叠列表详解
前言 在需要实现一个List的item需要包含列表的时候,我们就可以选择ExpandableListView. 其实这个View的原始设计还是ListView的那套.就是增加2层的ListView而已 ...
- JZOJ[3771] 【NOI2015模拟8.15】小 Z 的烦恼
题目 描述 题目大意 有从111到nnn的数字,每个数字都可以放在一个盒子里(可以不放).一旦放,满足: 如果它不在第mmm个盒子,那么它的两倍一定在后面一个盒子里. 如果它不在第111个盒子,那么它 ...
- thinkphp 自动验证
自动验证是ThinkPHP模型层提供的一种数据验证方法,可以在使用create创建数据对象的时候自动进行数据验证. 大理石平台价格表 验证规则 数据验证可以进行数据类型.业务规则.安全判断等方面的验证 ...
- Clion IDE的安装
/下载压缩包 wget https://download.jetbrains.8686c.com/cpp/CLion-2016.2.2.tar.gz //解压 tar -zxvf CLion-2016 ...
- 洛谷P3694 邦邦的大合唱
题目背景 BanG Dream!里的所有偶像乐队要一起大合唱,不过在排队上出了一些问题. 题目描述 N个偶像排成一列,他们来自M个不同的乐队.每个团队至少有一个偶像. 现在要求重新安排队列,使来自同一 ...
- 你知道的和不知道的sass
关于sass,大多数人的认识一个写css的工具而已 其实就是的 但是这个工具的威力你发挥了多少呢... 以下全部都是干货,希望你能用在自己的项目里 定义集合 我们通常是这么定义变量的 $warning ...