跨模块使用变量的最佳方法? (Python3)

时间:2017-03-21 18:59:18

标签: python python-3.x

我试图将程序中的各种功能分开,以保持整洁。而且我试图在另一个模块中使用在一个模块中创建的变量时遇到困难。我尝试使用global list_of_names,但它不起作用,而且我已经读过它建议不要这样做。

以下是我的代码示例。在我看来,将list_of_names作为函数参数传递是没有意义的,因为除了实际传递的参数之外,我还需要执行多个其他变量。

不幸的是,即使我将read_json移到engine.py中,我仍然在main.py中遇到同样的问题,因为我需要在那里引用list_of_names。< / p>

# main.py:
import json
from engine import create_person
def read_json():
    with open('names.json', 'r') as file
        data = json.load(file)
    return data
list_of_names = read_json()
person1 = create_person()

# engine.py:
from random import choice
def create_person():
    name = choice(list_of_names)
    new_person = {
        'name': name,
        # other keys/values created in similar fashion
    }
    return new_person

EDIT1: 这是我的新代码。对我来说,构建参数列表然后在函数内解构它似乎并不高效。 (我知道我在这个例子中重复使用变量名称)然后我必须将其中一些参数传递给其他函数。

# main.py:
import json
from engine import create_person
def read_json():
    with open('names.json', 'r') as file
        data = json.load(file)
    return data

player_id_index = 0
list_of_names = read_json()
person_parameters = [
    list_of_names,
    dict_of_locations,
    player_id_index,
    dict_of_occupations,
    .
    .
    .
]

person1, player_id_index = create_person()

# engine.py:
from random import choice
def create_person(person_params):
    list_of_names = person_params[0]
    dict_of_locations = person_params[1]
    player_id_index = person_params[2]
    dict_of_occupations = person_params[3]
    .
    .
    .
    attr = person_params[n]

    name = choice(list_of_names)
    location = get_location(dict_of_locations) # a function elsewhere in engine.py
    p_id = player_id_index
    occupation = get_occupation(dict_of_occupations) # a function elsewhere in engine.py

    new_person = {
        'name': name,
        'hometown': location,
        'player id': p_id,
        'occupation': occupation,
        .
        .
        .
    }

    player_id_index += 1
    return new_person, player_id_index

1 个答案:

答案 0 :(得分:2)

一般而言,您不应该依赖共享的全局状态。如果你需要共享状态封装对象中的状态或作为函数参数传递。

关于您的具体问题,您似乎希望从一组选项中组合随机词典。它可以这样编码:

from random import choice

person_options = {
   'name': ['fred', 'mary', 'john', 'sarah', 'abigail', 'steve'],
   'health': [6, 8, 12, 15],
   'weapon': ['sword', 'bow'],
   'armor': ['naked', 'leather', 'iron']
}

def create_person(person_options):
    return {k:choice(opts) for k, opts in person_options.items()}

for _ in range(4):
    print create_person(person_options)

行动中:

>>> for _ in range(4):
...     print(create_person(person_options))
...
{'armor': 'naked', 'weapon': 'bow', 'health': 15, 'name': 'steve'}
{'armor': 'iron', 'weapon': 'sword', 'health': 8, 'name': 'fred'}
{'armor': 'iron', 'weapon': 'sword', 'health': 6, 'name': 'john'}
{'armor': 'iron', 'weapon': 'sword', 'health': 12, 'name': 'john'}

请注意,像{'armor': 'naked', 'weapon': 'bow', 'health': 15, 'name': 'steve'}这样的字典看起来可能想成为一个对象。字典是一个没有任何已定义行为的状态。如果你创建一个类来容纳这个状态,那么类可以生成对该状态起作用的方法。当然,解释所有这些可能会使这个答案真的很长。就目前而言,只要意识到你应该放弃拥有任何旧代码可能会混乱的共享状态。对此进行一些约束将使您的代码在以后更容易重构。

这解决了您编辑过的问题:

from random import choice
from itertools import count
from functools import partial

person_options = {
   'name': partial(
         choice, ['fred', 'mary', 'john', 'sarah', 'abigail', 'steve']),
   'location': partial(
         get_location, {'heaven':1, 'hell':2, 'earth':3}),
   'player id': count(1).next
}

def create_person(person_options):
    return {k:func() for k, func in person_options.items()}

但是,我们现在超出了原始问题的范围,并且进入对您以外的任何人都没有帮助的细节。 Code Review Stack Exchange

更好地询问了这些问题