python笔记11

来源:互联网 发布:广电网络怎么连接电视 编辑:程序博客网 时间:2024/06/05 08:54
2017/10/16
.lambda函数,globals()/locals()函数,eval()exec()函数,闭包函数,函数式编程,高阶函数
1.lambda表达式(又称匿名函数对象)
作用:
    创建一个匿名(无名)函数对象
    同def类似,但是不提供函数名


语法:
    lambda [参数1,参数2,...]:表达式
    注:[]内的部分可以省略


--------------------------------------------------
实例:
def myadd(x,y):
    return x + y


可以改写为:
myadd = lambda x,y:x+y
myadd(10+20)
print('10+20=',myadd(10,20))


实例:@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
print('10+20=',(lambda x,y:x*y)(100,200))


--------------------------------------------------


实例:
def operator(fn,x,y):       
    return fn(x,y) 


operator((lambda a,b:a+b),100,200)
operator((lambda a,b:a*b),100,200)


del operator  #释放函数所占的内存空间,用完之后销毁


曾出现的bug分析总结:
在python的交互环境中执行以上程序,如果
def operator(fn,x,y):       
    return fn(x,y) 

operator((lambda a,b:a+b),100,200)
直接按没有空行,交出出现SyntaxError: invalid syntax bug错误交互环境下,如果写下函数语句(多个表达式,系统会认为你的函数表达式可能还没有写完,因此前面依旧有3个点 ... 
提示是否继续写语句,我们应该按回车表示已经结束函数的定义,在>>>提示符下进行键入operator((lambda a,b:a+b),100,200))


注意:operator((lambda a,b:a+b),100,200) 和 print('10+20=',(lambda x,y:x*y)(100,200)) 的写法




语法说明:
    lambda只是一个表达式,它用来创建一个函数对象;
    当labda表达式执行时(调用的时候),返回的是冒号(:)后面的表达式的值;
    lambda表达式创建的函数只能包含一条语句(一个表达式)
    lambda比函数简单且可以随时创建和销毁,有利于减少程序的偶合度(联想以前的电视连接线和现在的一根HDMI线)


实例练习:
写一个lambda表达式,求两个变量的最大值
def mymax(x,y):
    if x >= y:
        return x
    else:
        return y


mymax2 = lambda x,y:mymax(x,y)


print(mymax2(100,200))


新的解法(题意实际上是将一个定义函数改写成为lambda函数表达式):
(1)
def mymax(x,y):
    if x >= y:
        return x
    return y
(2)
def mymax(x,y):
    rturn max(x,y)
(3)正确解法
def mymax(x,y):
    rturn x if x >= y else y


改写:
mymax2 = lambda x,y : x if x >= y else y
print(mymax2(100,200))


----------------------------------------------------------------------------------------------------------------------------------------------


2.globals()/locals()函数
  globals() 返回当前全局作用域内变量的字典
  locals()  返回当前局部作用域内变量的字典


实例:
a = 1
b = 2
def fn(c,d):
    e = 300
    print('locals 返回:',locals())
    print('globals返回:',globals())


fn(100,200)


>>>
locals 返回: {'c': 100, 'e': 300, 'd': 200}
globals返回: {'a': 1, 'b': 2, 'fn': xxxxxxxxxxxx}@@@@@@@@@@@@@@@@@@@@@
globals返回: {'__name__': '__main__', '__spec__': None, 
'__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x7f81a0d72a58>,
 'b': 2, '__doc__': None, 'a': 1, '__builtins__': <module 'builtins' (built-in)>, 
'__file__': 'yuan.py', 'fn': <function fn at 0x7f81a0e30f28>, '__package__': None, 
'__cached__': None}




实例:
a = 1
b = 2
def fn(c,d):
    e = 300
print('locals 返回:',locals())@@@@@@@@@@@@
    print('globals返回:',globals())
    d = globals()
    d['b'] = 10


fn(100,200)
print(d)  >>>10


----------------------------------------------------------------------------------------------------------------------------------------------


3.eval(),exec()函数
eval()函数作用:
    把一个字符串当成一个表达式来执行,返回表达式执行后的结果
eval()格式:
    eval(source,globals=None,local=None)@@@@@@@ @@@@@@@@@@@@@@@@


