python中的多方法闭包
我试图用python编写一个类对象,它的属性是能够修改私有字符串的闭包函数,我对闭包的理解大部分是理解的,但我不能让它处理多个闭包。我试图返回一个函数数组,但我得到python中的多方法闭包,python,closures,Python,Closures,我试图用python编写一个类对象,它的属性是能够修改私有字符串的闭包函数,我对闭包的理解大部分是理解的,但我不能让它处理多个闭包。我试图返回一个函数数组,但我得到 local variable 'string' referenced before assignment 向我指示字符串变量已销毁,或者函数未保留其闭包状态并无法访问它。get_val函数似乎可以工作,我尝试添加全局声明,但这不是问题所在,或者我无法让它正常工作 class StringUpdater: def _(sel
local variable 'string' referenced before assignment
向我指示字符串变量已销毁,或者函数未保留其闭包状态并无法访问它。get_val函数似乎可以工作,我尝试添加全局声明,但这不是问题所在,或者我无法让它正常工作
class StringUpdater:
def _(self):
string = "MI"
def get_val():
return string
def add_u():
if string.endswith("I"):
string+="U"
def add_two_through_last():
string+=string[1:]
def replace_III_with_U():
#global string
string.replace("III", "U")
def remove_UU():
#global string
string.replace("UU", "")
return [get_val,add_u,add_two_through_last,replace_III_with_U,remove_UU]
def __init__(self):
str_obj = self._()
self.get_val = str_obj[0]
self.add_u = str_obj[1]
self.add_two_through_last = str_obj[2]
self.replace_III_with_U = str_obj[3]
self.remove_UU = str_obj[4]
f = StringUpdater()
print f.add_two_through_last()
print f.get_val()
下面是一种以FP方式执行OO封装的方法。请注意,fp是一门不变性的艺术:
def encap_str(s):
def get():
return s
def append(s_):
return encap_str(s + s_)
def replace(s1, s2):
return encap_str(s.replace(s1, s2))
def encap(fname):
return {'get': get,
'append': append,
'replace': replace}[fname]
return encap
测试:
更多信息,请参考SICP
以下是我的一些看法 python似乎并不鼓励您执行FP。您可能知道,
lambda
在python中被削弱了,它并不意味着具有与普通函数相同的功能。立法会的范围界定是必要的,但令人讨厌。因此,如果您想了解FP,python不是一个好的平台
比较一下,Perl
非常支持FP。以下是Perl
中的演示:
package OOinPerl;
sub new{
my $self=shift;
my $type=ref $self || $self;
#... somehow fetch the parameters from @_ and save in $a, $b and $c.
my $data={a=>$a,b=>$b,c=>$c}; #this is a hash table reference
my $this=sub{
my $field=shift;
$data->{$field}=shift if @_;
$data->{$field}
};
bless $this, $type
}
#... other functions
在这里,对象实际上是lambda,lambda允许修改内部数据($data
)。但老实说,Perl中真正的OO很糟糕
我个人推荐您。您在赋值之前得到引用的错误
字符串的原因是在add\u
的内部,您试图通过+=
操作符写入名为string
的变量,因此Python正在add\u
的内部创建一个新的局部变量,这与中的变量不同
这可以通过Python3中的非局部
来解决,但是如果您仍然使用Python2,我只会将“outer”字符串
包装在一个数组中。我想说,这是在Python中使用的一种相当常见的模式,但大多数情况下,Python并没有真正以功能性的方式使用,尽管它完全能够实现闭包
为了说明这是如何工作的,我将事情简化了一点,并抛弃了类
,制作了一个使用闭包字符串的函数字典。为了写入该字符串,我将其固定在一个数组中:
def _mu():
data = ["MI"]
def rule1():
if data[0].endswith('I'): data[0] += 'U'
def rule2():
data[0] += data[0][1:]
def rule3():
data[0] = data[0].replace('III', 'U')
def rule4():
data[0] = data[0].replace('UU', '')
return {
'value': lambda: data[0],
'rule1': rule1,
'rule2': rule2,
'rule3': rule3,
'rule4': rule4}
mu = _mu()
我称之为mu
,因为这些规则可以识别为
现在你可以写:
mu['value']() # => 'MI'
mu['rule1']()
mu['value']() # => 'MIU'
此解决方案与相同,但避免使用dict['key']
表示法,因为我觉得这是一种更干净的函数.attribute
表示法。通过(ab)使用python函数可以使用function.attribute=value
分配属性这一事实来实现这一点
我将使用Ray Toal的示例,以便您可以看到差异
def _mu():
data = ["MI"]
def rule1():
if data[0].endswith('I'): data[0] += 'U'
def rule2():
data[0] += data[0][1:]
def rule3():
data[0] = data[0].replace('III', 'U')
def rule4():
data[0] = data[0].replace('UU', '')
_mu.value = lambda: data[0]
_mu.rule1 = rule1
_mu.rule2 = rule2
_mu.rule3 = rule3
_mu.rule4 = rule4
return _mu
mu = _mu()
mu.value() # => 'MI'
mu.rule1()
mu.value() # => 'MIU'
您可以重用\u mu
为其分配变量或函数,将其视为一个容器。对我来说,它似乎类似于使用self
变量的OOP。还请注意,\u mu.\uuuuu dict\uuuu
允许您访问属性,就像需要访问字典一样
我对这种方法与字典方法的性能不太了解,但这种方法可能是等效的,因为afaik属性存储在字典中
最后,我不知道将属性分配给\u mu
本身是否会产生某种问题,但如果会,您可以添加一个伪函数作为容器,然后将其分配给\u mu
,而不是分配给\u mu
:
container = lambda: None
container.value = lambda: data[0]
container.rule1 = rule1
container.rule2 = rule2
container.rule3 = rule3
container.rule4 = rule4
return container
你说的对。您的代码通常应该使用fp语言。这个恼人的问题是由python legb作用域引入的。完全相同的问题。感谢这篇文章,但我认为他的解决方案无法解决我的问题,他的解决方案仍然无法修改原始变量在python中使用多函数闭包是否有其他方法?你的问题是,字符串在python中是不可变的。(顺便说一句,请不要给变量命名string
)您对这种类似的方法有什么看法?
container = lambda: None
container.value = lambda: data[0]
container.rule1 = rule1
container.rule2 = rule2
container.rule3 = rule3
container.rule4 = rule4
return container