# Map 和 Filter这两个函数能为函数式编程提供便利。
# Map会将⼀个函数映射到⼀个输⼊列表的所有元素上。
# 规范 map(function_to_apply, list_of_inputs)
# 常规做法:把列表中所有元素⼀个个地传递给⼀个函数,并收集输出。比如下面这样:
items = [1, 2, 3, 4, 5]
squared = []
for i in items:
squared.append(i**2) # 用for循环添加
print(squared)
# Map可以让我们⽤⼀种简单⽽漂亮得多的⽅式来实现。就是这样:
#squared = list(map(lambda x:x**2, items)) # 多数时候,使用匿名函数(lambda)来配合map
#squared = [map(lambda x:x**2, items)] # 不使用list()函数的话,生成的是一个map对象
#print(squared)
# lambda函数配合map,对一列表的函数进行操作,请看如下代码
1 def multiply(x):
2 return (x*x)
3 def add(x):
4 return (x+x)
5 funcs = [multiply, add] # 列表元素是函数名称
6 res = [[],[]]
7 for i in range(5):
8 value = list(map(lambda y:y(i), funcs)) # 这里y(i) 就是 [multiply(i), add(i)]
9 print(value) # 输出是2个元素组成的列表
10 res[0].append(value[0]) # 组成一个大的列表,对元素进行拆分
11 res[1].append(value[1])
12 print(res)
# filter能创建⼀个列表,其中每个元素都是对⼀个函数能返回True.下面是一个简单例子
number_list = range(-5,5)
less_than_zero = list(filter(lambda x:x<0, number_list))
print(less_than_zero) # 从输出可知,filter过滤掉lambda函数指定条件的数
# 这个filter类似于⼀个for循环,但它是⼀个内置函数,并且更快。
# set(集合)是⼀个⾮常有⽤的数据结构。它与列表(list)的⾏为类似,区别在于set不能
# 包含重复的值。下面示例检查列表中是否包含重复元素
1 some_list = ['a', 'b', 'c', 'b', 'd', 'm', 'n', 'n']
2 duplicates = []
3 for value in some_list:
4 if some_list.count(value) > 1:
5 if value not in duplicates:
6 duplicates.append(value)
7 print(duplicates) # 输出:['b', 'n']
# 下面使用更简单优雅的解决方案,使用集合(set)实现
# duplicates = set( [x for x in some_list if some_list.count(x) > 1] )
# print(duplicates)
# 第15行语句解读:使用变量x去迭代some_list,将x传递给if语句进行条件判断,返回条件判断为真的结果,最后set函数对结果中重复元素去重
# 交集,对⽐两个集合的交集(两个集合中都有的数据)
valid = set(['yellow', 'red', 'blue', 'green', 'black'])
input_set = set(['red', 'brown'])
print(input_set.intersection(valid))
# 差集,⽤差集(difference)找出⽆效的数据,相当于⽤⼀个集合减去另⼀个集合的数据
print(input_set.difference(valid))
# 使用符号创建集合
a_set = {'red', 'blue', 'green'}
print(type(a_set)) # 输出:<class 'set'>
# 三元运算符(ternary operator),三元运算符通常在Python⾥被称为条件表达式,这些表达式基于真(true)/假(not)的条件判
# 断,在Python 2.4以上才有了三元操作。
# 如果条件为真,返回真 否则返回假
# condition_is_true if condition else condition_is_false
# 例子
is_fat = True
state = "fat" if is_fat else "not fat"
print(state)
# ⽤简单的⼀⾏快速判断,⽽不是使⽤复杂的多⾏if语句。 这在⼤多数时候⾮常有
# ⽤,⽽且可以使代码简单可维护。
#(返回假,返回真)[真或假]
#(if_test_is_false, if_test_is_true)[test]
# 例子
fat = True
fitness = ('skinny', 'fat')[fat]
print(fitness)
# 为在Python中,True等于1,⽽False等于0,这就相当于在元组中使用0和1来选取数据
# 这个例⼦没有被⼴泛使⽤,⽽且Python玩家⼀般不喜欢那样,因为没有Python味⼉
# (Pythonic)。这样的⽤法很容易把真正的数据与true/false弄混。
# 另外⼀个不使⽤元组条件表达式的缘故是因为在元组中会把两个条件都执⾏,⽽ if-else
# 的条件表达式不会这样。例如:
condition = True
print(2 if condition else 1/0) # 输出:2
print((1/0, 2)[condition]) # 输出:ZeroDivisionError异常
# 这是因为在元组中是先建数据,然后⽤True(1)/False(0)来索引到数据。 ⽽if-else条件表
# 达式遵循普通的if-else逻辑树, 因此,如果逻辑中的条件异常,或者是重计算型(计
# 算较久)的情况下,最好尽量避免使⽤元组条件表达式。
# 装饰器(Decorators)是Python的⼀个重要部分。
# 是修改其他函数的功能的函数。
# 有助于让代码更简短,也更Pythonic(Python范⼉)。
# 一切皆对象,先理解python中的函数
# def hi(name='Michael'):
# return "hi " + name
# print(hi()) # 正常调用函数
# greet = hi # 将函数赋值给一个变量,这里没有使用小括号,因为并不是在调用hi函数,是将它放在greet变量里头
# print(greet('迈克尔')) # 通过变量调用函数
# del hi #删掉旧的hi函数,看会发生什么
# #print(hi()) # 输出:NameError异常
# print(greet('China')) # 输出:hi China
# 在函数中定义函数,也是嵌套函数。例如:
# def hi(name='Michael'):
# print("now you are inside the hi() function")
# def greet():
# return "now you are inside the greet() function"
# def welcome():
# return "now you are inside the welcome() function"
#
# print(greet())
# print(welcome())
# print("now you are back in the hi() function")
#
# hi() # 调用hi函数能正常运行,同时greet()和welcome()函数也会被调用
# greet() # 直接调用greet()会报错:NameError
# 从函数中返回函数,
# def hi(name='Michael'):
# def greet():
# return "now you are inside the greet() function"
# def welcome():
# return "now you are inside the welcome() function"
# if name == 'Michael':
# return greet
# else:
# return welcome
# a = hi() # 此时a指向hi()函数中的greet()函数
# print(a) # 输出结果是greet()函数的内存地址。<function hi.<locals>.greet at 0x000002B6240776A8>
# print(a()) # 在变量a后面加上小括号,实际上是执行:greet()
# 在if/else语句中返回greet和welcome,⽽不是greet()和welcome()。
# 因为当把⼀对⼩括号放在后⾯,这个函数就会执⾏;
# 然⽽如果不放括号在它后⾯,那它可以被到处传递,并且可以赋值给别的变量⽽不去执⾏它。
# 当写下a = hi(),hi()会被执⾏,而根据hi()内部的if语句返回相应的函数名称。
# 还可以打印出hi()(),这会输出if语句为True的返回
#print(hi()())
# 将函数作为参数传给另⼀个函数
# def hi():
# return "hi Michael"
# def doSomethingBeforeHi(func):
# print("I am doing some boring work before executing hi()")
# print(func())
#
# doSomethingBeforeHi(hi) # 把函数名作为参数传递另一个函数
# 第⼀个装饰器,上面代码也算是一个装饰器,下面来修改上面的代码,使程序更有用
def a_new_decorator(a_func):
def wrapTheFunction():
print("I am doing some boring work before executing a_func")
a_func()
print("I am doing some boring work after executing a_func")
return wrapTheFunction
# def a_function_requiring_decorator():
# print("I am the function which needs some decoration to remove")
# a_function_requiring_decorator() # 直接调用函数
# a_function_requiring_decorator = a_new_decorator(a_function_requiring_decorator)
# a_function_requiring_decorator() # 经过上面的赋值语句,此时调用函数。输出结果已经改变
# 上面例子正是python中装饰器做的事情!它们封装⼀个函数,并且⽤这样或者那样的⽅式来修改它的⾏为。
# 下面使用(@)符号来运行前面的代码
@a_new_decorator # 装饰下面的函数
def a_function_requiring_decoration():
"""Hey you! Decorate me"""
print("I am the function which needs some docoration to "
"remove my foul smell")
a_function_requiring_decoration()
# 使用符号(@)只是一个简短的做法,下面的赋值语句是装饰器的长语句做法
a_function_requiring_decoration = a_new_decorator(a_function_requiring_decoration)
print(a_function_requiring_decoration.__name__) # 输出:wrapTheFunction
print(a_new_decorator.__name__) # 输出:a_new_decorator
# 上面88行的输出表示函数被warpTheFunction替代了。它重写了我们函数的名字和注释⽂档(docstring)。幸运的是
# Python提供给我们⼀个简单的函数来解决这个问题,那就是functools.wraps。下面重写上面的代码
from functools import wraps
def a_new_decorator(a_func):
@wraps(a_func)
def wrapTheFunction():
print("I am doing some boring work before executing a_func")
a_func()
print("I am doing some boring work after executing a_func")
return wrapTheFunction
@a_new_decorator # 装饰下面的函数,a_function_requiring_decoration = a_new_decorator(a_function_requiring_decoration)
def a_function_requiring_decoration():
"""Hey you! Decorate me"""
print("I am the function which needs some docoration to "
"remove my foul smell")
print(a_function_requiring_decoration.__name__) # 此时输出的是:a_function_requiring_decoration
# 下面代码是装饰器蓝本规范(111-128)
from functools import wraps # 1
def decorator_name(f): # 2
@wraps(f) # 4
def decorated(*args, **kwargs): # 7
if not can_run: # 8
return "Function will not run"
return f(*args, **kwargs) # 9(if can_run=True)
return decorated # 5
@decorator_name # 3
def func():
return("Function is running") # 10(if can_run=True)
can_run = True # 6
print(func()) # 7 func=decorated
can_run = False
print(func())
# 注意:@wraps接受⼀个函数来进⾏装饰,并加⼊了复制函数名称、注释⽂档、参数列表
# 等等的功能。这可以让我们在装饰器⾥⾯访问在装饰之前的函数的属性。
# 下面是装饰器的使用场景
# 授权(Authorization),检查某个⼈是否被授权去使⽤⼀个web应⽤的端点(endpoint)。它们被⼤量
# 使⽤于Flask和Django web框架中。这⾥是⼀个例⼦来使⽤基于装饰器的授权
from functools import wraps
def requires_auth(f):
@wraps(f)
def decorated(*args, **kwargs):
auth = request.authorization
if not auth or not check_auth(auth.username, auth.password):
authenticate()
return f(*args, **kwargs)
return decorated
# ⽇志(Logging)应用,⽇志是装饰器运⽤的另⼀个亮点。下面是一个例子
from functools import wraps
def logit(func):
@wraps(func)
def with_logging(*args, **kwargs):
print(func.__name__ + " was called")
return func(*args, **kwargs)
return with_logging
@logit
def addition_func(x):
"""Do some math."""
return x + x
result = addition_func(4)
print(result)
'''在函数中嵌入装饰器,创建一个包裹函数,指定一个用于输出的日志文件'''
from functools import wraps
def logit(logfile='out.log'):
def logging_decorator(func):
@wraps(func)
def wrapped_function(*args, **kwargs):
log_string = func.__name__ + " was called"
print(log_string)
func(*args, **kwargs)
# 打开logfile并写入内容
with open(logfile,'a') as open_file:
# 现在将日志写到指定的logfile
open_file.write(log_string + '
')
return wrapped_function
return logging_decorator
# @logit()
# def myfunction1():
# print("Hello China!")
#
# myfunction1()
@logit(logfile='func2.log')
def myfunction2():
print("Hello world!")
myfunction2()