实例:
x = 100
y = 200
a = eval('x+y')
print(a)   
>>>300
总结('x+y')本应该是字符串表达式,但是eval将其作为一个表达式来执行并返回了




实例:
x = 100
y = 200
a = eval('x+y')
print(a)     #300


s = input('请输入字符串:')          #只能输入表达式例如1+2,如果输入字符串反而会出错---
a = eval(s)
print('请输入字符串的结果',a)   
>>>输入的数字字符串会像数字一样输出


实例:
x = 100
y = 200
a = eval('x+y')
print(a)
local_scope = {'x':5,'y':10}
a = eval('x+y',None,local_scope)
print('a=',a)
z = 300
a = eval('x*y+z',{'z':3333},local_scope)@@@@@@ @@@@@@@@@@@@
print(a)


----------------------------------------------------------------------------------------------------------------------------------------------


4.exec()函数:
作用:把一个字符串当做程序来执行
格式:
    exec(source,global=None,locals=None)


实例:
x = 100
y = 200
s = 'print('hello:',x,y)'
exec(s)   #hello:100 200


实例:
gs = {'x':10,'y':20}   #作用域
ls = {'x':1,'y':2}     #作用域
exec('z = x + y',gs,ls)              @@@@@@@@@@@@@@@@@@@
print(ls)   #{'x':1,'y':2,'z':3}








实例练习:
写一个程序的解释执行器,解释我们自己输入的程序
$./myprog.py
请输入程序:>>>> x = 100<回车>
请输入程序:>>>> x = 200<回车>
请输入程序:>>>> print('x+y',x+y)<回车>
x+y=300
提示:用exec()函数实现


a = input('请输入程序:')
b = input('请输入程序:')
c = input('请输入程序:')


exec(a)
exec(b)


新的解法:@@@@@@@@@@@@@@@@@@@@@@@


#!/usr/bin/python3 


while True:
    s = input('请输入程序:>>>')
    exec(s)                      #将任意写入的程序都用python3的解释执行器解释执行


----------------------------------------------------------------------------------------------------------------------------------------------


5.闭包 closure
    将组成函数的语句和这些语句的执行环境打包在一起时,得到的对象成为闭包
说明:
    如果一个内嵌函数访问函数外部作用域的变量,则这个函数就是闭包


实例:
def make_power(x):
    def fn(arg):
        return arg ** x  #本作用域内是没有x的绑定值的,因此去找其作用域外的变量值2
    return fn


f2 = make_power(2)       #f2绑定了一个函数,函数中绑定了一个值2
y = f2(100)             #平方 100的平方




f3 = make_power(3)       #f3绑定了一个函数,函数中绑定了一个值3
y = f3(4)               #立方 4的立方




注意:只有内嵌函数才能形成闭包,见以上的说明。


----------------------------------------------------------------------------------------------------------------------------------------------


6.函数式编程:
    指用一些列函数解决问题


函数式编程的好处:
    每一个函数完成细小的功能,一系列函数的任意组合可以完成大问题;
    函数仅接受输入并产生输出,不包含任何可能影响输出的内部状态


函数的可重入性:
    输入一定,则输出必须一定(函数没有用到函数外的变量)


可重入函数的优点:
    易于测试,易于调试,更高的生产率(软件、函数的复用),模块化(逻辑清晰),逻辑可证


实例-不可重入函数:
y = 200
def myadd(x):
    return x+y
print(myadd(10))    #210


y = 300
print(myadd(10))    #310




实例-可重入函数:
def add2(x+y):
    return x+y


----------------------------------------------------------------------------------------------------------------------------------------------


7.高阶函数:
    满足以下条件中的一个条件的函数即为高阶函数:
    1.函数接受一个或者多个函数作为参数输入
    2.函数返回一个函数


实例:
def operator(fn,x,y):       #函数作为参数
    return fn(x,y) 


python中内置(builtins)的高阶函数:map,filter,sorted


--------------------------------------------------


(1)map函数:
    map(func,*iterable)
    用函数和可迭代对象中的每个元素作为参数计算出新的可迭代对象,当最短的一个可迭代对象完成迭代后,迭代生成结束


实例:
#生成一个迭代器,此迭代器可以生成1-9的自然数的平方:1 4 9 16...


