Python 黑魔法研究系列

作为兴(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, […]]
无限嵌套制!

元编程:

不用元类进行元编程-IBM

深刻理解Python中的元类(metaclass)

我们先来看一个如下的程序,这个程序的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)
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值