我有一个你可以实例化的按钮类:
engine.createElement((0, 0), Button(code=print, args=("Stuff!",)))
点击它会打印出“Stuff!”。但是,我需要按钮在单击时自行销毁。像这样:
engine.createElement((0, 0), Button(code=engine.killElement, args=(self,)))
然而,这只会杀死调用者,因为self指的是当时的调用者。我需要做的是提前让班级自己“自我”......
我想只是让字符串'self'
在点击时引用self
变量,但是如果我想在参数中使用字符串'self'
怎么办?
这样做的方法是什么?我的架构是错还是什么?
答案 0 :(得分:3)
不幸的是,这是不可能的 - 在评估构造函数之前,会评估按钮构造函数的参数。您需要将按钮分配给变量,然后设置回调:
b = Button(code=engine.killElement)
b.args = (b, )
或类似的东西。
答案 1 :(得分:2)
您基本上已将其设置为需要对对象的引用才能创建该对象,这当然是不可能的。你可以做这样的事情(列表和参数解包的元组一样好):
arglist = []
button = Button(code=engine.killElement, args=arglist)
arglist.append(button)
engine.createElement((0, 0), button)
这是不优雅的,不清楚的,冗长的,但它会将实例引用到实例中。
您可以使用哨兵值作为另一张海报建议。也许更好的建议是简单地使用约定(如Python本身)self
总是作为指定函数的第一个参数传递,并且不需要显式指定。然后你的回调写入总是接受self
,即使他们没有对它做任何事情。
但通常你不会通过将对象的行为传递给该对象的构造函数来指定对象的行为,而是通过继承来指定对象的行为。换句话说,你子类 Button
,覆盖它的onClick
方法或其他什么,并实例化子类。让onClick
知道它附加的实例是非问题。所以,我站在了一边,你的架构有点错误。
答案 2 :(得分:1)
这一般是不可能的。
但是,如果您正在创建Button
类,则可以传递一个特殊的标记值,表示“您自己”。例如:
class Button(object):
yourself = 'yourself'
def __init__(self, code, args):
self.code = code
self.args = [self if arg is yourself else arg for arg in args]
然后:
engine.createElement((0, 0), Button(code=engine.killElement, args=(Button.yourself,)))
挑选合适的哨兵可能很棘手 - 明显的选择,例如None
,0
或''
可能是合法的价值观,甚至你提出的棘手的事情可能会变成调试时有用的参数。将yourself
作为类变量或模块中的全局变量意味着如果您确实需要重新定义标记,则只需在一个地方更改它,而不是在您使用它的任何地方。
有关选择适当的哨兵值的简短讨论,请参阅http://bytes.com/topic/python/answers/555169-sentinel-values-special-cases。还有另一个博客有更多信息,但我没有在快速搜索中找到它...无论如何,这里有一些简单的想法:
None
总是最好的答案。 object
类(object()
)的全局实例。func_code
或其他)。Ellipsis
(或type(Ellipsis)
,这是一个名为ellipsis
的类型,但该名称无法访问)几乎总是安全的,因为它仅用于__getitem__
和朋友(可能还有定义要传递给他们的slice
个对象)。func_code
函数的__init__
成员。答案 3 :(得分:0)
也许这样的事情会有所帮助:
class Button(object):
def __new__(cls, *args, **kwargs):
obj = object.__new__(cls, *args, **kwargs)
kwargs['args'].append(obj)
return obj
def __init__(self, code, args):
self.code = code
self.args = args
def click(self):
return self.code, self.args
b = Button(code="engine.killElement", args=[])
print b.click()
输出:
('engine.killElement', [<__main__.Button object at 0x00B59AF0>])