def power2(x):
    return x**2
mit = map(power2,range(1,10))  #range已经是一个可迭代器,map将range迭代器中的所有元素处理后再重新生成并返回一个迭代器,power2 没有括号,表示调用函数,而不是返回函数运行结果




>>> mit
<map object at 0x7f9068dd37f0>
>>> for x in mit:
...     print(x,end=' ')
... 
>>>1 4 9 16 25 36 49 64 81 


总结:
mit = map(power2,range(1,10)) 语句中全是函数或者是可迭代器,map函数,power2自定义函数,range(1,10)迭代函数(器,对象)
将后函数的迭代元素取出,供前函数使用,最后生成新迭代元素集,由map函数生成迭代器




实例:
#生成迭代器,1*4 ,2*3,3*2,4*1


def mymul(x,y):
    return x*y
mit = map(mymul,[1,2,3,4],[4,3,2,1])     #power2 没有括号,表示调用函数,而不是返回函数运行结果
for x in mit:
    print(x,end=' ')
>>>4 6 6 4




实例:
#求和:1**1 + 2**2 + 3**3 + ... + n**n ,用pow,sum,map,range函数组成来做
#知识点提示 pow(a,b,c)  表示 a**b%c


我的解法:
n = int(input('please enter a num:'))
mit = map(pow,range(1,n+1),range(1,n+1))
L = []
for x in mit:
    L.append(x)
print(sum(L))




新的解法1:
def mysum(n):
    def power(x):
        return pow(x,x)
    mit = map(power,range(1,1+n))
    return sum(mit)


a = int(input('please enter a num:'))
print(mysum(a))




新的解法2:
def mysum(n):
    return sum(map(pow,range(1,n+1),range(1,n+1)))
a = int(input('please enter a num:'))
print(mysum(a))




新的解法3:
def mysum(n):
    return sum(map(lambda x : pow(x,x),range(1,n+1)))
a = int(input('please enter a num:'))
print(mysum(a))




实例:
#求和: 1**9 + 2**8 + 3**7 + ... + 9**1 的和 11377
#提示:函数式编程 pow sum map range


def mysum(n):
    return sum(map(lambda x,y : (x ** y),range(1,n+1),range(n,0,-1)))
a = int(input('please enter a num:'))
print(mysum(a))




实例:@@@@@@@@@@@@@@@@@@@@@
mit = map(pow,[1,2,3,4],[3,2])
L = [x for x in mit]
print(L)
>>>[1,4]
总结:记得pow是幂运算!!!!!
--------------------------------------------------


(2)filter函数:
    filter(function or None,iterable)
    function是筛选条件
作用:
    筛选序列中的数据,返回一个可迭代对象,此可迭代对象将对iterable进行筛选


说明:
    function将对iterable中的每个元素进行求值,返回False则将此数据丢弃,返回True,则保留此数据


实例:
L = [x for x in range(10)]  #[0,1,2,3,4,5,6,7,8,9]


def isodd(x):                  #如果奇数则返回True
    return x % 2 == 1 
L2 = [x for x in filter(isodd,range(10))]    #filter函数中只有两个参数,一个是函数,另一个是迭代器函数
print(L2)
>>>[1, 3, 5, 7, 9]


--------------------------------------------------


(3)sorted函数
作用:
    将原可迭代对象的数据进行排序,生成排序后的列表
格式:
    sorted(iterable,key=None,reverse=False)
说明:
    key函数用来提供一个值,这个值将作为排序的依据


实例:
L = [5,-2,-4,0,3,1]
L2 = sorted(L)                      #[-4, -2, 0, 1, 3, 5]
L3 = sorted(L,reverse=True)         #[5,3,1,0,-2,-4]
L4 = sorted(L,key=abs)              #[0, 1, -2, 3, -4, 5]
L5 = sorted(L,key=abs,reverse=True) #[5, -4, 3, -2, 1, 0]


实例:
names = ['Tom','Jerry','Spike','Tyke']
L1 = sorted(names)                   #['Jerry', 'Spike', 'Tom', 'Tyke'] 首字母
L2 = sorted(names,key=len)           #['Tom', 'Tyke', 'Jerry', 'Spike']
pirnt(L1,L2)






