Дайте ссылку на атрибут экземпляра Python при определении класса - PullRequest
0 голосов
/ 10 июня 2010

У меня есть класс с атрибутами, которые имеют ссылку на другой атрибут этого класса.См. Класс Device, value1 и value2, содержащий ссылку на interface:

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() строка выполняется, когда определение класса анализируется (один раз).Таким образом, каждый Device класс имеет один и тот же экземпляр interface.

. Я мог бы изменить класс Device на:

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"

Итак, как я могу решить это с помощью питона?Я мог бы настроить функцию в классе Device для поиска атрибутов с типом Value и переназначить их новому интерфейсу.Разве это не распространенная проблема с типичным решением для него?

Спасибо!

Ответы [ 2 ]

4 голосов
/ 10 июня 2010

interface является атрибутом class .Поэтому, когда вы делаете

d2=Device("Bar")

, вы меняете порт interface для всех объектов класса Device.


Если вы хотите иметь эти атрибуты для экземпляра объекта, вы должны поместить их в метод __init__:

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

Вы должны использовать только атрибуты классаесли вы действительно хотите поделиться значением со всеми объектами.

Кроме этого, я не знаю, что вы пытаетесь достичь здесь.Зачем вообще определять его как атрибут класса?

2 голосов
/ 10 июня 2010

Вы не можете отложить поиск интерфейса, если ваши значения не являются методами Device. Возможно, что-то подобное делает то, что вы хотите?

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

Если вы хотите, чтобы ваши значения делали больше, чем получали и устанавливали, то это сложнее.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...