玩了一晚上王者,突然觉得该学习,然后大晚上的搞出来这道练习题,凌晨一点写博客(之所以这么晚就赶忙写是因为怕第二天看自己程序都忘了咋写的了),我太难了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学习之高阶函数--嵌套函数、函数装饰器、含参函数装饰器的更多相关文章

  1. Python学习笔记 - 高阶函数

    高阶函数英文叫Higher-order function.什么是高阶函数?我们以实际代码为例子,一步一步深入概念. 变量可以指向函数 以Python内置的求绝对值的函数abs()为例,调用该函数用以下 ...

  2. python学习笔记——高阶函数map()

    满足以下两点中任意一点,即为高阶函数: 1.函数接收一个或多个函数作为参数 2.函数返回一个函数 1 描述 用函数和可迭代对象中每一个元素作为参数,计算出新的迭代对象 map() 会根据提供的函数对指 ...

  3. python学习之高阶函数

    filter函数:filter()为已知的序列的每个元素调用给定的布尔函数,调用中,返回值为非零的元素将被添加至一个列表中 list = filter(调用函数名,可迭代对象)——调用函数名自动传参— ...

  4. Python入门篇-高阶函数

    Python入门篇-高阶函数 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.高级函数  1>.First Class Object 函数在Python中是一等公民 函数也 ...

  5. Python 函数式编程 & Python中的高阶函数map reduce filter 和sorted

    1. 函数式编程 1)概念 函数式编程是一种编程模型,他将计算机运算看做是数学中函数的计算,并且避免了状态以及变量的概念.wiki 我们知道,对象是面向对象的第一型,那么函数式编程也是一样,函数是函数 ...

  6. Python中的高阶函数与匿名函数

    Python中的高阶函数与匿名函数 高阶函数 高阶函数就是把函数当做参数传递的一种函数.其与C#中的委托有点相似,个人认为. def add(x,y,f): return f( x)+ f( y) p ...

  7. python进阶学习之高阶函数

    高阶函数就是把函数当做参数传递的一种函数, 例如: 执行结果: 1.map()函数 map()接收一个函数 f 和一个list, 并通过把函数 f 依次作用在 list 的每个元素上,得到一个新的 l ...

  8. 匿名函数python内置高阶函数以及递归

    匿名函数 python定义一个函数通常使用def关键词,后面跟函数名,然后是注释.代码块等. def func(): '''注释''' print('from func') 这样就在全局命名空间定义了 ...

  9. 说说 Python 中的高阶函数

    高阶函数(higher-order function)指的是:接受一个函数为参数,或者把函数作为结果值返回的函数. 1 sorted() 比较常见的高阶函数是 sorted(),其内部的关键字参数 k ...

随机推荐

  1. CSS 属性1

    CSS列表属性 list-style:列表样式,取值:none.去掉项目符号或编号前面的各种符号. CSS边框属性:每个元素都可以加边框线  border-left:左边框线.   格式:border ...

  2. PAT甲级——A1127 ZigZagging on a Tree【30】

    Suppose that all the keys in a binary tree are distinct positive integers. A unique binary tree can ...

  3. Nvelocity 语法

    原文:Nvelocity 语法 1,数字循环   #foreach($i in [0..9])     $i #end 2,dictionary 根据key获取value值 #set($key1=&q ...

  4. AngularJs 报错 Error: [$parse:lexerr]

    参考:https://www.cnblogs.com/fangshidaima/p/6048071.html 错误: 根据错误找到报错行: $scope.$apply($scope.param1 = ...

  5. java笔试之提取不重复的整数

    输入一个int型整数,按照从右向左的阅读顺序,返回一个不含重复数字的新的整数. 此题可以使用linkedHashedSet\ArrayList\Stack\数组等来做.类似题目是输入一个数/字符串,从 ...

  6. JS数组 组团(如何创建数组)var mychar = new Array( )

    组团,并给团取个名(如何创建数组) 使用数组之前首先要创建,而且需要把数组本身赋至一个变量.好比我们出游,要组团,并给团定个名字"云南之旅". 创建数组语法: var myarra ...

  7. BP 算法之一种直观的解释

    0. 前言 之前上模式识别课程的时候,老师也讲过 MLP 的 BP 算法, 但是 ppt 过得太快,只有一个大概印象.后来课下自己也尝试看了一下 stanford deep learning 的 wi ...

  8. c# 中反射里的invoke方法的参数

    一个最简单的C#反射实例,首先编写类库如下: namespace ReflectionTest { public class WriteTest { //带参数的公共方法 public void Wr ...

  9. windows安装apache系统中无apache2服务解决方案

    一直都是用WIN开发PHP,今天有用户反映SHUGUANG CMS在APACHE+PHP中不能正常运行,只好自己机器配置个环境测试(http://xz.8682222.com)遇到点小问题,搜索相关资 ...

  10. Python 变量与数据类型

    1.变量命名规则: 变量名只能是字母,数字和下划线的任意组合 变量名第一个字符不能是数字 变量名区分大小写,大小写字母被认为是两个不同的字符 特殊关键字不能命名为变量名 2.数值的运算 print ( ...