实例:
'ekipS','ekyT''moT','yrreJ',  后再首字母  @@@@@@@@@@@@@@@@@@@@
names = ['Tom','Jerry','Spike','Tyke']
def k(x):
    return x[::-1]      #将字符串翻转,reversed.不能用
L = sorted(names,key=k) #翻转只是依据
print(L)                #['Spike', 'Tyke', 'Tom', 'Jerry']






实例-要求同上:
names = ['Tom','Jerry','Spike','Tyke']
L = sorted(names,key = lambda x : x[::-1])
print(L)
>>>['Spike', 'Tyke', 'Tom', 'Jerry']




=======================================================================================


8.递归函数(recursion):
    函数直接或间接是调用自身


实例:
def f():
    print('hello')
    f()
f()                       #调用函数
print('递归完成')
>>>
ello
hello
hello
hello
hello
...
最终bug提示:RecursionError: maximum recursion depth exceeded while calling a Python object
函数始终在调用自己,调用深度无限大,无限进入(屋子)(但是python系统中默认最多的递归深度是1000层),而不进行返回,
屏幕不会打印 递归完成




实例改进-方便观察:
import time
def f():
    print('hello')
    time.(1)
    f()
f()                       #调用函数
print('递归完成')




说明:
    递归一定要空值递归的层数,当符合某一条件时要终止递归调用;
    几乎所有的递归都能用while循环来代替


优缺点:
    优点:可以把问题简化,让思路清晰,代码更简洁
    缺点:递归因系统环境影响大,当递归深度太大,可能会得到不可预知的结果




实例:
#循环实现阶乘
def myfac(n):
    result = 1
    for x in range(1,n+1):
        result *= x
    return result


a = int(input('please enter a num:'))
print(myfac(a))




#递归实现阶乘  @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
def myfac(n):
    if n == 1:                #递归 和 循环的思想类似,其循环的判断条件,既可以按顺序取数,例如 个数,升序, 也可以逆顺序排列,例如本题的降序
        return 1              #这里用很巧妙的方法将阶乘实现,其实际是从 n (n-1)... 一直乘到 1
    return n * myfac(n-1)
print('5!= ',myfac(5))


=======================================================================================


课后练习:
1.用filter函数将 1-100之间的所有素数prime放入到列表中并打印


L = [x for x in range(10)]  #[0,1,2,3,4,5,6,7,8,9]


def isodd(x):                  #如果奇数则返回True
    return x % 2 == 1 
L2 = [x for x in filter(isodd,range(10))]    #filter函数中只有两个参数,一个是函数,另一个是迭代器函数




2.用递归方式计算 1+2+3+  ...  +n的和
def mysum(n):
    ...#此处自己实现


3.用函数式编程,算出1-20的阶乘的和


4.改写之前学生信息的程序,每个人的信息有:
  姓名:name
  年龄:age
  成绩:score
输入5个学生的信息,然后做如下的操作:
按成绩从高到低打印学生信息;
按年龄从高到低打印学生信息;
按年龄从低到高打印学生信息;
按原来输入顺序打印学生信息(保持原来的列表不变);




1.
def isprime(n):
    for i in range(2,n):
        return n % i != 0 
L = [ x for x in filter(isprime,range(1,101))]
print(L)




2.
def fun(n):
    if n == 1:                
        return 1              
    return n + fun(n-1)


a = int(input('please enter a num:'))
print(fun(a))




3.
def fun(n):
    if n == 1:                
        return 1              
    return n * fun(n-1)      #算阶乘
L = []
for i in range(1,21):
    L.append(fun(i))
print(sum(L))




4.
第1次做题:
docs = []
for x in range(5):
    name = input("请输入第"+str(x+1)+"个学生的姓名:")
    age  = int(input("请输入第"+str(x+1)+"个学生的年龄:"))
    d = {"name":name,"age":age}
    docs.append(d)
print(docs)


L=docs.copy()    #浅拷贝  L=docs[::]也可以
print('+'+'-'*13+'+'+'-'*13+'+')
print('|'+'姓名'.center(12)+'|'+'age'.center(12)+'|')
print('+'+'-'*13+'+'+'-'*13+'+') 
for d in L:
    print("|",d["name"].center(13),"|",str(d["age"]).center(13),'|',sep='')
print('+'+'-'*13+'+'+'-'*13+'+') 




############
names = ['Tom','Jerry','Spike','Tyke']
L1 = sorted(names)                   #['Jerry', 'Spike', 'Tom', 'Tyke'] 首字母
L2 = sorted(names,key=len)           #['Tom', 'Tyke', 'Jerry', 'Spike']
pirnt(L1,L2)
############


def fun():
    for i in L:
    d['age']


for i in range(5):


def quzhi():
    for i in range(5):
        return L[i]['age']






L3 = sorted(L,key =quzhi )






s = [(q,1,3)(w,2,4)(e,4,5)]
L = sorted(s,lanbda s : s[2])
print(L)




第2次做题:


网络参考提示:
L = [{'name':'a','score':10},{'name':'b','score':30},{'name':'c','score':20}]
print(L)
L2 = sorted(L,key=lambda stu:stu['score'])
print(L2)


#----------------------------------------------------------------------正解如下————————————————
docs = []


for x in range(3):
    name = input("请输入第"+str(x+1)+"个学生的姓名:")
    age  = int(input("请输入第"+str(x+1)+"个学生的年龄:"))
    score = int(input("请输入第"+str(x+1)+"个学生的分数:"))
    d = {"name":name,"age":age,"score":score}
    docs.append(d)


L=docs.copy()    #浅拷贝  L=docs[::]也可以


#----------------------------------------------------------------------


print('+'+'-'*13+'+'+'-'*13+'+'+'-'*13+'+')
print('|'+'NAME'.center(13)+'|'+'AGE'.center(13)+'|'+'SCORE'.center(13)+'|')
print('+'+'-'*13+'+'+'-'*13+'+'+'-'*13+'+') 


for d in L:
    print("|",d["name"].center(13),"|",str(d["age"]).center(13),'|',str(d["score"]).center(13),'|',sep='')


print('+'+'-'*13+'+'+'-'*13+'+'+'-'*13+'+') 


#----------------------------------------------------------------------


L = sorted(L,key=lambda stu:stu['score'])


print('+'+'-'*13+'+'+'-'*13+'+'+'-'*13+'+')
print('|'+'NAME'.center(13)+'|'+'AGE'.center(13)+'|'+'SCORE'.center(13)+'|')
print('+'+'-'*13+'+'+'-'*13+'+'+'-'*13+'+') 


for d in L:
    print("|",d["name"].center(13),"|",str(d["age"]).center(13),'|',str(d["score"]).center(13),'|',sep='')


print('+'+'-'*13+'+'+'-'*13+'+'+'-'*13+'+') 


#----------------------------------------------------------------------


L = sorted(L,key=lambda stu:stu['age']) 


print('+'+'-'*13+'+'+'-'*13+'+'+'-'*13+'+')
print('|'+'NAME'.center(13)+'|'+'AGE'.center(13)+'|'+'SCORE'.center(13)+'|')
print('+'+'-'*13+'+'+'-'*13+'+'+'-'*13+'+') 


for d in L:
    print("|",d["name"].center(13),"|",str(d["age"]).center(13),'|',str(d["score"]).center(13),'|',sep='')


print('+'+'-'*13+'+'+'-'*13+'+'+'-'*13+'+') 


#----------------------------------------------------------------------


L = sorted(L,key=lambda stu:stu['age'],reverse = True) 


print('+'+'-'*13+'+'+'-'*13+'+'+'-'*13+'+')
print('|'+'NAME'.center(13)+'|'+'AGE'.center(13)+'|'+'SCORE'.center(13)+'|')
print('+'+'-'*13+'+'+'-'*13+'+'+'-'*13+'+') 


for d in L:
    print("|",d["name"].center(13),"|",str(d["age"]).center(13),'|',str(d["score"]).center(13),'|',sep='')


print('+'+'-'*13+'+'+'-'*13+'+'+'-'*13+'+')


可以使用输入重定向完成这道题,工作中是写好了脚本方便测试
Python3 shiyan.py < nn.txt
如果用./students.py运行,需要为该文件添加执行权限 chmod u+x shiyan.py 并在该程序文档的首行(必须是第一行)键入#!/usr/bin/python3  来声明python3 解释执行器的位置


如果是shell文件 则要键入   #!/usr/bin/bash