对init中对象的python引用会在memberfunction

时间:2018-01-25 13:28:52

标签: python python-3.x class

我是非常非常新的编码(在python之前没有其他语言),这是我正在处理的第一个大项目,我遇到了一个错误,我希望你能帮助我理解。我正在使用python 3.43

我在这个网站和互联网上搜索了这个答案,但只发现了一个模糊的暗示,也许我的进口可能是问题所在。 使用类似的设置重现我的程序文件之外的错误是不成功的,所以它必须与我错误的代码结构相关。

这是我的koreanwar类,它应该引用另一个模块的一个countryclass实例,它包含一些数字。我的koreanwar类的start事件成员函数应该编辑该特定实例的数字。

我通过get_country_by_name函数从包含许多此类国家/地区实例的字典中提取实例。 字典应该不是问题,如果我尝试使用列表并遍历所有国家来提取它,我会得到同样的错误。

现在的代码似乎在 init 的结尾和start_event的开头之间创建了一个阴影变量,因为内存地址与 init 和self.korea,我所做的任何更改都不会显示在原始对象上。

class KoreanWar(WarCard):
    def __init__(self):
        super().__init__()
        self.korea = countries.countrymodel.get_country_by_name('South Korea')
        print('init',self.korea)


    def start_event(self):
        print('start_event',self.korea)
        self.korea.influence_west = 9

        print('self.korea.influence_west_start_event ' + str(self.korea.influence_west))
        print('self.korea.influence_west_original ' + str(countries.countrymodel.get_country_by_name('South Korea').influence_west))            

这是我得到的输出,我希望所有值都相同:

init <countries.countrymodel.CountryModel object at 0x0000000002F6B6D8>
start_event <countries.countrymodel.CountryModel object at 0x0000000002F74400>
self.korea.influence_west_start_event 9
self.korea.influence_west_original 1

更晦涩的是,当我在引用它之后在 init 中编辑self.korea时,它正在编辑正确的对象,如果我打印内存地址则是正确的。 因此,在 init 的结尾与start_event的第一行之间发生了神奇的事情,这会导致创建卷影副本,然后将其用于start_event。

我可以通过将self.korea引用移动到成员函数本身来修复错误,但是我想理解为什么这会修复错误以及我如何创建这样的混乱,因为在我的特定代码结构之外我可以只需在init中执行它,没有任何错误。

class KoreanWar(WarCard):
    def __init__(self):
        super().__init__()

    def start_event(self):

        self.korea = countries.countrymodel.get_country_by_name('South Korea')    
        self.korea.influence_west = 9

继承似乎是无关的,我没有尝试,仍然得到相同的错误。 我严格使用导入:

xy = folder, z module
a, b, c = functions, classes, lists/dictionaries
import xy.z
import xy
from xy.z import a, b, c

countries是我存储countrymodel.py的文件夹。 countrymodel是countrymodel.py文件,我存储了我的CountryModel类。

countrymodel.py

此处没有相关导入,该类从硬盘驱动器获取.txt文件并填写memberattributes

class CountryModel:
    def __init__(self, fileName):

        self.connected_country_object_list = []
        country_file = fileName
        file = open(country_file, 'r')
        lines = file.readlines()

        for line in lines:
            lineList = line.strip('\n').split('=')
            attrName = lineList[0]
            attrValue = lineList[1]
            if attrValue.isdigit():
                attrValue = int(attrValue)
            if attrName == "current_influence_west":
                attrName = "influence_west"
            setattr(self, attrName, attrValue)

country_dict = {}

def get_country_by_name(name):
    return country_dict[name]

def create_country_dict():
    global country_dict
    keys = []
    values = []
    for country_model in country_models:
       keys.append(country_model.name)
       values.append(country_model) 
       country_dict = dict(zip(keys, values))

在我的初始化模块中,我实际上遍历所有可能的国家并实例化它们并将它们保存到country_models-list。

initialization.py

from countries.countrymodel import CountryModel, country_models, create_country_dict

def collect_countries():
    for file in os.listdir(paths.PATH_COUNTRIES): # iterate over all possible countryfiles
        if file.endswith(".txt"): 
            country_model = CountryModel(filename)
            country_models.append(country_model)

    create_country_dict()

更新: 找到答案的暗示。我通过复制完整的countryobject在计算机之间通过网络发送这些countryobjects(例如参考self.korea)。这个过程似乎为countryobject引用创建了一个新的内存地址,因此如果self.korea = xxx在init中,它在开始时只连接一次到该国家的初始内存地址,并且不会更新它在替换country对象之后,因此指向空的或过时的内存地址。 如果self.korea引用位于init之外,则每次为countryobject写入新的内存地址后,它将连接到正确的内存地址,因为它只会在之后和每次激活时创建引用。 这也解释了为什么我无法在一台计算机上使用更简单的版本重现该问题,因为我不会通过我的网络代码更改内存地址。

0 个答案:

没有答案