Python类中的奇怪行为

Python类中的奇怪行为,python,python-2.7,oop,Python,Python 2.7,Oop,所以这是不言自明的 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

所以这是不言自明的

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没有根据self.cycle、self.cell等中的值进行更新。这里有什么问题?

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)

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)

当您执行以下操作时-

self.trayData = (self.cycle,
                 self.cell,
                 self.bIsTilted,
                 self.bSendNoData)
self.trayData的第一个元素不指向self.cycle,至少不以您希望的方式指向它,它指向self.cycle指向的对象,该对象为None。因此,当您将新值设置为self.cycle时,它不会自动反映在self.trayData中

要使您的特定案例发挥作用,最简单的方法是在setCycle和setCell方法中设置trayData

范例-

def setCycle(self, cycle):
    self.cycle = cycle
    self.trayData = (self.cycle,
                 self.cell,
                 self.bIsTilted,
                 self.bSendNoData)
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定义为属性,而不是在uuu init_uuu方法中定义它,例如-

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.
然后,可以使用Tray类的对象,使用Tray.trayData访问trayData

示例/演示-

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)

当您执行以下操作时-

self.trayData = (self.cycle,
                 self.cell,
                 self.bIsTilted,
                 self.bSendNoData)
self.trayData的第一个元素不指向self.cycle,至少不以您希望的方式指向它,它指向self.cycle指向的对象,该对象为None。因此,当您将新值设置为self.cycle时,它不会自动反映在self.trayData中

要使您的特定案例发挥作用,最简单的方法是在setCycle和setCell方法中设置trayData

范例-

def setCycle(self, cycle):
    self.cycle = cycle
    self.trayData = (self.cycle,
                 self.cell,
                 self.bIsTilted,
                 self.bSendNoData)
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定义为属性,而不是在uuu init_uuu方法中定义它,例如-

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.
然后,可以使用Tray类的对象,使用Tray.trayData访问trayData

示例/演示-

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)
在uuu init_uuuu中设置trayData时,它不会在每次调用其他函数时都得到更新。将其作为返回值的类的方法更有意义:

def trayData():
    return (self.cycle, self.cell, self.bIsTilted, self.bSendNoData)
在uuu init_uuuu中设置trayData时,它不会在每次调用其他函数时都得到更新。将其作为返回值的类的方法更有意义:

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

我觉得这很奇怪。我的setCycle方法中的self.cycle变量不是与我的u_init__u;方法中的self.cycle相同吗?@Asif是,但是当您执行foo=bar时,foo只在赋值时获取bar的值。它不会继续指向BAR。这是我在尝试同时使用C++和Python时的挣扎。我忘记了变量在每种语言中的工作方式,这对我来说似乎很奇怪。我的setCycle方法中的self.cycle变量不是与我的u_init__u;方法中的self.cycle相同吗?@Asif是,但是当您执行foo=bar时,foo只在赋值时获取bar的值。它不会继续指向BAR。这是我在尝试同时使用C++和Python时的挣扎。我忘记了变量在每种语言中是如何工作的了:/如果在本例中使用@property decorator,最好使用@property decorator@DanielRoseman。你需要为它设置一个设置器吗?@HalcyonAbrahamRamirez不,因为你根本不会设置虚线;它是一个只读属性,可以聚合其他属性。@DanielRoseman这是一个更好的建议。我会编辑我的答案以包含它,但我以前没有使用过decorators,Anand接受的答案已经涵盖了它。如果在这种情况下使用@property decorator,最好使用@property decorator@DanielRoseman。你需要为它设置一个设置器吗?@HalcyonAbrahamRamirez不,因为你根本不会设置虚线;它是一个只读属性,可以聚合其他属性。@DanielRoseman这是一个更好的建议。我会编辑我的答案以包含它,但我以前没有使用过decorators,Anand接受的答案已经涵盖了它;camel case通常是为类名保留的,而不是允许用户简单地设置属性本身的值。但我确实在某个地方读到,由于Python在技术上不允许“private/public”变量,因此它仍然是为您的应用程序编写访问器的正确方法variables@Asif:没有。您只需让最终用户直接修改内容。如果以后需要封装,可以创建类似Anand shows的属性。属性既可以是可读的,也可以是可写的
; 它们查看属性引用,但行为类似于方法,您可以用属性替换属性,而不必破坏假定它直接访问属性的代码;camel case通常是为类名保留的,而不是允许用户简单地设置属性本身的值。但我确实在某个地方读到,由于Python在技术上不允许“private/public”变量,因此它仍然是为您的应用程序编写访问器的正确方法variables@Asif:没有。您只需让最终用户直接修改内容。如果以后需要封装,可以创建类似Anand shows的属性。属性既可以写也可以读;它们查看属性引用,但行为类似于方法,您可以用属性替换属性,而不必破坏假定它直接访问属性的代码。