Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用JSON文件中的值初始化多个类似乎会创建重复项_Json_Python 3.x_Class - Fatal编程技术网

使用JSON文件中的值初始化多个类似乎会创建重复项

使用JSON文件中的值初始化多个类似乎会创建重复项,json,python-3.x,class,Json,Python 3.x,Class,我有一个名为Dense的主类,它有许多变量,还有一个名为Sequential的类,它将这些层堆叠在一个数组中,并允许它们之间轻松通信 在我的程序中的某个时刻,我最终将每个单独的密集类的所有变量保存在一个JSON文件中,供以后使用。它看起来有点像这样: { “层:0”:{ . . . 变量 . . . }, “层:1”:{ . . . 变量 . . . } } 然后,当我将这些dict加载回我的层时,当我稍后使用它们时,Sequential类中最后一层的值似乎会复制到其他每一层 下面是我在重新

我有一个名为Dense的主类,它有许多变量,还有一个名为Sequential的类,它将这些层堆叠在一个数组中,并允许它们之间轻松通信

在我的程序中的某个时刻,我最终将每个单独的密集类的所有变量保存在一个JSON文件中,供以后使用。它看起来有点像这样:


{
“层:0”:{
.
.
.
变量
.
.
.
},
“层:1”:{
.
.
.
变量
.
.
.
}
}
然后,当我将这些dict加载回我的层时,当我稍后使用它们时,Sequential类中最后一层的值似乎会复制到其他每一层

下面是我在重新创建代码方面所能做的最好的工作

从abc导入ABCMeta,abstractmethod
导入操作系统
导入json
类基本层(元类=ABCMeta):
@抽象方法
定义初始化(self,名称:str,**kwargs)->无:
self.name=名称
@抽象方法
def get_摘要(自我)->记录:
返回摘要
@抽象方法
def加载(自身,层_数据:dict)->无:
通过
密实等级(基层):
def uuu init uuuu(自,层形状:元组):
超级()
self.layer\u shape=layer\u shape
def get_摘要(自我):
摘要={
“name”:self.name,
“图层形状”:self.layer\u形状
}
返回摘要
def加载(自身、层_数据):
self.name=图层_数据[“名称”]
self.layer\u shape=元组(layer\u数据[“layer\u shape”])
类顺序:
定义初始化(self,model=[]):
self.model=model
def保存(自身,文件路径):
摘要=[]
对于self.model中的图层:
summaries.append(layer.get\u summary())
保存的_模型={}
对于范围内的i(len(摘要)):
已保存的_模型[“层:%s”%i]={}
对于关键的总结[i]:
已保存的_模型[“层:%s”%i][key]=摘要[i][key]
打开(文件路径,“w+”)作为json文件:
json_file.write(json.dumps(保存的_模型,缩进=2))
def加载(自身,文件路径):
层={
“稠密”:稠密((0,0)),
}
#尝试在文件路径处打开文件。
尝试:
打开(文件路径,“r”)作为json文件:
model_layers=json.loads(json_file.read())
对于范围内的i(len(model_层)):
层\数据=模型\层[“层:%s”%i]
self.model.append(层[layer_data[“name”]])
self.model[-1]。加载(图层数据)
#如果程序找不到文件路径,则调用。
例外情况除外,如e:
raise FileNotFoundError(“找不到文件路径%s。请尝试保存模型或输入正确的文件路径。”%file\u path)
seq_模型=顺序([
稠密的((128784)),
稠密((128128)),
稠密((128128)),
稠密的((32128)),
致密((10,32)),
])
file\u path=os.path.dirname(os.path.realpath(\uu file\uuu))+“/recreate\u error\u test.json”
seq_model.save(文件路径)
seq_model.load(文件路径)
对于seq_model.model中的图层:
打印(图层、图层形状)
这实际上输出: (128, 784) (128, 128) (128, 128) (32, 128) (10, 32) (10, 32) (10, 32) (10, 32) (10, 32) (10、32)

奇怪的是,为什么要打印两次,前7个值是正确的,下7个值显示了我在实际代码中面临的问题


非常感谢您对此问题提供的任何帮助。

问题是重复使用图层[layer_data[“name”]”,这与添加到列表中的参考相同。load()不会重新创建新的稠密对象,而是填充它

这里有一些重载重写函数来查看元素的创建

import copy

(...)



    def load(self, file_path):
        layers = {
                    "Dense":Dense((0, 0)),
                 }

        # Try to open the file at file_path.
        try:
            with open(file_path, "r") as json_file:
                model_layers = json.loads(json_file.read())

                for i in range(len(model_layers)):
                    layer_data = model_layers["layer: %s" % i]
                    print("%s %s" %( i,layer_data["name"]))
                    # OK could be new_layer=Dense((0, 0)) since it recreate a new object
                    new_layer=copy.copy(layers[layer_data["name"]])
                    # NOK same reference is reused
                    # new_layer=layers[layer_data["name"]]
                    new_layer.load(layer_data)
                    self.model.append(new_layer)

        # Gets called if the program can't find the file_path.
        except Exception as e:
            raise FileNotFoundError("Can't find file path %s. Try saving the model or enter a correct file path." % file_path)
这里是另一个使用类名而不需要复制的解决方案:

def load(self, file_path):
    layerclass = {
                "Dense":Dense,
             }

    # Try to open the file at file_path.
    try:
        with open(file_path, "r") as json_file:
            model_layers = json.loads(json_file.read())

            for i in range(len(model_layers)):
                layer_data = model_layers["layer: %s" % i]
                print("%s %s" %( i,layer_data["name"]))
                # requires that all layerclass have a __init__ constructor with layer_shape tuple.
                new_layer=layerclass[layer_data["name"]](layer_shape=(0,0))
                new_layer.load(layer_data)
                self.model.append(new_layer)

    # Gets called if the program can't find the file_path.
    except Exception as e:
        raise FileNotFoundError("Can't find file path %s. Try saving the model or enter a correct file path." % file_path)

“layer:0”{…}不是有效的json内容,“layer:0”:{…}会更正确。@philippelhardy谢谢,我刚刚编辑了这个问题以添加您的更改。self.model.append(layers[layer_data[“name”]])self.model[-1]。load(layer_data)self.model.append(layers[layer_data[“name”]]。load(layer_data)@philippelhardy这样做是为了解决问题,还是仅仅是编写代码的更好方法?self.model.append(层[layer_data[“name”])self.model[-1]。load(layer_data)~=self.model.append(layers[“Dense”].load(layer_data))==>layers[“Dense”]然后是附加到列表中的对象,这是同一个对象。append可能会克隆它,但我认为它并不总是被克隆的,因此会产生副作用。非常感谢,代码是有效的。但是,不幸的是,我不明白这是如何解决问题的,所以我想我必须对python复制库进行一些研究。嗯,你的fir问题是,您将()和load()保存在同一个模型列表中,因此前5个(而不是7个)只是您的输入,下5个是加载的结果。然后所有5个加载的值都指向同一个对象。无需复制,只需创建正确的类实例就足够了