2015-07-31 2 views
1

Так что это довольно понятно.Странное поведение в моем классе Python

class Tray(object): 
    ''' 
    A class used to collect information about each unique tray 
    ''' 
    def __init__(self): 
     self.cycle = None 
     self.cell = None 
     self.bIsTilted = False # Assume trays are not tilted 
     self.bSendNoData = False # Assume data is sent, modified later if data not sent 
     self.trayData = (self.cycle, 
         self.cell, 
         self.bIsTilted, 
         self.bSendNoData) 

    def __repr__(self): 
     return str(self.trayData) 

    def setCycle(self, cycle): 
     self.cycle = cycle 

    def setCell(self, cell): 
     self.cell = cell 

Если я бегу следующие утверждения:

currentTray = Tray() 
currentTray.setCycle(250) 
currentTray.setCell(300) 
print(currentTray) 
currentTray.setCell(25) 
print(currentTray.cell) 

мой выход будет:

(None, None, False, False) 
25 

Итак, я предполагаю, что я пытаюсь выяснить, почему мой self.trayData ISN обновляясь по значениям в self.cycle, self.cell и т. д. В чем проблема?

+1

В Python, вы обычно не определяете '' setCycle' и setCell' (который был бы более правильно будет называться 'set_cycle' и 'set_cell', случай верблюда условно зарезервирован для имен классов), вместо этого позволяя пользователю просто устанавливать значения самих атрибутов. – chepner

+0

Вы правы в том, что мое соглашение об именах отключено.Но я определенно где-то читал, что, поскольку Python не позволяет технически разрешать «частные/общедоступные» переменные, это по-прежнему правильный подход к написанию аксессуаров для ваших переменных. – Asif

+1

@Asif: Nope. Вы просто позволяете конечному пользователю изменять вещи напрямую. Если позже вам понадобится инкапсуляция, вы создадите свойство, подобное шоу Ананда. Свойства можно записывать, а также читать. – Kevin

ответ

3

Когда вы делаете следующее -

self.trayData = (self.cycle, 
       self.cell, 
       self.bIsTilted, 
       self.bSendNoData) 

self.trayData «s первый элемент не point to self.cycle (по крайней мере, не так, как вы этого хотите), он указывает на объект self.cycle указывает на то, что находится None. Поэтому, когда вы устанавливаете новое значение в self.cycle, оно не будет автоматически отражено в self.trayData.

Проще всего сделать для вашего конкретного случая работу, установить trayData как в setCycle, так и setCell методах.

Пример -

def setCycle(self, cycle): 
    self.cycle = cycle 
    self.trayData = (self.cycle, 
       self.cell, 
       self.bIsTilted, 
       self.bSendNoData) 

Или вы можете определить trayData как свойство вместо определения его в методе __init__(), пример -

class Tray(object): 
    ''' 
    A class used to collect information about each unique tray 
    ''' 
    @property 
    def trayData(self): 
     return (self.cycle, self.cell, self.bIsTilted, self.bSendNoData) 
    . 
    . 
    . #rest of the class. 

Затем вы можете получить доступ к trayData с помощью Tray().trayData, используя объект класса Tray.

Пример/Demo -

In [94]: class Tray(object): 
    ....:  @property 
    ....:  def trayData(self): 
    ....:   return (1,2,3,4) 
    ....: 

In [95]: t=Tray() 

In [96]: t.trayData 
Out[96]: (1, 2, 3, 4) 
1

Переменные Python не обновляются, как вы пытаетесь сделать. Вы должны были бы сделать что-то вроде этого:

def __init__(self): 
    self.cycle = None 
    self.cell = None 
    self.bIsTilted = False # Assume trays are not tilted 
    self.bSendNoData = False # Assume data is sent, modified later if data not sent 
    self.trayData = (self.cycle, 
        self.cell, 
        self.bIsTilted, 
        self.bSendNoData) 

def __repr__(self): 
    return str(self.trayData) 

def setCycle(self, cycle): 
    self.cycle = cycle 
    self.trayData = (self.cycle, 
        self.cell, 
        self.bIsTilted, 
        self.bSendNoData) 

def setCell(self, cell): 
    self.cell = cell 
    self.trayData = (self.cycle, 
        self.cell, 
        self.bIsTilted, 
        self.bSendNoData) 

В принципе, если вы хотите self.trayData иметь самые последние данные, вам необходимо обновить его в любое время, когда вы обновляете в значениях в нем.

Теперь, если вам не нужно, чтобы когда-либо получить доступ к self.trayData напрямую, вы можете просто сделать:

def __repr__(self): 
    return (self.cycle, self.cell, self.bIsTilted, self.bSendNoData) 
+0

Мне это кажется странным. Не является ли переменная 'self.cycle' в моем методе setCycle() такой же, как' self.cycle' в моем методе __init __()? – Asif

+0

@Asif Это так, но когда вы делаете 'foo = bar',' foo' просто получает значение 'bar' во время назначения. Он не продолжает указывать на «bar». –

+0

Это моя борьба при попытке работать на C++ и python одновременно. Я забываю, как переменные работают на каждом языке:/ – Asif

3

При установке trayData в __init__ он не получает обновляется каждый раз, когда другие функции называются. Было бы больше смысла, чтобы сделать его метод класса, который возвращает значение:

def trayData(): 
    return (self.cycle, self.cell, self.bIsTilted, self.bSendNoData) 
+5

Еще лучше, используйте декоратор '@ property'. –

+0

@ DanielRoseman, если вы используете декоратор '@ property' в этом случае. вам нужно установить для него сеттер? –

+1

@ HalcyonAbrahamRamirez нет, потому что вы вообще не будете устанавливать traydata; это свойство только для чтения, которое объединяет другие свойства. –

Смежные вопросы