Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/338.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
python中的多方法闭包_Python_Closures - Fatal编程技术网

python中的多方法闭包

python中的多方法闭包,python,closures,Python,Closures,我试图用python编写一个类对象,它的属性是能够修改私有字符串的闭包函数,我对闭包的理解大部分是理解的,但我不能让它处理多个闭包。我试图返回一个函数数组,但我得到 local variable 'string' referenced before assignment 向我指示字符串变量已销毁,或者函数未保留其闭包状态并无法访问它。get_val函数似乎可以工作,我尝试添加全局声明,但这不是问题所在,或者我无法让它正常工作 class StringUpdater: def _(sel

我试图用python编写一个类对象,它的属性是能够修改私有字符串的闭包函数,我对闭包的理解大部分是理解的,但我不能让它处理多个闭包。我试图返回一个函数数组,但我得到

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