使用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']}
答案 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}
可能在真正的代码中没用,但它表明有足够的类,一切皆有可能......