作为兴(yu)趣(le)笔记之用,长期更新(大概
函数式:
傻瓜函数式编程
号称消灭for循环系列:
# 阶乘
n = 5
print reduce(lambda x, y: x * y, range(1, n + 1)) # 120
append的替代产物:
reduce(lambda x,y:x+y, [[1,2]],[3])#3,1,2
reduce(lambda x,y:y+x, [[1,2]],[3])#1,2,3
类haskell语法
class ProgressionMaker(object):
def __getitem__(self, key):
if isinstance(key, tuple) and len(key) == 4 and key[2] is Ellipsis:
return range(key[0], key[-1] + 1, key[1] - key[0])
>>> class Test(object):
... def __getitem__(self, key):
... print key
...
>>> test = Test()
>>> test[1]
1
>>> test[:]
slice(None, None, None)
>>> test[1:9]
slice(1, 9, None)
>>> test[1:3:5]
slice(1, 3, 5)
>>> test[1, 5]
(1, 5)
>>> test[1, 2:3, :4:, ::]
(1, slice(2, 3, None), slice(None, 4, None), slice(None, None, None))
>>> test[1, 2, ..., 9, 10]
(1, 2, Ellipsis, 9, 10)
>>> maker = ProgressionMaker()
>>> maker[1, 2, ..., 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> maker[6, 13, ..., 34]
[6, 13, 20, 27, 34]
3行代码解一元一次方程组
def solve(eq,var='x'):
eq1 = eq.replace("=","-(")+")"
c = eval(eq1,{var:1j})
return -c.real/c.imag
>>> solve("x - 2*x + 5*x - 46*(235-24) = x + 2")
3236.0
"""
看上去很强大,于是就解读下代码吧。
首先是第一行,它将等式进行了变形,生成了一个结果为0的算式“x - 2*x + 5*x - 46*(235-24) -( x + 2)”。
第二行用eval来执行这个算式,并将x = 1j代入算式,结果是-9708+3j。
注意x = 1j,所以这个方程就化简为“-9708+3x = 0”了,只要将-(-9708) / 3就能得到x了。而-9708是这个复数的实部,3是这个复数的虚部,于是结果变成了“-c.real/c.imag”。
很显然,这个函数是不能解复数方程的。
"""
语言特性:
a.append(a)
[1, […]]
a[1][1][1]… = [1, […]]
无限嵌套制!
元编程:
我们先来看一个如下的程序,这个程序的process()有三个步骤:
1)找出偶数。
2)乘以3
3)转成字符串返回
def process(num):
# filter out non-evens
if num % 2 != 0:
return
num = num * 3
num = 'The Number: %s' % num
return num
nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
for num in nums:
print process(num)
# 输出:
# None
# The Number: 6
# None
# The Number: 12
# None
# The Number: 18
# None
# The Number: 24
# None
# The Number: 30
我们可以看到,输出的并不够完美,另外,代码阅读上如果没有注释,你也会比较晕。下面,我们来看看函数式的pipeline(第一种方式)应该怎么写?
def even_filter(nums):
for num in nums:
if num % 2 == 0:
yield num
def multiply_by_three(nums):
for num in nums:
yield num * 3
def convert_to_string(nums):
for num in nums:
yield 'The Number: %s' % num
nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
pipeline = convert_to_string(multiply_by_three(even_filter(nums)))
for num in pipeline:
print num
# 输出:
# The Number: 6
# The Number: 12
# The Number: 18
# The Number: 24
# The Number: 30
我们动用了Python的关键字 yield,这个关键字主要是返回一个Generator,yield 是一个类似 return 的关键字,只是这个函数返回的是个Generator-生成器。所谓生成器的意思是,yield返回的是一个可迭代的对象,并没有真正的执行函数。也就是说,只有其返回的迭代对象被真正迭代时,yield函数才会正真的运行,运行到yield语句时就会停住,然后等下一次的迭代。(这个是个比较诡异的关键字)这就是lazy evluation。
好了,根据前面的原则——“使用Map & Reduce,不要使用循环”,那我们用比较纯朴的Map & 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)
nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
pipeline = convert_to_string(
multiply_by_three(
even_filter(nums)
)
)
for num in pipeline:
print num
但是他们的代码需要嵌套使用函数,这个有点不爽,如果我们能像下面这个样子就好了(第二种方式)。
pipeline_func(nums, [even_filter,
multiply_by_three,
convert_to_string])
那么,pipeline_func 实现如下:
def pipeline_func(data, fns):
return reduce(lambda a, x: x(a),
fns,
data)