机器学习——Python(五)
本篇主要练习函数式编程,这里关键点:map/reduce、排序、lambda匿名函数、filter、函数作为参数、函数作为返回值。
#coding:utf-8
print "-------------Higher-order function--------------------"
print "以abs函数为例",abs(-10)
print "abs 函数自身",abs
f=abs
print "变量可以指向函数 ",f
print "-------------将函数名作为参数传给另外一个函数--------------------"
# 函数执行过程的推导:a是个函数,该函数的功能是返回,f函数关于x,y计算值的算术加和运算。将函数作为参数传入,这样的函数称为高阶函数
def a(x,y,f):
return f(x)+f(y)
print "验证函数名作为变量传给另外一个函数 ",a(3,-6,abs)
print "-------------map/reduce函数--------------------"
#map 函数只接收两个参数 函数、序列。map函数将序列中元素依次做f(x)处理,并将处理结果作为新的list返回
#map 函数的调用,应当先声明 map中f函数,f=.... 然后在map中调用
def f(x):
return x*x
L= map(f,[1,2,3,4])
print "map函数的作用结果: ",L
print "map函数将列表中元素转化为字符串 ",map(str,[1,2,3,4])
def reduce_demon(x,y):
return x+y
r=reduce_demon
# print "reduce函数计算结果 ",reduce(r,L)----这种写法是错误的,这里对于
# reduce函数相对于map函数来说,最大的区别是在于reduce接收两个参数,而map函数只接收一个参数,与map相同的也是需要提前定义一个函数f
# reduce函数公式:reduce[f,(x1,x2,x3,x4)]=f(f(f(x1,x2),x3),x4)
print "reduce函数计算结果 ",reduce(r,[1,2,3])
# 提前定义一个接收两个参数的函数
def reduce_demon2(x,y):
return 10*x+y
r2= reduce_demon2#注意此处使用r2=reduce_demon2() 在函数赋值时不要带后面的(),带上()会在执行时报错
print "将列表[1,3,5,7,9]转化为13579: ",reduce(r2,[1,3,5,7,9])
#map 与 reduce函数配合,完成字符串转成整数类型
print "-------------reduce函数--------------------"
def reduce_demon3(x,y):
return 10*x+y
def map1(s):
#这个不是很理解?
return {"0":0,"1":1,"2":2,"3":3,"4":4,"5":5,"6":6,"7":7,"8":8,"9":9}[s]
r3=reduce_demon3
m1=map1
#map函数的参数(f,"序列"),因为reduce函数只接收两个参数,reduce(函数,序列)。map函数的返回值恰好是一个序列,reduce_demon3恰好是一个函数
print map(m1,"13579")
print "map、reduce函数配合转化 ",reduce(r3,map(m1,"13579"))
print "将上述的两个函数整合为一个函数str2int"
def str2int(s):
def m1(s):
return {"0":0,"1":1,"2":2,"3":3,"4":4,"5":5,"6":6,"7":7,"8":8,"9":9}[s]
def r2(x,y):#此处注意reduce 函数中的 参数函数,声明为f(x,y)
return 10*x+y
# 第一次开发时未编写 return语句
return reduce(r2,map(m1,s))
print "字符串转化为整型数据: ",str2int("13579")
print "--------------规范化用户输入字符串----------------"
# def regular_str(l):
def regular_str(s):
# s1 = s[0].upper()
# for s2 in s[1:]:
# s1 = s1 + s2.lower()
# return s.title()
return s.capitalize()
m = regular_str
# print regular_str('adam')
# print map(m,['adam', 'LISA', 'barT'])
# print map(str.capitalize(),['adam', 'LISA', 'barT']) 这种写法是错误的
#reduce函数=reduce(f,[x1,x2,x3])=f(f(f(f(x1,x2),x3),x4),其中f是可以接收两个参数的函数
def f(x,y):
return x*y
print reduce(f,[1,2,3])
def prod(x):
def f(x,y):
return x*y
return reduce(f,[1,2,3])
print prod([1,2,3])
print "--------------filter 练习----------------"
#filter 函数一定也是 接收一个 函数,一个序列,不同的是fiter 函数会根据 f处理的结果为如果返回值是 0、False、None、空字符串、空列表、空元组、空字典等,则丢弃该元素;否则保留,完成 对原序列中数据进行筛选
#错误1:在定义is_odd函数时,不能返回列表中的元素,应当返回True/false
# 错误2:在filter()函数中调用的时候,传入的参数应当是不带()的
def is_odd(x):
if x % 2 == 1:
return True
print "筛选序列中的奇数: ",filter(is_odd,[1,2,3,4,5,6])
print "s.strip()测试 ",' 123\n'.strip()
#and关键字 是 当前后的值不为False 时,返回最后一个真值。
print "and 关键字测试 ","asd" and False
print "and 关键字测试 ","asd" and ''
print "and 关键字测试 ","asd" and '123'
def not_empty(s):
return s and s.strip()#此处对字符串做删除空格、空串的操作,并返回处理的结果
print filter(not_empty, ['A', '', 'B', None, 'C', ' '])
print "---------------排序算法--sorted--------------------"
#sorted 是高阶函数,可以传入函数变量
print "排序算法 ",sorted([1,-1,3,2,90,2,-11])
def reversed_cmp(x,y):
if x > y:
return -1
if x <= y:
return 1
print "倒序排序算法: ",sorted([1,-1,3,2,90,2,-11],reversed_cmp)
#函数作为返回值
print "-----------------函数作为返回值----------------------"
#定义一个求和函数
def cal_sum(*args):
ax = 0
for n in args:
ax = ax + n
return ax
#定义一个函数,将求和函数返回
# def lazy_sum(*args):
# def cal_sum(*args):----此处的写法使得外部函数的args,失效,作用域范围
# # print args
# ax = 0
# for n in args:
# # print n
# ax = ax + n
# return ax
# # return cal_sum() 如果写成这种形式则在调用的时候返回为0
# return cal_sum(*args)
# f = lazy_sum(1,2,3,4)
# print f# return cal_sum() 如果写成这种形式则在调用的时候,打印返回结果为0
# print f()
def lazy_sum(*args):
def cal_sum():
ax = 0
for n in args:
ax = ax + n
return ax
return cal_sum
# f=lazy_sum([1,2,3,4]) 这里写法是错误的,可变参数
f1=lazy_sum(1,2,3,4,5)
f2=lazy_sum(1,2,3,4,5)
print "函数作为返回值后 返回的结果:",f1
print "调用将函数作为返回值的函数: ",f1()
print "即使两个函数传入的参数相同,但是f还是不同的",f1==f2
print "-----------------函数闭包的练习---------------------"
# 返回函数不要引用任何循环变量,或者后续会发生变化的变量。
# 定义返回函数列表
def count():
# 定义一个列表
fs=[]
for i in range(1,4):
# 在for循环里定义一个f,该函数返回i平方值
def f():
return i*i
fs.append(f)
return fs
f1,f2,f3 = count()
print f1()
print "返回值是三个函数的列表:",count()
print "-----------修改闭包,因为作用域的问题-------"
#在循环中再次定义一个函数,绑定循环变量,
def count():
# 定义一个 列表来存储生成的函数
L=[]
for i in range(1,4):
def f(j):
def g():
return j*j#此处j是引用外部的函数的参数
return g#在此处返回一个函数g
L.append(f(i))#此处绑定一个数
return L
f1,f2,f3 = count()
print f1()
print f2()
print f3()
print "*************lambda表达式的练习***************"
#lambda 表达式,没有函数名,没有return语句,但是也能返回函数处理结果,调用函数方式和之前调用函数的方式是一样的
f = lambda x:x*x
print f
print "lambda表达式的计算结果:",f(5)
print "-------------比较以下两个写法的不同,注意调用的方式----------------------"
def build(x,y):
return lambda :x*y+x*x
print "lambda表达式作为返回值返回: ",build(2,3) #此处返回的是一个函数——<function <lambda> at 0x034B9E70>
f=build(2,3)
print "lambda表达式作为返回值返回: ",f()#—— 此处返回的是一个数值:10
def build(x,y):
return lambda x,y:x*y+x*x
f=build(2,3)
print "lambda表达式作为返回值返回: ",f(2,3)#与上面的函数写法做比较
print "******************装饰器练习***********************"
#定义一个函数,然后将函数赋值给变量,通过该变量来调用该函数
#注意在对函数进行赋值时,建议:使用f=函数名,如果是后面加上(),如果原函数没有参数,则可以,如果有参数,带括号必须也要带上该参数,调用时也必须带上该参数
def now(l):
print "2020.12.12"
f=now
print f(1)
print "通过_name_属性,获取函数名: ",f.__name__
print "----------------定义一个装饰器-------------------"
#定义一个打印日志的装饰器,decorator 自身是一个高阶函数,传入函数名作为参数,返回一个函数
#decorator 包含两个部分
# 1、外部函数:参数是:函数名,返回值是内部函数函数名.函数体是内部函数
#2、内部函数:参数是任意数,*args **kw 返回值是 外部函数传入参数的函数,该返回值包含了参数。说明了在调用的时候,外部函数的传入的函数要带参数
#
def log(func):
def wraaper(*args,**kw):
# print "call %s():",% func._name_ 第一次编写此处不应当有逗号,
print "call %s():"% func.__name__#第一次编写时,此处写错,注意func 名字属性为.__name__ name左右两边是__两个横
return func(*args,**kw)
# return wraaper(*args,**kw) 第一次开发时错误,此处返回一个函数,只需要返回函数名,即可,函数名即为一个变量,不应当带参数
return wraaper
@log
def sum(x,y):
return x+y
print sum(3,4)
log(sum(3,4))
#定义一个复杂的函数,完成装饰器自身带有参数,即@log(参数):包含三个函数的嵌套,最外部的函数 是 除了函数作为参数,要传入的参数
#1、最外部函数:该函数带有一个参数,是装饰器的参数,
#2、第二层函数:该函数是装饰器,该函数的参数是:函数,函数的返回值是wraaper函数
#3、第三层函数是:wraaper函数,参数是(*args,**kw)完成打印print 返回值是 func(*args,**kw)
import functools
def log(text):
def decorator(func):
@functools.wraps(func)#注意此处要加上该注解,若不加则会使调用该装饰器的函数,会使方法名变为wraaper
def wraaper(*args,**kw):
print "%s %s:"% (text,func.__name__)
return func(*args,**kw)#此处是 wraaper返回值
return wraaper#此处是decorator返回值
return decorator#此处返回是:log的返回值
@log("execute")
def absM(x):
if x > 0:
return x
if x < 0:
return -x
absM(-10)
print "打印方法名 ",absM.__name__
print "*****************偏函数练习**********************"
print "字符串转成整型数据 ",int("12345")
print "字符串转成二进制 ",int("10000",2)
#使用functionTools 来定义一个偏函数
import functools
int2 = functools.partial(int,base=2)
print "使用functionTools转成二进制 ",int2("100000")