范围,使用当前模块中的功能

时间:2009-05-29 08:58:05

标签: python function scope module structure

我知道这一定是一个微不足道的问题,但我尝试了很多不同的方法,并且搜索了一些解决方案,但是如何在当前模块中创建和引用子功能呢?

例如,我正在编写一个程序来解析文本文件,对于其中的300个不同名称中的每一个,我想分配一个类别。

其中有300个,我有一个这样的结构列表来创建一个字典,所以形式查找[key] =值(奖金问题;任何更有效或明智的方式来做这个比一个大规模的字典? )。

我想将所有这些保留在同一个模块中,但是在函数中使用函数(dict初始化等) 文件的结尾,所以我不必向下滚动300行来查看代码,即如下例所示。

当我按如下方式运行时,我收到错误'initlookups is not defined'。当我的结构是初始化时,那么函数定义,然后函数使用,没问题。

我确信必须有一种明显的方法来初始化函数和相关的字典而不保持代码内联,但到目前为止已经尝试了很多但没有成功。我可以把它放在一个外部模块中并导入它,但是为了简单起见,我宁愿不这样做。

我应该在模块结构方面做些什么?有没有比使用dict存储此查找表更好的方法(300个唯一的文本键映射到大约10个类别?

谢谢,

布兰登


import ..... (initialisation code,etc )

initLookups()          # **Should create the dict - How should this be referenced?**
print getlookup(KEY)   # **How should this be referenced?**


def initLookups():
    global lookup
    lookup={}
    lookup["A"]="AA"
    lookup["B"]="BB"
    (etc etc etc....)


def getlookup(value)
    if name in lookup.keys():
        getlookup=lookup[name]
    else:
        getlookup=""

    return getlookup

4 个答案:

答案 0 :(得分:5)

在调用函数之前需要定义函数。如果您想要在文件顶部执行需要执行的代码,只需定义main函数并从底部调用它:

import sys

def main(args):
    pass

# All your other function definitions here

if __name__ == '__main__':
    exit(main(sys.argv[1:]))

这样,无论你在main中引用的是什么都将被解析,因此已经知道了。测试__name__的原因是,这样main方法只会在脚本直接执行时运行,而不是在由另一个文件导入时运行。


旁注:带有300个密钥的dict绝不是很大,但您可能想要将填充dict的代码移动到单独的模块,或者(可能更花哨)商店类似JSON的格式的键/值对,并在程序启动时加载它。

答案 1 :(得分:1)

这是一种更加pythonic的方式来做到这一点。 BTW没有太多选择。

使用之前,必须定义函数。期。

但是,您不必严格订购所有函数以获得编译器的好处。你只需要执行最后的函数。

import # (initialisation code,etc )

def initLookups(): # Definitions must come before actual use
    lookup={}
    lookup["A"]="AA"
    lookup["B"]="BB"
    (etc etc etc....)
    return lookup

# Any functions initLookups uses, can be define here.
# As long as they're findable in the same module.

if __name__ == "__main__": # Use comes last
    lookup= initLookups() 
    print lookup.get("Key","")

请注意,您不需要getlookup函数,它是dict的内置功能,名为get

此外,“初始化代码”是可疑的。导入不应该“做”任何事情。它应该定义函数和类,但实际上不提供任何可执行代码。从长远来看,导入处理的可执行代码可能会成为维护的噩梦。

最值得注意的例外是默认情况下创建的模块级Singleton对象。即使这样,也要确保在文档中清楚地识别出使模块工作的神秘对象。

答案 2 :(得分:0)

如果你的查找字典是不变的,最简单的方法就是让它成为一个模块范围变量。即:

lookup = {
    'A' : 'AA',
    'B' : 'BB',
    ...
}

如果您可能需要进行更改,稍后重新初始化,则可以在初始化功能中执行此操作:

def initLookups():
    global lookup
    lookup = {
        'A' : 'AA',
        'B' : 'BB',
        ...
    }

(或者,lookup.update({'A':'AA',...})来就地更改dict,影响所有可以访问旧绑定的调用者。)

但是,如果您已经以某种标准格式进行了这些查找,那么简单地从文件中加载它并从中创建字典可能会更简单。

您可以根据需要安排自己的功能。关于排序的唯一规则是被访问的变量必须在函数被称为时存在 - 如果函数引用了身体中尚不存在的变量,那就没关系了,只要没有实际上尝试使用该功能。即:

def foo():
    print greeting, "World"  # Note that greeting is not yet defined when foo() is created

greeting = "Hello"

foo() # Prints "Hello World"

可是:

def foo():
    print greeting, "World"

foo()              # Gives an error - greeting not yet defined.
greeting = "Hello"

还有一点需要注意:你的getlookup函数非常低效。使用“if name in lookup.keys()”实际上是从dict获取键的列表,然后迭代此列表以查找该项。这会损失dict给出的所有性能优势。相反,“if name in lookup”会避免这种情况,甚至更好地使用.get如果密钥不在字典中则可以返回默认值的事实:

def getlookup(name)
    return lookup.get(name, "")

答案 3 :(得分:0)

我认为将名称保存在平面文本文件中,并在运行时加载它们将是一个不错的选择。我尝试用我的数据坚持最低级别的复杂性,从纯文本开始到RDMS(我从The Pragmatic Programmer提出了这个想法)。

字典在python中非常有效。它本质上是整个语言的基础。 300个项目完全在合理的字典使用范围内。

names.txt中:

A = AAA
B = BBB
C = CCC

getname.py:

import sys

FILENAME = "names.txt"

def main(key):
    pairs = (line.split("=") for line in open(FILENAME))
    names = dict((x.strip(), y.strip()) for x,y in pairs)
    return names.get(key, "Not found")

if __name__ == "__main__":
    print main(sys.argv[-1])

如果你真的想出于某种原因将它全部保存在一个模块中,你可以在模块的顶部粘贴一个字符串。我认为,大量的文本比dict初始化代码的大量混乱更容易分散注意力(以后更容易编辑):

import sys

LINES = """
A = AAA
B = BBB
C = CCC
D = DDD
E = EEE""".strip().splitlines()

PAIRS = (line.split("=") for line in LINES)
NAMES = dict((x.strip(), y.strip()) for x,y in PAIRS)

def main(key):
    return NAMES.get(key, "Not found")

if __name__ == "__main__":
    print main(sys.argv[-1])