Python: 等价于闭包继承
Python: Equivalent of Inheritance with Closures
我正在尝试从 OOP 过渡到函数式编程。我遇到以下情况:(变量没有意义 - 它们只是示例)。
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_2
和 Thing2
覆盖func_2
方法和 __init__
(将调用 BaseThing.__init__
然后初始化增量)。
使用闭包,这对我来说并不明显 - 做同样事情的最佳方法是什么?
适用范围:
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'
f1
关闭 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
没看懂你的具体例子,但是更抽象的说,OOP和FP的区别可以概括如下:
- 面向对象
- 对象是一个单位
- 通过虚方法实现参数化
- 专业化是通过继承实现的
换句话说,对象的行为取决于(或"is parametrized by")它调用的虚拟方法。要修复(或 "specialize")一组特定的 "parameters"(=方法),您可以扩展对象。
- 在 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)
这种事情经常出现,因此有一个高阶函数,称为 partial,指的是偏应用的一般概念。这使您可以使用一个函数创建一个较小的函数,其中包含一些参数 "frozen":
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)
returns 一个新函数,与 func_1
具有相同的函数体,只是它只接受一个 x
参数,而 gamma
有已 "frozen" 到 thing_1
内的本地 gamma
。
我正在尝试从 OOP 过渡到函数式编程。我遇到以下情况:(变量没有意义 - 它们只是示例)。
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_2
和 Thing2
覆盖func_2
方法和 __init__
(将调用 BaseThing.__init__
然后初始化增量)。
使用闭包,这对我来说并不明显 - 做同样事情的最佳方法是什么?
适用范围:
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'
f1
关闭 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
没看懂你的具体例子,但是更抽象的说,OOP和FP的区别可以概括如下:
- 面向对象
- 对象是一个单位
- 通过虚方法实现参数化
- 专业化是通过继承实现的
换句话说,对象的行为取决于(或"is parametrized by")它调用的虚拟方法。要修复(或 "specialize")一组特定的 "parameters"(=方法),您可以扩展对象。
- 在 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)
这种事情经常出现,因此有一个高阶函数,称为 partial,指的是偏应用的一般概念。这使您可以使用一个函数创建一个较小的函数,其中包含一些参数 "frozen":
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)
returns 一个新函数,与 func_1
具有相同的函数体,只是它只接受一个 x
参数,而 gamma
有已 "frozen" 到 thing_1
内的本地 gamma
。