【问题标题】:Returning a dictionary from a module to main将字典从模块返回到主模块
【发布时间】:2021-02-08 16:28:28
【问题描述】:

如何从模块返回 python 字典?

我包含了我的代码的精简版本。

我有 main.py 运行程序的文件,它从另一个文件 import_gdb.py 导入 *。

from copa_import import *



def get_data(self):
    gdb_path = "<some file path>"
    import_gdb(gdb_path)

在导入的copa_import.py 中,我在import_gdb() 中构建了一个字典。

imports ...
layers = {}

def import_gdb(gdb_path):
    global layers

    try:
        <code to make the dictionary>
        layers = <dictionary>
    except:
        print('failed to make dictionary')
    return layers

我已经分配了一个全局变量,但我认为它只能在模块内本地访问? 我已返回 layers 如何在 main.py 中使用/访问它?

我已经在谷歌上搜索了几天,试图找到一个关于如何做到这一点的明确解释。我可能缺乏一些基本的了解,我欢迎指导。

【问题讨论】:

  • 您通常不需要将global 用于常规的python 任务,并且它不会实现您在此处尝试执行的操作。你可以做import copa_import,你可以通过copa_import.layerscopa_import.import_gdb('my/path)访问函数和层
  • 您不需要将layers 设为全局。您从import_gdb() 退回它。在get_data() 中分配返回值。 returned_layers = import_gdb(gdb_path)
  • 在使用全局变量之前,要知道global variables are evil!
  • 谢谢你,我一直很困惑,现在我可以将我愚蠢的长脚本切割成可重用的模块。谢谢。

标签: python return


【解决方案1】:

您不需要使用全局,如上面的 cmets 概述。使用普通导入应该没问题:

gdb.py

# don't put layers at the global level here and modify its value later!!! WILL cause bugs later
# Make ALL_CAPS if you want it to look like default constant but still don't modify its value

def import_gdb(gdb_path):
    # dummy logic to populate layers
    layers = {
        'layer1': 1,
        'layer2': 2,
        'layer3': 3,
        'layer4': 4,
        'layer5': 5,
    }
    return layers

main.py

import gdb

layers = gdb.import_gdb('my/path')

print(layers)

输出:

{'layer1': 1, 'layer2': 2, 'layer3': 3, 'layer4': 4, 'layer5': 5}

【讨论】:

    【解决方案2】:

    我通常会怎么做我认为你想做的事:

    有人指出,但您尝试做的通常是通过从模块级函数返回字典来完成。

    # simple example
    def import_gdb(gdb_path):
      with open(gdb_path, 'r') as f:
         layers = parse_layers_from_file(f)
      return layers
    

    现在,如果您出于某种原因想要多次调用它并保存该值,则可以将其设置为附加到该类的字典成员的新类的方法。到目前为止,此类类型的对象会以您可能一直在尝试使用全局变量的方式“保存”层。

    # This class would let you access the aggregated dict through layers member, and
    # get new layers from the import gdb method
    class LayerStore:
      def __init__(self):
        self.layers = {}
      
      def import_gdb(self, gdb_path):
        with open(gdb_path, 'r') as f:
          new_layers = parse_layers_from_file(f)
        self.layers.update(new_layers)
        return new_layers
    

    奖励:为什么你所做的似乎不起作用

    让我们稍微简化一下你的 copa_import 文件

    #copa_import.py
    layers = {"foo": "bar"}
    
    def import_gdb(path_to_gdb):
        global layers
        layers = {"bar": "baz"}
        return layers
    

    并使用您的第一个导入方法编写一个主文件,显示该全局发生了什么

    # main_with_star_import.py
    
    from copa_import import *
    
    print("After import")
    print(layers)
    print("Return value from import_gdb")
    print(import_gdb(""))
    print("After running import_gdb")
    print(layers)
    print("Re-import")
    from copa_import import *
    print(layers)
    
    ## Output:
    #After import
    {'foo': 'bar'}
    #Return value from import_gdb
    {'bar': 'baz'}
    #After running import_gdb
    {'foo': 'bar'}
    #Re-import
    {'bar': 'baz'}
    

    注意我们是如何在重新导入模块后才获得更新的全局字典的?这是因为模块本身就是一个命名空间和对象。全局命名空间 = 模块级命名空间。您在上面看到的行为是因为 from module import * 将值写入调用该语句的范围内的命名空间。即使您调用重新分配全局layersimport_gdb 方法,在重新导入copa_import 之前,您也不会看到新值。

    如果我们使用不同类型的导入会怎样?

    # main_with_module_import.py
    import copa_import as c_i
    
    print("After import")
    print(c_i.layers)
    print("Return value from import_gdb")
    print(c_i.import_gdb(""))
    print("After running import_gdb")
    print(c_i.layers)
    print("Re-import")
    from copa_import import *
    print(c_i.layers)
    
    ## Output
    # After import
    {'foo': 'bar'}
    # Return value from import_gdb
    {'bar': 'baz'}
    # After running import_gdb
    {'bar': 'baz'}
    # Re-import
    {'bar': 'baz'}
    

    使用此方法,您必须通过模块对象来访问图层。当您调用 import_gdb 时,模块对象的 layers 变量的值将被覆盖,因此下次访问它时,您将获得新值。

    这说明了为什么使用全局变量可能会让使用/调试代码的人感到困惑,因为不同类型的导入具有不同类型的行为。

    我首先提到的方法(使用类和/或函数)更好,因为变量的范围以及如何访问它们更加清晰。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-10-05
      • 1970-01-01
      • 1970-01-01
      • 2023-03-14
      • 1970-01-01
      • 2016-06-06
      • 2010-09-26
      • 1970-01-01
      相关资源
      最近更新 更多