Python:等价于带有闭包的继承



我正试图从面向对象编程过渡到函数式编程。我有以下情况:(变量毫无意义——它们只是示例)。

Funcs = namedtuple('Funcs', ('func1', 'func2'))
def thing_1(alpha, beta):
    gamma = alpha+beta
    def func_1(x):
        return x+gamma
    def func_2(x):
        return x*gamma
    return Funcs(func_1, func_2)
def thing_2(alpha, beta):
    gamma = alpha+beta
    delta = alpha*beta
    def func_1(x):
        return x+gamma
    def func_2(x):
        return x*gamma+delta
    return Funcs(func_1, func_2)

现在,我们有一些代码重复:func_1在这两方面都是相同的。这两件事也以相同的方式初始化gamma。

如果我使用OOP,很明显该做什么——生成BaseThing,使func_2抽象,并让Thing1覆盖方法func_2Thing2覆盖func_2方法和__init__(它将调用BaseThing.__init__,然后初始化delta)。

使用闭包,对我来说并不明显——做同样事情的最佳方法是什么?

我不理解您的具体示例,但从更抽象的角度来看,OOP和FP之间的区别可以总结如下:

  • OOP中
    • 对象是一个单元
    • 参数化是通过虚拟方法实现的
    • 专业化是通过继承实现的

换句话说,对象的行为取决于它调用的虚拟方法(或"由"参数化)。要修复(或"专门化")某组"参数"(=方法),需要扩展对象。

  • 在FP中
    • 函数是一个单元
    • 参数化是通过函数参数实现的
    • 专业化是通过部分应用来实现的

要对一个函数进行参数化,可以将其他函数传递给它。要修复一组参数,可以创建一个新函数,该函数是具有部分应用参数的基函数。

插图:

# OOP style
class Animal:
    def voice(self):
        pass
    def greet(self, person):
        return '%s, %s!' % (self.voice(), person)
class Dog(Animal):
    def voice(self):
        return 'woof'
class Cat(Animal):
    def voice(self):
        return 'meow'
print Dog().greet('master')
print Cat().greet('master')
# FP style
def greet(voice, person):
    return '%s, %s!' % (voice(), person)
from functools import partial
dogGreet = partial(greet, lambda: 'woof')
catGreet = partial(greet, lambda: 'meow')
print dogGreet('master')
print catGreet('master')

最基本的方法是为func_1:创建一个单独的闭包

def gammafied_func_1(gamma):
    def func_1(x):
        return x + gamma
    return func_1
def thing_1(alpha, beta):
    gamma = alpha+beta
    def func_2(x):
        return x*gamma
    return Funcs(gammafied_func_1(gamma), func_2)

这类事情经常出现,以至于它有一个高阶函数,称为偏函数,指的是偏应用的一般概念。这让你可以使用一个函数来创建一个较小的函数,其中一些参数被"冻结":

from functools import partial
def func_1(gamma, x):
    return x + gamma
def thing_1(alpha, beta):
    gamma = alpha+beta
    def func_2(x):
        return x*gamma
    return Funcs(partial(func_1, gamma), func_2)

这里,partial(func_1, gamma)返回一个与func_1具有相同主体的新函数,只是它只接受了一个x参数,并且gamma已被"冻结"到thing_1内的本地gamma

这很有效,但不是特别整洁。

#!/usr/bin/env python
from collections import namedtuple
Funcs = namedtuple('Funcs', ('func1', 'func2'))
def thing_1(alpha, beta):
    gamma = alpha+beta
    def func_1(x):
        return x+gamma
    def func_2(x):
        return x*gamma
    return Funcs(func_1, func_2)
t1 = thing_1(3, 7)
print t1.func1(10), t1.func2(10)
def thing_2(alpha, beta):
    delta = alpha*beta
    t = thing_1(alpha, beta)
    def func_2(x):
        return t.func2(x) + delta
    return Funcs(t.func1, func_2)
t2 = thing_2(4, 6)
print t2.func1(10), t2.func2(10)

输出

20 100
20 124

范围工作:

In [22]: def f1(x):
   ....:     return x + gamma
   ....: 
In [23]: def t1():
   ....:     return f1("foo")
   ....: 
In [24]: gamma = "bar"
In [25]: t1()
Out[25]: 'foobar'

CCD_ 16闭合超过CCD_ 17。

最新更新