我理解在Python变量中指向对象,所以当你将它们分配给另一个时,它们都指向同一个对象。我想做的是在另一个变量时进行一次变量变换。在我正在使用GUI的情况下。所以我有一个带有文本属性的标签。我希望该属性等于另一个类中的属性。目前我正在通过使用中间函数来实现它,但感觉应该有一种更优雅的方式。所以我的方式实际上类似于下面的内容:
class Label():
def init():
self.text = None
self.gettext = None
def display():
if callable(self.gettext):
self.text = self.gettext()
else:
self.text = self.gettext
print(str(self.text))
class Anotherclass():
def init():
self.anattribute = "avaluethatchanges"
mylabel = Label()
myclass = Anotherclass()
def gettheattribute():
return myclass.anattribute
mylabel.gettext = gettheattribute
会有很多标签链接到许多不同的类。所以我希望能够做到的只是:
mylabel.gettext = myclass.anattribute
但是,当myclass.anattribute被更改时 - myclass.gettext不会。我理解为什么,但有没有另一种方式来编写它,而不是创建函数?
非常感谢
编辑: - 这两个类将用于其中一个或另一个可能不存在的其他应用程序中,因此我无法在类本身内对它们之间的关系进行硬编码。
答案 0 :(得分:1)
听起来这可能是property的一个很好的用例。使用属性可以使getter / setter像属性一样无缝地工作。来自文档
[属性]是构建数据描述符的简洁方法,该数据描述符在访问属性时触发函数调用 ...
每当用户界面授予属性访问权限,然后后续更改需要方法的介入时,property()内置帮助。
mylabel = Label()
class MyClass(object):
def __init__(self, some_label):
self._anattribute = None
self.label = some_label
@property
def anattribute(self):
return self._anattribute
@anattribute.setter
def anattribute(self, value):
self._anattribute = value # set the underlying value
# do something else, too
self.label.text = self._anattribute
因此...
mylabel = Label()
myinstance = MyClass(mylabel)
myinstance.anattribute = 'foo'
mylabel.text == 'foo' # True
存储self._anattribute
也不是必需的。如果适用,您可以让getter / setter直接访问/修改self.label.text
。
答案 1 :(得分:1)
我要说的第一件事就是在某个地方重复存储数据,因为它违反了 DRY < / strong>软件开发原理。
通常,对于这样的GUI设计,有 MVC ,模型,查看,的概念控制器即可。
这是一个非常大的主题,但一般的想法是你创建一个模型对象来存储你的所有数据,然后创建GUI的所有其他部分 - 显示数据的许多视图,以及更改数据的控制器 - 全部查看模型,以便仅在一个位置存储和更新数据。
GUI元素要么设计为接受模型,要么手动触发刷新,或者存在某种类型的Listen / Callback / Event系统,以便在模型更改时自动触发视图上的刷新。处理这种情况的具体方法取决于您正在使用的GUI框架。
实现此目的的一种简单方法是创建一个模型类,两个类共享并使用python 属性和回调注册表来触发更新。
class Model():
def __init__(self, text):
self._text = text
self._callbacks = []
def on_text_changed(callback):
self._callbacks.append(callback)
@property
def text(self):
return self._text
@text.setter
def text(self, value):
self._text = text
for callback in self._callbacks:
callback()
然后其他两个类都需要这样的东西
class Label():
def __init__(self, model):
self.model = model
self.model.on_text_changed(self.refresh)
def refresh(self):
print(self.text)
@property
def text(self):
return self.model.text
@text.setter
def text(self, value):
self.model.text = value
然后你会像这样创建它们
model = Model('The text')
label = Label(model)
another_class = AnotherClass(model)
label.text = 'This will update text on all classes'
another_class.text = 'So will this'
model.text = "And so will this.
答案 2 :(得分:0)
class MyClass:
def __init__(self,shared_dict): # use some mutable datatype (a dict works well)
self.shared = shared_dict
def __getattr__(self,item):
return self.shared.get(item)
data = {'a':'hello','b':[1,2,3]}
c = MyClass(data)
print(c.a)
data['a'] = 'world!'
print(c.a)
我想......从用例的角度来看,这真的没有多大意义......几乎可以肯定是一种更好的方式来做你正在尝试做的事情(可能涉及通知订阅者和更新变量)
答案 3 :(得分:0)
听起来你有一些想要绑定到底层模型的GUI元素。关于0x5453的非常好的建议,以下是什么:
class Label():
def __init__(self, text_source, source_attribute):
self.text_source = text_source
self.source_attribute = source_attribute
@property
def text_from_source(self):
return getattr(self.text_source, self.source_attribute)
def display(self):
print(str(self.text_from_source))
class Anotherclass():
def __init__():
self.anattribute = "avaluethatchanges"
>>> A = Anotherclass()
>>> L = Label(A, "anattribute")
>>> L.display()
avaluethatchanges
>>> A.anattribute = 3.1415
>>> L.display()
3.1415
这不允许您在标签内更改属性,但我更喜欢这样。