【问题标题】:Pass Variable to Self-Written Module on Import?在导入时将变量传递给自写模块?
【发布时间】:2018-10-16 22:54:41
【问题描述】:

我想将一些设置导入我当前的脚本,包含一个名为 settings.py 的外部模块。

目前,我在导入之前手动更改了“动物”变量。

settings.py

animal='Unicorn' #I want to get rid of this line, and pass the variable during the import.

if animal=='Unicorn':
        fur_color='sparkles'
        number_of_legs=4

if animal=='Centipede':
    fur_color='black'
    number_of_legs=100

if animal =='Cat':
    fur_color='brown'
    number_of_legs=4

我跑:

from settings import fur_color, number_of_legs

并获得所需的信息。

但是,我现在需要遍历这 3 个案例。我不能这样做,因为在我当前的设置中,我必须在导入之前手动更改“动物”变量。

如何将动物传递到设置中,以便我可以编写如下内容:

for animal in animals:
    from settings import *
    print('A' + animal + ' has ' + str(number_of_legs) + ' and is ' + fur_color)

期望的输出是:

A Unicorn has 4 legs and is sparkles
A Centipede has 100 legs and is black
A Cat has 4 legs and is brown.

循环内的“导入”不会更新设置,也不会使用 imp.reload(settings)。我不知道在这里做什么。显然,实际用例更复杂。我真的希望我没有以这种方式逐个案例变量存储案例!

【问题讨论】:

  • 即使同一个模块有多个import 语句,模块也只会导入一次。你有什么理由不想把它变成settings.get_animal('unicorn')
  • @Andreas Deak,这可能就是我一直在寻找的!您能否详细说明答案?我如何在现有的 settings.py 中构建类似“get_animal”的东西?

标签: python pandas python-import python-module


【解决方案1】:

这最好通过调用外部模块中的函数来完成。可以这样做:

settings.py:

def animal_info(animal):
    if animal=='Unicorn':
        fur_color='sparkles'
        number_of_legs=4
    elif animal=='Centipede':
        fur_color='black'
        number_of_legs=100
    elif animal =='Cat':
        fur_color='brown'
        number_of_legs=4
    return fur_color, number_of_legs

然后,在你的主模块或交互式提示中,你可以使用这个:

import settings
for animal in animals:
    fur_color, number_of_legs = settings.animal_info(animal)
    print('A' + animal + ' has ' + str(number_of_legs) + ' and is ' + fur_color)

如果您正在处理比这更大的数据表,那么您可能需要考虑使用 pandas 数据框。只需将您的数据存储在逗号分隔或制表符分隔的文本文件中,然后使用df = pandas.read_csv(....) 将其读入,根据您的查找列设置索引,然后访问df.loc[animal, “number of legs”] 之类的数据。

【讨论】:

  • 关于 pandas 的 blib 只是不必要的复杂化。标准库中有许多更适合用例的序列化模块,包括一个完全可用的 csv 模块。无论如何,人们使用 settings.py 文件的原因是设置文件可以包含逻辑,而 csv/pandas 无论如何也无法真正解决。
  • 为了回应 EHB 对已接受答案的评论,添加了关于 pandas 的部分,他们认为解压一长串变量名是不雅的,并表示它们有一个二元素索引。通过扩展,从 .py 文件生成所有这些数据是不优雅的。这么多数据可能应该在一个文本文件中,然后 pandas 是一种访问它的简单方法。 Python 的 csv.DictReader 可以做到这一点,但您需要跟进额外的代码来将行转换为字典的字典以进行高效搜索。使用 pandas 更容易,它就是为此而生的。
  • @MathiasFripp:所以安装 pandas,它有数千行你永远不会使用的代码,并添加你不感兴趣的依赖项,包括可能需要安装 C 编译器的 numpy以及对系统库的依赖。所有这些,您可以节省一行字典理解 ({(row["animal"], row["number of legs"]): row for row in csv.DictReader(csvfile)})?你有一种奇怪的方式来定义“更容易”。
【解决方案2】:

模块只导入一次,即使同一模块有后续导入。这意味着我不希望有一种简单的方法可以使用您当前的设置。

我建议在settings 中定义一个函数,它将根据其字符串输入生成您想要的配置:

def get_animal(kind):
    if kind == 'Unicorn':
        fur_color = 'sparkles'
        number_of_legs = 4
    elif kind == 'Centipede':
        fur_color = 'black'
        number_of_legs = 100
    elif kind == 'Cat':
        fur_color = 'brown'
        number_of_legs = 4
    else:
        raise ValueError(f'Invalid animal {kind}!')
    #return dict(fur_color=fur_color, number_of_legs=number_of_legs)
    # or
    return fur_color, number_of_legs

那么就可以得到对应的dict为

from settings import get_animal
for animal in animals:
    animal_dict = get_animal(animal)
    # animal_dict['fur_color'] etc. can be accessed
    print('A {animal} has {number_of_legs} legs and is {fur_color}'.format(
         animal=animal, **animal_dict))

当然,如果您的用例不太适合使用 dict,您可以使用元组返回值定义函数,然后将其解包:

from settings import get_animal
for animal in animals:
    fur_color,number_of_legs = get_animal(animal)
    # do complicated stuff here

【讨论】:

  • 您能否建议一种更优雅的方式来解开我在其中定义的 12 个变量?这是一个非常长且丑陋的单行:base_path, data_columns, general_data_columns, out_date_format, precip_columns, precip_gage_change, primary_temp_column, temp_columns, timezone, wind_col, wind_dir_columns=settings.get_settings(Glacier, Station)。我认为这是您建议的字典选项?
  • @EHB 好吧,您始终可以将该元组绑定到临时名称并通过索引访问每个项目,例如 base_path = settings_tuple[0]; data_columns = settings_tuple[1] 等。但我首先想到 dict 的原因是我怀疑你有很多这些变量。您可以接受自己的命运并使用这种长解包(可能在行尾使用 `` 来显式续行),或者将它们全部保存在字典中并按名称访问项目(最好使用短名称字典和短名称的键...)。我不确定是否有更好的选择。
猜你喜欢
  • 1970-01-01
  • 2021-12-01
  • 1970-01-01
  • 2018-09-07
  • 1970-01-01
  • 2017-05-15
  • 2015-01-27
  • 2014-01-05
  • 2019-04-10
相关资源
最近更新 更多