一、函数高级
1.函数的本质
函数就是一个变量,可以重新赋值,可以作为函数的参数,也可以作为函数的返回值
#1.变量可以指向函数,则可以通过该变量来调用指定函数,适用于系统函数和自定义函数 print(abs(-10)) #函数调用 print(abs) #<built-in内置 function abs> 函数本身 a = abs(-10) f = abs print(a) print(f) print(f(-18)) data = abs print(data(-20)) print("+" * 30) #2.函数名其实就是一个变量名 print(abs(-4)) # abs = 56 #print(abs(-11)) #TypeError: 'int' object is not callable可调用的 # list = [3,4,45] # print(list("fahjfh")) #TypeError: 'list' object is not callable #注意:自定义变量名的时候,尽量避免和系统内置函数重名,list(),tuple(),dict(),set(),str(),int()等 print("=" * 30) #3.函数可以作为参数使用,只需要传递函数名即可 def add(x,y,f): return f(x) + f(y) #abs(x) + abs(y) print(add(1,-2,abs)) #f = abs def hello(): print("hello world") def show(func): func() show(hello)
2.闭包
函数只是一段可执行代码,编译后就“固化”了,每个函数在内存中只有一份实例,得到函数的入口点便可以执行函数了。函数还可以嵌套定义,即在一个函数内部可以定义另一个函数,有了嵌套函数这种结构,便会产生闭包问题
#1.函数的嵌套定义 """ 注意: a.函数一定要手动调用,否则无法执行 b.但凡定义在函数内部的变量,在函数外面都无法直接访问 c.理论上函数的嵌套层数没有限制,但是一般嵌套两层 """ #a. def func1(): print("1111") def func2(): print("2222") func2() func1() #func2() #NameError: name 'func2' is not defined print("=" * 30) #b. def func1(): print("1111") def func2(): print("2222") return func2 f = func1() #f = func2 变量指向了函数 f() #f() ---->func2() # func1()() #2.闭包 """ 前提:嵌套定义的函数 概念:如果在一个内部函数中,对在外部函数中定义的变量进行引用,那么内部函数就被认为是闭包【closure】 """ #a #外部函数 def outter(n): num = n #内部函数 def inner(): return num + 1 return inner print(outter(3)()) f1 = outter(4) #f1 = inner print(f1()) #b def outter1(a): b = 10 def inner1(): return a + b return inner1 print(outter1(3)()) #c def outter2(num1): def inner2(num2): return num1 + num2 return inner2 print(outter2(3)(6)) f2 = outter2(6) print(f2(8)) #结论:闭包的好处:在内部函数中可以随意访问外部函数中的变量
3.变量的作用域
变量的作用域指的是变量可以使用的范围
程序的变量并不是在任意位置都可以访问,访问权限取决于这个变量是在哪里赋值的
变量的作用域决定了在哪一部分程序可以访问哪个特定的变量名称。Python的作用域一共有4种,分别是
L:Local,局部作用域
E:Enclosing,函数作用域【闭包函数外的函数中】
G:Global,全局作用域
B:Built-in,内建作用域【内置作用域】
查找方式:以L—>E—>G—>B,在局部找不到,便会去局部外的局部找(例如闭包),再找不到就会去全局找,再者去内建中找
注意:Python中只有模块(module)、类(class)以及函数(def、lambda)才会引入新的作用域,其他的代码块,例如if/elif/else、try/except、for/while等是不会引入新的作用域的,也就是说这些语句内定义的变量,在外部也可以使用
#1.变量作用域:不同作用域变量不重名 #变量的访问权限取决于变量定义的位置和访问的位置之间的相对关系 num1 = 10 #全局作用域:Global def outter1(): num2 = 20 #函数作用域:Enclosing,在inner的外面,在outter的里面 def inner1(): num3 = 30 #局部作用域:Local print("inner:",num1,num2,num21,num3) num21 = 25 #函数作用域:Enclosing print("outter:", num1, num2, num21) return inner1 f1 = outter1() f1() print("外部::",num1) print("=" * 30) #2.变量作用域:不同作用域变量重名 #变量查找规则:Local----->Enclosing---->Global num = 11 def outter2(): #num = 22 def inner2(): #注意:当不同作用域的变量重名的时候,根据【就近原则】识别 #num = 33 print("inner:",num) print("outter:", num) return inner2 outter2()() print("外部:",num) #3.总结 """ Python中只有函数【def,lambda】、模块【module】、类【class】才会引入新的作用域 其他的代码块,例如if语句,while语句,for语句,try-except语句等不会引入新的作用域, 也就是说,在这些语句内部定义的变量,在外部也可使用 """ if 1: n = 39 print(n) for i in range(4): m = 45 print(m)
4.局部变量和全局变量
定义在函数内部的变量拥有一个局部作用域,定义在函数外的拥有全局作用域。
局部变量只能在其被声明的函数内部访问,而全局变量可以在整个程序范围内访问。调用函数时,所有在函数内声明的变量名称都将被加入到作用域中
""" 说明:全局变量和局部变量是一个相对的说法【单层函数】 全局变量:在函数外面定义的变量 局部变量:在函数内部定义的变量 """ #1.局部变量 #局部变量的作用:为了临时保存数据,当函数执行完毕,函数中定义的局部变量会被销毁 def test1(): a = 100 print("修改前:%d" % (a)) a = 200 print("修改后~~~~:%d" % (a)) def func1(): a = 200 print("func1:%d" % (a)) test1() func1() #2.全局变量 a = 111 def show1(): print(a) def show2(): print(a) show1() show2() #3.全局变量和局部变量不重名 num1 = 44 def check(): num2 = num1 + 55 print(num2) check() print(num1) #4.全局变量和局部变量重名 a = 100 def test1(): #注意:当函数内出现全局变量和局部变量重名的情况,函数内部中的 变量名 = 数据 , # 可以理解为定义了一个新的局部变量,而不是修改全局变量的值 a = 200 print("修改前:%d" % (a)) a = 300 print("修改后~~~~:%d" % (a)) def func1(): print("func1:%d" % (a)) test1() func1()
5.global和nonlocal
5.1global
#1. a = 100 def test1(): #定义了一个新的局部变量,和全局变量没有关系 a = 3 a += 300 #a = a + 300 #UnboundLocalError: local variable 'a' referenced before assignment print(a) test1() print("111~~~~",a) print("=" * 30) #2. a = 100 def test1(): #global关键字表示声明当前局部变量使用的是全局变量 global a a += 300 #a = a + 300 print(a) test1() print("222~~~~",a) """ [面试题] b = 2 def show(): b += 1 show() print(b) 阅读上述代码,是否有误,如果没有问题结果是什么? """ b = 2 def show(): global b b += 1 show() print(b)
5.2nonlocal
#nonlocal只能使用在函数嵌套中 #1. x = 0 def outter(): x = 1 def inner(): #定义了一个新的变量,和函数作用域中的x没有关系 x = 2 print("inner:",x) inner() print("outter:", x) outter() print("global:",x) """ inner: 2 outter: 1 global: 0 """ print("*" * 30) #2 x = 0 def outter(): x = 1 def inner(): nonlocal x #经过nonlocal的修饰,此处的x就不是定义了一个新的变量,而是对函数作用域的x重新赋值 x = 2 print("inner:",x) inner() print("outter:", x) outter() print("global:",x) """ inner: 2 outter: 2 global: 0 """ """ global:单层函数,全局变量和局部变量之间 nonlocal:嵌套函数,函数作用域和局部作用域的变量之间 """
6.装饰器
#理解 def func(): pass """ func:函数本身【地址】 func():执行函数,得到执行的结果 """ #1.案例 def now(): print("拼搏到无能为力,坚持到感动自己") f1 = now f1() #需求:给now函数增加一个新的功能,但是不希望修改now函数本身 #解决方案;装饰器 """ 给某个函数增强功能但是又不希望更改原函数,这种在代码运行期间动态增加功能的方式被称为装饰器【Decorator】 本质:函数嵌套定义,将需要被装饰的函数作为参数传递,最后将装饰的结果返回 使用场景:统计函数的执行时间,权限校验,引入日志,执行函数之后的清理工作等 """
#1.简单的装饰器 def now(): print("拼搏到无能为力,坚持到感动自己") #a.书写闭包 #b.给外部函数设置参数,该参数表示需要被装饰的函数 def outter1(func): def inner1(): #c.增加新功能 print("new~~~~~~") #d.调用原函数,注意:c和d可以交换位置 func() return inner1 f1 = outter1(now) #func = now f1() #outter1就是装饰器的名称,inner1负责装饰,return inner1表示将装饰的的结果返回 #2.给内部函数设置参数 def getAge(age): print(age) # getAge(18) # getAge(-18) #需求:在不修改原函数的基础上,实现数据的过滤,当用户输入负数,则变成绝对值 def outter2(func): def inner2(n): #增加新功能 if n < 0: n = -(n) #调用原函数 func(n) return inner2 f2 = outter2(getAge) #f2 = inner2 f2(-5) #inner2(-5) f2(10)
列表的练习题
1.创建一个空列表,命名为names,往里面添加old_driver,rain,jack,shanshan,peiqi,black_girl 元素
names = ['old_driver','rain','jack','shanshan','peiqi','black_girl']
a.往names列表里black_girl前面插入一个alex
b.把shanshan的名字改成中文,姗姗
c.往names列表里rain的后面插入一个子列表,[oldboy, oldgirl]
d.返回peiqi的索引值
e.创建新列表[1,2,3,4,2,5,6,2],合并入names列表
f.取出names列表中索引4-7的元素
g.取出names列表中索引2-10的元素,步长为2
h.取出names列表中最后3个元素
i.循环names列表,打印每个元素的索引值,和元素,当索引值 为偶数时,把对应的元素改成-1
#a.往names列表里black_girl前面插入一个alex
names.insert(names.index('black_girl'),"alex")
print(names)
#b.把shanshan的名字改成中文,姗姗
names[names.index("shanshan")]="姗姗"
print(names)
#c.往names列表里rain的后面插入一个子列表,[oldboy, oldgirl]
names.insert(names.index("rain")+1,["oldboy", "oldgirl"])
print(names)
#d.返回peiqi的索引值
print(names.index("peiqi"))
#e.创建新列表[1,2,3,4,2,5,6,2],合并入names列表
list1=[1,2,3,4,2,5,6,2]
list2=names+list1
print(list2)
#f.取出names列表中索引4-7的元素
print(names[4:8])
#g.取出names列表中索引2-10的元素,步长为2
print(names[2:11:2])
#h.取出names列表中最后3个元素
print(names[-3:])
#i.循环names列表,打印每个元素的索引值,和元素,当索引值 为偶数时,把对应的元素改成-1
for i in range(len(names)):
if i%2==0:
names[i]=-1
print(i,names[i])
2.写一个循环,不断的问用户想买什么,用户选择一个商品编号,就把对应的商品添加到购物车里, 最终用户输入q退出时,打印购物车里的商品列表。 购物车用列表表示
# 商品类表
products = [['Iphone',6888],['MacPro',14800],['小米',2499],['Coffee',31],['Book',80],['NikeShoes',799]]
products=[]
while True:
good=input("请输入您想要购买的商品:")
if good=="q":
break
price=input("请输入商品的编号(数字):")
while price.isdigit()==False:
print("编号输入错误!,请重新输入")
price = input("请输入商品的编号(数字):")
small_list=[good,price]
products.append(small_list)
print(products)
字典的练习题
1.数字重复统计:
1). 随机生成100个整数;
2). 数字的范围[20, 100],
3). 降序输出所有不同的数字及其每个数字重复的次数;
例如: 结果可能为: {75:30, 38:21, 80:19, 92:12, 33:8, 65:5, 71:3, 99:2}
import random
dict1={}
for i in range(100):
k=random.randint(20,100)
if k not in dict1:
dict1[k]=1
else:
dict1[k]+=1
count_list=[item for item in dict1.items()]
print(count_list)
count_list.sort(key=lambda ele:ele[1],reverse=True)
print(count_list)
count_dict=dict(count_list)
print(count_dict)
字符串的练习题
字符串s = “hello bye 123 See you”
- 获取第二个“e”的索引位置 【不能直接通过交表获取 使用find查找】
- 从第二个“l”开始提取之后的子串
- 统计字符串s中"e"出现的个数
- 将字符串s反转
- 对字符串s排重 但是不影响字符的顺序
- 将首字母转化为大写
- 将每个单词的首字母大写
- 判断字符串s的内容是否是纯数字
- 判断字符串s的内容是否是字母或者数字
- 统计每个字符出现的次数
- 去除掉字符串s中的空格
- 去除掉字符串s中的数字
- 去除掉字符串s中的字母, 并将结果中数字两边的空格去除
- 对字符串s以空格进行切割
#1.获取第二个“e”的索引位置 【不能直接通过交表获取 使用find查找】
print(s.find("e",s.find("e")+1))
#或者
print(s.find("e",s.find("e")+1))
list1=[]
for index,strs in enumerate(s):
if strs=="e":
list1.append(index)
print(list1)
print(list1[1])
#2.从第二个“l”开始提取之后的子串
index1=s.find("l",s.find("l")+1)
print(index1)
print(s[index1:])
#或者
list1=[]
for index,strs in enumerate(s):
if strs=="l":
list1.append(index)
print(list1)
print(list1[1])
print(s[3:])
#3.统计字符串s中"e"出现的个数
print(s.count("e"))
#4.将字符串s反转
print(s[::-1])
#或者
s2=""
i=len(s)-1
while i >=0:
s2+=s[i]
i-=1
print(s2)
#或者
list1=list(s)
list1.reverse()
s3="".join(list1)
print(s3)
#5.对字符串s排重 但是不影响字符的顺序
str1=""
for i in s:
if i not in str1:
str1+=i
print(str1)
#6.将首字母转化为大写
print(s.capitalize())
#7.将每个单词的首字母大写
print(s.title())
#8.判断字符串s的内容是否是纯数字
print(s.isdigit())
#9.判断字符串s的内容是否是字母或者数字
print(s.isalnum())
#10.统计每个字符出现的次数
dict1={}
for i in s:
if i not in dict1:
dict1[i]=1
else:
dict1[i]+=1
print(dict1)
#11.去除掉字符串s中的空格
s2=""
for i in s:
if i != " ":
s2+=i
print(s2)
#12.去除掉字符串s中的数字
s2=""
for i in s:
if not (i.isdigit()):
s2+=i
print(s2)
#13.去除掉字符串s中的字母, 并将结果中数字两边的空格去除
s2=""
for i in s:
if not (i.isalpha()):
s2+=i
print(s2)
print(s2.strip(" "))
#14.对字符串s以空格进行切割
print(s.split(" "))
函数的练习
1.封装一个函数 验证一个年是否是闰年
闰年的条件:1. 能被4整除但是不能被100整除
2. 能被400整除
条件1和条件2 满足一个即可
def judge_bissextile(year):
if year%4==0 and year%100!=0 or year%400==0:
return True
else:
return False
print(judge_bissextile(2000))
2.封装一个函数 获取指定月的天数
注意: 闰年和平年下 2月份的天数是不一样的
def month_day(year,month):
year=int(year)
month = int(month)
if year%4==0 and year%100!=0 or year%400==0:
dict1={1:31,2:29,3:31,4:30,5:31,6:30,7:31,8:31,9:30,10:31,11:30,12:31}
return dict1[month]
else:
dict2 = {1: 31, 2: 28, 3: 31, 4: 30, 5: 31, 6: 30, 7: 31, 8: 31, 9: 30, 10: 31, 11: 30, 12: 31}
return dict2[month]
print(month_day(1999,6))
#或者
def is_leap(year):
return year % 4 == 0 and year % 100 != 0 or year % 400 == 0
res = is_leap(2020)
print(res)
def get_days(year, month):
if month in (1,3,5,7,8,10,12):
return 31
elif month in (4,6,9,11):
return 30
else:
return 29 if is_leap(year) else 28
days = get_days(2019, 2)
print(days)
3.封装一个函数 获取指定月所属的季节
3、4、5春季 6、7、8夏季 9、10、11秋季 12、1、1冬季
def judge_season(month):
month=int(month)
if month in [3,4,5]:
print("春季")
elif month in [6,7,8]:
print("夏季")
elif month in [9,10,11]:
print("秋季")
else:
print("冬季")
judge_season(2)
4.封装一个函数 验证指定数是否是质数
注意:质数:在大于1的自然数中,除了1和它本身以外不再有其他因数的自然数。
def judge_num(num):
count=0
for i in range(2,num):
if num%i==0:
return False
else:
return True
print(judge_num(11))
5.封装一个函数 验证一个数是否是回文
回文: 颠倒过来 与 自身数据一样的称为回文 例如 111 121 1221 12321
def judge_palindrome(num):
num1=str(num)
if num1 ==num1[::-1]:
return True
else:
return False
print(judge_palindrome("78987"))
6.封装一个函数,获取多个数中的最大值和平均值
def max_avg(*num):
list1=num
avg = sum(num) / len(num)
print("最大值是:{},平均值是{}".format(str(max(num)),str(avg)))
return max(num),avg
max_avg(78,79845,54
print(max_avg(78,79845,54))
7.封装一个函数 获取多个数中的平均值并统计其中高于平均数的值个数
def avg_count(*num):
list1=num
avg=sum(list1)/len(list1)
count=0
for i in list1:
if i>avg:
count+=1
print("平均值是{},高于平均数的数有{}个".format(str(avg),str(count)))
return avg,count
avg_count(1,2,3)
print(avg_count(1,2,3))
8.封装一个函数,获取所有的水仙花数
水仙花数是指一个 3 位数,它的每个位上的数字的 3次幂之和等于它本身(例如:1^3 + 5^3+ 3^3 = 153)
def daffodil():
list1=[]
for i in range(100,1000):
a=(i//100)**3
b=(i//10%10)**3
c=(i%10)**3
if a+b+c==i:
list1.append(i)
return list1
print(daffodil())
综合题
-
后台管理员只有一个用户: admin, 密码: admin
-
当管理员登陆账号成功后, 可以管理前台会员信息.
-
会员信息管理包含方法:
1.添加会员信息
2.删除会员信息
3.查看会员信息4.对会员按照年龄降序排序
5.退出
思路:
1.输入用户名和密码 跟 管理员的账号密码匹配 不一致的话 登陆失败
一致的话 提示登陆成功
并列出 对应的 1 2 3 4 5的操作 输入对应的编号 执行对应的方法
2.会员信息包含:
会员编号(mid) ---- 编号是在10000到99999中随机选择一个 不能重复
会员姓名(name)
会员性别(sex)
会员年龄(age)
使用字典保存每个会员信息
例如{'mid':10000, 'name':'乐乐','sex':'男', 'age':20}
使用列表保存所有的会员
例如[{'mid':10000, 'name':'乐乐','sex':'男', 'age':20},{'mid':10001, 'name':'美美','sex':'女', 'age':19}]
import random
list1=[]
account=input("输入用户名:")
if account=="admin":
password=input("请输入密码:")
if password=="admin":
print("登陆成功!")
print(""" 1.添加会员信息
2.删除会员信息
3.查看会员信息
4.对会员按照年龄降序排序
5.退出""")
while True:
num = input("请按号码输入您项进行的操作:(按q退出!):")
if num=="1":
a = input("请依次输入会员的 姓名,性别,年龄:")
a1 = random.sample(range(10000, 99999), 1)
a1 = str(a1[0]) + ","
a2 = a1 + a
lista = a2.split(",")
dicta = dict(zip(["编号", "姓名", "性别", "年龄"], lista))
list1.append(dicta)
print("添加成功!")
continue
elif num=="2":
b = input("请输入要删除的会员编号:")
for i in list1[:]:
if i["编号"]==b:
list1.remove(i)
print("删除成功!")
break
else:
print("不存在该编号!")
continue
elif num=="3":
print(list1)
continue
elif num=="4":
for i in range(len(list1)-1):
for j in range(len(list1)-1-i):
if list1[j]["年龄"]<list1[j+1]["年龄"]:
list1[j],list1[j+1]=list1[j+1],list1[j]
print("排序成功!")
elif num=="q":
break
else:
print("密码输入错误!")
else:
print("用户名不正确!")
#或者
import random
#1.添加会员
def adduser():
#获取会员
uid=getuid()
name=input("请输入你的姓名:")
age = input("请输入你的年龄:")
gender = input("请输入你的性别:")
#将一个会员信息保存到字典中
userdict={"uid":uid,"name":name,"age":age,"gender":gender}
#将字典添加到列表中
userList.append(userdict)
#2.删除会员
def deluser():
#通过会员id删除
uid=input("请输入需要被删除的会员号:")
for userdict in userList:
if userdict["uid"]==uid:
userList.remove(userdict)
print("删除成功!")
#如果在查找的过程中,提前找到了会员,则循环提前结束
break
else:
print("该会员不存在,无法删除!")
#3.查看会员信息
#3.1查看指定会员信息
def searchuser():
name=input("请输入需要查找的会员姓名:")
print("查找%s的信息如下:" % (name))
for userdict in userList:
if userdict["name"]==name:
print(userdict)
#3.2查看s所有会员信息
def searchall():
print("所有会员信息如下:")
#遍历列表
for userdict in userList:
print(userdict)
#4.排序
def sortbyage():
return sorted(userList,key=lambda userdict:userdict["age"],reverse=True)
#5.产生会员编号
def getuid():
#获取管理系统中已经存在的所有会员id
uidlist=[userdict["uid"] for userdict in userList]
#获取到的编号是否重复不一定,不确定循环次数
while True:
uid = str(random.randint(10000,99999))
if uid not in uidlist:
return uid
#定义一个列表,用于存放所有的用户字典
userList=[]
#调用函数
uname="admin"
pwd="admin"
username=input("请输入管理员的用户名:")
password=input("请输入管理员的密码:")
if username==uname and password==pwd:
print("登录成功")
print("=" * 10 + "欢迎进入xxx会员管理系统" + "=" * 10)
while True:
print("""该系统提供了如下操作:
0.添加会员信息
1.删除会员信息
2.查看指定会员信息
3.查看所有会员信息
4.对会员按照年龄降序排序
5.退出
""")
choice=input("请输入你需要进行的操作:")
if choice=="0":
adduser()
elif choice=="1":
deluser()
elif choice=="2":
searchuser()
elif choice=="3":
searchall()
elif choice=="4":
sortbyage()
elif choice=="5":
print("欢迎下次光临!")
break
else:
print("用户名或密码有误!")