python中的有效闭包

时间:2015-02-13 15:10:51

标签: python python-2.7

使用Python 2.7x我试图创建一个Map对象,它可以用'This'或'self'引用自己。在Javascript中,这将是粗略的,

myObj = function(){ 
 obj = {}; 
 this = obj; 
 obj = { 'a':'b', 'b':this.a };
 return obj;
}()

但是在Python中你不能做多行lambda表达式。范围界定的行为也不像我预期的那样。我可以在一个单独的行上创建一个函数然后调用它,但这似乎缺少pizzaz(特别是因为它不仅限于被调用一次)。 有没有一种有效的方法在Python中执行此操作?

编辑:有些人一直在问 OH我的上帝为什么???? 首先,作为一项练习。其次,你无法理解我正在尝试做什么 - 我试图用MAP模拟CLASS。在python中的类中,你会说,     var otherfunc = self.predefinedFunction 我希望能够使用self(这在其他一些语言中)来引用该对象。所以在python中我想转此:

my_obj = { 'sqr':lambda x: x*x, 'quad': my_obj['sqr']}

进入这个:

my_obj = { 'sqr':lambda x: x*x, 'quad': this['sqr']}

3 个答案:

答案 0 :(得分:2)

如果您尝试使用地图实现闭包,这样可以正常使用

mymap = {a:1,b:"foo"} # all of your previously initialized and constant data
mymap["self"] = mymap

然后你可以打电话

mymap["self"]["b"]

以下是使用此

编写代码的方法
mymap["func"] = lambda x: return x*mymap["self"]["x"]

这被认为是丑陋的,但你无法将地图称为lambda表达式中的全局变量。特别是,自我引用没有好办法。更好的方法是使用对象,而不是地图。

答案 1 :(得分:1)

在你的答案here中给出你的例子,你为什么不写一个课?以下功能等同于您的代码示例。

class myobj(object):
    def __init__(self):
        self.count = 0
    @staticmethod
    def addOne(n):
        return n + 1
    def addOneTimesTwo(self, n):
        return self.addOne(n) * 2
    def __getitem__(self, attrname):
        "Allows attributes to accessed as if they were key/value pairs in a map."
        return getattr(self, attrname)

myObj = myobj()
assert myObj["addOneTimesTwo"](1) == 4

如果您真的想要尝试模拟原型设计,那么您可以尝试以下方法。但它不适用于继承。你需要添加一些零碎的东西来实现这一点。

class Prototype(object):    
    def __init__(self, **attrs):
        self.__dict__.update(attrs)

def myobj():
    count = 0
    def addOne(n):
        return n + 1
    def addOneTimesTwo(n):
        """This is like a 'bound' method. The self in this context will refer to the same
        Prototype even if this function is transferred to a different Prototype."""
        return self.addOne(n) * 2
    self = Prototype(**locals())
    return self

myObj = myobj()
assert myObj.addOneTimesTwo(1) == 4

答案 2 :(得分:0)

使用以下样板代码:

class StoringOperations:
    for specfunc in ["getattr", "getitem", "call", "len"]:  # Extend as needed
        name = "__" + specfunc + "__"
        f = lambda self, *args, __name=name, **kwargs: StoredOperation(self, __name, args, kwargs)
        f.__name__ = name
        locals()[name] = f


class StoredOperation(StoringOperations):
    def __init__(self, s, methname, args, kwargs):
        self.__args = args
        self.__kwargs = kwargs
        self.__methname = methname
        self.__s = s
        super().__init__()


def gethiddenname(thing, name):
    return getattr(thing, "_StoredOperation" + name)


def consolidate(thing, this):
    if isinstance(thing, StoredOperation):
        s = consolidate(gethiddenname(thing, "__s"), this)
        methname = gethiddenname(thing, "__methname")
        try:
            meth = getattr(s, methname)
        except AttributeError:
            if methname == "__getattr__":
                meth = lambda *args, **kwargs: getattr(s, *args, **kwargs)
            else:
                raise
        return meth(*gethiddenname(thing, "__args"), **gethiddenname(thing, "__kwargs"))
    elif isinstance(thing, StoringOperations):
        return this
    else:
        return thing


class SelfConsciousMap(dict):
    def __init__(self, **kwargs):
        super().__init__()
        self.kwargs = kwargs
        for key in kwargs:
            self.consolidation(key)

    def consolidation(self, key):
        self[key] = consolidate(self.kwargs[key], self)

    def __getitem__(self, key):
        if key in self.kwargs and key not in self:
            self.consolidation(key)
        return super().__getitem__(key)


this = StoringOperations()

你可以这样做:

d = SelfConsciousMap(a=[1,2,3], b=this["a"], c=this["b"].copy(), d=this["a"].__len__())
print(d)

你会得到:

{'a': [1, 2, 3], 'c': [1, 2, 3], 'b': [1, 2, 3], 'd': 3}

可能在真正的代码中没用,但它表明有足够的类,一切皆有可能......