简体   繁体   English

Python类属性与全局变量

[英]Python class attributes vs global variable

I have defined an attribute(yYEAR) within a class and use a global variable(YEAR) to initialize it. 我在一个类中定义了一个属性(yYEAR),并使用一个全局变量(YEAR)对其进行了初始化。 When I called the method within the class it is updating the global variable, even if I didn't assign any value to it. 当我在类中调用该方法时,即使没有给它分配任何值,它也会更新全局变量。 Why is it happening like this?. 为什么会这样发生? Is the error is to do some with the incorrect location of definition of the class variable. 错误是用类变量的定义的不正确位置来做的。

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

Your YEAR is a list type. 您的YEAR是一种列表类型。 Python's lists are mutable. Python的列表是可变的。 Spelling it in all caps means that it should not be changed once set (a "constant"), but this is just a convention not enforced by Python at all. 将其全部大写会意味着它一旦设置就不应更改(“常量”),但这只是Python完全不执行的约定。

If you want a separate copy that you can change instead of a reference to the global, do 如果您想要一个可以更改的单独副本,而不是对全局变量的引用,请执行
yYEAR = YEAR[:] instead. yYEAR = YEAR[:]代替。 Then the copy will belong to the class. 然后副本将属于该类。

The [:] is slice notation that just copies the whole thing because you didn't specify bounds. [:]是切片符号,因为您没有指定边界,所以它仅复制整个内容。
yYEAR = YEAR.copy() would also work, but the former is more conventional in the case of lists. yYEAR = YEAR.copy()也可以,但是对于列表,前者更为常规。

If you want a per-instance copy, set the attribute inside __init__ instead, like 如果__init__实例复制,请在__init__内设置属性,例如
self.yYEAR = YEAR[:] . self.yYEAR = YEAR[:] Really, you could spell it as self.year . 确实,您可以将其拼写为self.year That would be more pythonic. 那会更pythonic。

You can code your constants a little more defensively to protect yourself from accidental mutation by using an immutable tuple instead of a list. 您可以使用不可变的元组而不是列表来防御性地编码常量,以保护自己免受意外突变的影响。 Then you would make your local list from it like yYear = [*YEAR] or if you're still using an old version of Python, yYear = list(YEAR) works too. 然后,您可以从中创建本地列表,例如yYear = [*YEAR]或者如果您仍在使用旧版本的Python,则yYear = list(YEAR)也可以。 But beware that immutable tuples can still contain mutable elements, so this doesn't completely enforce const correctness either. 但是要注意,不可变的元组仍然可以包含可变元素,因此这也不会完全强制执行const正确性。


Note also that syntax like APR=JUN=SEP=NOV=[0]*30 means that all four of those months will have a reference to the same list object. 还要注意,类似APR=JUN=SEP=NOV=[0]*30语法意味着这四个月中的所有月份都将引用同一列表对象。

The error was due to the python mutable lists as "glitch" mentioned. 该错误是由于提到了“小故障”的python可变列表造成的。 However the copying the list using [:] or .copy() does not work in this case as the original list is 2D. 但是,使用[:].copy()复制列表在这种情况下不起作用,因为原始列表是2D。

Making a deepcopy of the 2D list fixed the problem. 对2D列表进行深拷贝可解决此问题。

import copy

and making a per instance deepcopy using deepcopy() 并使用deepcopy()将每个实例制作成deepcopy()

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM