Python类属性与全局变量

时间:2018-11-03 01:09:50

标签: python class

我已经在一个类中定义了一个属性(yYEAR),并使用一个全局变量(YEAR)对其进行了初始化。 当我在类中调用该方法时,即使没有给它分配任何值,它也会更新全局变量。 为什么会这样发生? 错误是使用类变量的定义的不正确位置来完成的。

JAN = MAR =MAY =JUL =AUG= OCT =DEC=[0]*31
APR=JUN=SEP=NOV=[0]*30
FEB=[0]*28

YEAR = [JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC]

class load:
    yYEAR=YEAR
    def __init__(self, DURATION, LTYPE):
        self.DURATION=DURATION
        self.LTYPE= LTYPE


    def daily247(self):
        if self.LTYPE==1 :
            for month in range(len(self.yYEAR)):
                for day in range(len(self.yYEAR[month])):
                    self.yYEAR[month][day]= 1
            else:
                self.yYEAR= YEAR
        self.dispLoad()     

    def dispLoad(self):
        print(self.yYEAR[0])
        print(self.yYEAR[1])

event1= load(10,1)
event1.daily247() # Expected result ones in all nested elements in YEAR

event2= load(10,0)
event2.daily247()  # Expected result zeros in all nested elements in YEAR
print(YEAR[1])  # expected result is to have zeros for all elements

2 个答案:

答案 0 :(得分:2)

您的YEAR是列表类型。 Python的列表是可变的。将其全部大写会意味着它一旦设置就不应更改(“常量”),但这只是Python完全不实施的约定。

如果您想要一个可以更改的单独副本,而不是对全局变量的引用,请执行
改为yYEAR = YEAR[:]。然后副本将属于该类。

[:]是切片符号,因为您没有指定边界,所以它仅复制整个内容。
yYEAR = YEAR.copy()也可以,但是在列表的情况下,前者更为常规。

如果要按实例复制,请在__init__内设置属性,例如
self.yYEAR = YEAR[:]。确实,您可以将其拼写为self.year。那会更pythonic。

您可以使用不可变的元组而不是列表来防御性地编码常量,以保护自己免受意外突变的影响。然后,您可以从中创建本地列表,例如yYear = [*YEAR],或者如果您仍在使用旧版本的Python,yYear = list(YEAR)也可以使用。但是请注意,不可变的元组仍然可以包含可变元素,因此也不会完全强制执行const正确性。


还请注意,像APR=JUN=SEP=NOV=[0]*30这样的语法意味着这四个月中的所有月份都将引用同一列表对象。

答案 1 :(得分:0)

该错误是由于提到的Python可变列表“ glitch”造成的。但是,使用[:].copy()复制列表在这种情况下不起作用,因为原始列表是2D。

对2D列表进行深度复制可以解决此问题。

import copy

并使用deepcopy()

对每个实例进行深度复制
class load:
    def __init__(self, DURATION, LTYPE):
        self.DURATION=DURATION
        self.LTYPE= LTYPE
        self.yYEAR = copy.deepcopy(YEAR)