在类定义中引用python实例属性

在类定义中引用python实例属性,python,class,reference,attributes,Python,Class,Reference,Attributes,我有一个类,它的属性引用了这个类的另一个属性。参见类设备,值1和值2中的接口: class Interface(object): def __init__(self): self.port=None class Value(object): def __init__(self, interface, name): self.interface=interface self.name=name def get(self):

我有一个类,它的属性引用了这个类的另一个属性。参见类
设备
值1
值2
中的接口:

class Interface(object):
    def __init__(self):
        self.port=None

class Value(object):
    def __init__(self, interface, name):
        self.interface=interface
        self.name=name

    def get(self):
        return "Getting Value \"%s\" with interface \"%s\""%(self.name, self.interface.port)

class Device(object):
    interface=Interface()
    value1=Value(interface, name="value1")
    value2=Value(interface, name="value2")

    def __init__(self, port):
        self.interface.port=port

if __name__=="__main__":
    d1=Device("Foo")
    print d1.value1.get() # >>> Getting Value "value1" with interface "Foo"
    d2=Device("Bar")
    print d2.value1.get() # >>> Getting Value "value1" with interface "Bar"
    print d1.value1.get() # >>> Getting Value "value1" with interface "Bar"
最后一次打印错误,因为
d1
应该有接口“Foo”。我知道出了什么问题:当解析类定义(一次)时,执行行
interface=interface()
line。因此,每个
设备
类都有相同的
接口
实例

我可以将
设备
类更改为:

class Device(object):
    interface=Interface()
    value1=Value(interface, name="value1")
    value2=Value(interface, name="value2")

    def __init__(self, port):
        self.interface=Interface()
        self.interface.port=port
所以这也不起作用:值仍然引用原始接口实例,self.interface只是另一个实例

现在的输出是:

>>> Getting Value "value1" with interface "None"
>>> Getting Value "value1" with interface "None"
>>> Getting Value "value1" with interface "None"
那么,我怎样才能用蟒蛇的方式解决这个问题呢?我可以在
设备
类中设置一个函数来查找类型为
的属性,并将它们重新分配给新接口。这不是一个常见的问题,有一个典型的解决方案吗


谢谢

接口
是一个属性。所以当你这么做的时候

d2=Device("Bar")
您正在为类
设备
的所有对象更改
接口的端口


如果希望每个对象实例都具有这些属性,则必须将它们放入
\uuuu init\uuu
方法中:

class Device(object):
    def __init__(self, port):
        self.interface=Interface()
        self.value1=Value(self.interface, name="value1")
        self.value2=Value(self.interface, name="value2")
        self.interface.port=port

如果确实希望与所有对象共享一个值,则应仅使用类属性


除此之外,我不知道你想在这里完成什么。为什么首先将其定义为类属性?

接口
是一个属性。所以当你这么做的时候

d2=Device("Bar")
您正在为类
设备
的所有对象更改
接口的端口


如果希望每个对象实例都具有这些属性,则必须将它们放入
\uuuu init\uuu
方法中:

class Device(object):
    def __init__(self, port):
        self.interface=Interface()
        self.value1=Value(self.interface, name="value1")
        self.value2=Value(self.interface, name="value2")
        self.interface.port=port

如果确实希望与所有对象共享一个值,则应仅使用类属性


除此之外,我不知道你想在这里完成什么。为什么首先要将其定义为类属性?

除非您的值是设备的方法,否则不能延迟接口查找。也许这样的事情正是你想要的

def value(name):
    def get(self):
        print 'Getting %s from port %s' % (name, self.interface.port)
    def set(self, v):
        print 'Setting %s to %s on port %s' % (name, v, self.interface.port)
    return property(get, set)

class Device(object):
    value1 = value('value1')
    value2 = value('value2')
    def __init__(self, interface):
        self.interface = interface

class Interface(object):
    def __init__(self, port):
        self.port = port

d = Device(Interface(1234))
d.value1
d.value2 = 42

如果你想让你的值做的不仅仅是获取和设置,那就更难了。

除非你的值是设备的方法,否则你不能推迟界面查找。也许这样的事情正是你想要的

def value(name):
    def get(self):
        print 'Getting %s from port %s' % (name, self.interface.port)
    def set(self, v):
        print 'Setting %s to %s on port %s' % (name, v, self.interface.port)
    return property(get, set)

class Device(object):
    value1 = value('value1')
    value2 = value('value2')
    def __init__(self, interface):
        self.interface = interface

class Interface(object):
    def __init__(self, port):
        self.port = port

d = Device(Interface(1234))
d.value1
d.value2 = 42

如果你想让你的值做更多的事情而不是获取和设置,那就更难了。

我考虑过这一点,但是现在一个类检查器看不到value1和value2。这对编辑器的文档和智能感知功能有很大帮助。但这似乎是一个合理的解决方案。@Guenther-Jehle:您不应该为编辑器编写代码(如果您更改了编辑器,或者其他人使用了另一个编辑器,会发生什么情况?),您应该以最符合应用程序逻辑的方式编写代码。关于文档:提供好的文档字符串。我考虑过这一点,但现在类检查器看不到value1和value2。这对编辑器的文档和智能感知功能有很大帮助。但这似乎是一个合理的解决方案。@Guenther-Jehle:您不应该为编辑器编写代码(如果您更改了编辑器,或者其他人使用了另一个编辑器,会发生什么情况?),您应该以最符合应用程序逻辑的方式编写代码。关于文档:提供良好的文档字符串。