函数式编程更多的需要思维方式的改变,这个需要在平时的编程中去逐渐的体会。python中函数式编程其实和迭代器(iterator),生成器(generator)列表生成式(list comprehension)以及装饰器(decorator)等交织在一起的。 对于函数式编程,这里参考这几个文档来学习。
yield
语句的函数,这种函数返回的时一个生成器(generator)next()
函数或者是循环(loop)方法去获得相应的值functools.reduce(function, iterable[, _initializer_])
。f(x, y) = f(x)(y)
返回fp = f(x)
接受y参数,fp(y) == f(x, y)
In [3]:
## def具名函数和lambda匿名函数
def hello1(name):
print("Hello,", name)
hello2 = lambda name: print("Hello,", name)
hello1("Longshan")
hello2("Longshan")
print(hello1.__qualname__)
print(hello2.__qualname__)
In [5]:
## callable class
class Adder(object):
def __init__(self, n):
self.n = n
def __call__(self, m):
return self.n + m
add5_i = Adder(5)
print(add5_i)
print(add5_i(10))
## closure
def make_adder(n):
def adder(m):
return m + n
return adder
adder5_f = make_adder(5)
print(adder5_f)
print(adder5_f(11))
print(make_adder(5)(12))
In [13]:
## variables in closure
adders = []
for n in range(5):
adders.append(lambda m: m + n)
print(list([adder(10) for adder in adders]))
n = 10
print(list([adder(10) for adder in adders]))
## 因为这里是惰性求值,在创建adders的时候并没有计算n的值。n的值是在使用adders的时候计算的,在list comprehension中使用的时候n的值已经是4了,所以adders中加的都是4.
adders = []
for n in range(5):
adders.append(lambda m, k=n: m + k)
print(list([adder(10) for adder in adders]))
n = 10
print(list([adder(10) for adder in adders]))
## 这里n变成了局部变量,每一次执行k=n的时候,k的值是确定的,所以可以得到期望的结果。同时试图去重写n的值也不起作用了。
## TODO 这里的解释还是有些牵强的,需要进一步深化理解
In [34]:
# staticmethod/classmethod/abstractmethod
import math
class Pizza(object):
radius = 42
def __init__(self, cheese, vegetables):
self.cheese = cheese
self.vegetables = vegetables
@staticmethod
def mix_ingredients(x, y):
return x + y
@classmethod
def get_radius(cls):
return cls.radius
@staticmethod
def get_area():
raise NotImplementedError
def cook(self):
return self.mix_ingredients(sef.cheese, self.vegetables)
if __name__ == '__main__':
print(Pizza.mix_ingredients(2, 3))
print(Pizza(10, 12).get_radius)
print(Pizza(10, 12).get_radius())
In [36]:
# operator
## TODO 为什么self是8?
class TalkativeInt(int):
def __lshift__(self, other):
print("Shift", self, "by", other)
return int.__lshift__(self, other)
if __name__ == '__main__':
t = TalkativeInt(8)
print(t << 3)
In [1]:
from itertools import chain, count
thrice_to_inf = chain(count(), count(), count())
print(next(thrice_to_inf))
In [4]:
# The parameter order of reduce function
from functools import reduce
def even_filter(nums):
return filter(lambda x: x % 2 == 0, nums)
def multiply_by_three(nums):
return map(lambda x: x * 3, nums)
def convert_to_string(nums):
return map(lambda x: 'The number: %s' %x, nums)
def pipeline_func(data, fns):
return reduce(lambda a, x: x(a), fns, data)
list(pipeline_func(list(range(10)), [even_filter, multiply_by_three, convert_to_string]))
Out[4]:
In [6]:
import functools
def add(x, y):
return x + y
add2 = functools.partial(add, 2)
assert add(2, 3) == add2(3)
print(add2(3))
In [ ]: