Область применения, используя функции в текущем модуле - PullRequest
1 голос
/ 29 мая 2009

Я знаю, что это, должно быть, тривиальный вопрос, но я пробовал много разных способов и немного искал решение, но как мне создать и ссылаться на подфункции в текущем модуле?

Например, я пишу программу для анализа текстового файла, и для каждого из 300 различных имен в нем я хочу назначить категорию.

Их 300, и у меня есть список этих структур для создания диктата, поэтому в форме поиска [ключ] = значение (бонусный вопрос; есть ли более эффективный или разумный способ сделать это, чем массивный дикт? ).

Я хотел бы сохранить все это в одном модуле, но с функциями (инициализация dict и т. Д.) На конец файла, поэтому мне не нужно прокручивать вниз 300 строк, чтобы увидеть код, т. е. как показано в примере ниже.

Когда я запускаю его, как показано ниже, я получаю ошибку «initlookups не определен». Когда структура такова, что это инициализация, определение функции, использование функции, без проблем.

Я уверен, что должен быть очевидный способ инициализации функций и связанного с ними dict, не сохраняя код встроенным, но до сих пор пытался довольно много без успеха. Я могу поместить его во внешний модуль и импортировать его, но для простоты предпочел бы.

Что я должен делать с точки зрения структуры модуля? Есть ли лучший способ, чем использовать 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 ]

5 голосов
/ 29 мая 2009

Функция должна быть определена, прежде чем ее можно будет вызвать. Если вы хотите иметь код, который должен быть выполнен в верхней части файла, просто определите функцию main и вызовите ее снизу:

import sys

def main(args):
    pass

# All your other function definitions here

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

Таким образом, все, на что вы ссылаетесь в main, будет проанализировано и, следовательно, уже известно. Причина проверки __name__ заключается в том, что таким образом метод main будет запускаться только при непосредственном выполнении сценария, а не при его импорте из другого файла.


Примечание: dict с 300 ключами отнюдь не массивен, но вы можете либо переместить код, заполняющий dict, в отдельный модуль, либо (возможно, более необычно) сохранить ключ / значение пары в формате, подобном JSON , и загружайте его при запуске программы.

1 голос
/ 29 мая 2009

Вот более питонские способы сделать это. Кстати, вариантов не так много.

Функция должна быть определена , прежде чем ее можно будет использовать . Период.

Однако вам не нужно строго упорядочивать все функции для удобства компилятора. Вам просто нужно поставить выполнение ваших функций последним.

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 уровня модуля, который создается по умолчанию. Даже в этом случае убедитесь, что загадочный объект, который заставляет работать модуль, четко определен в документации.

0 голосов
/ 01 июня 2009

Я думаю, что сохранение имен в виде простого текстового файла и загрузка их во время выполнения было бы хорошей альтернативой. Я стараюсь придерживаться своих данных на самом низком уровне сложности, начиная с простого текста и заканчивая RDMS (я поднял эту идею с Прагматический программист ).

Словари очень эффективны в питоне. По сути, это то, на чем построен весь язык. 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])
0 голосов
/ 29 мая 2009

Если ваш запрос поиска неизменен, самый простой способ - просто сделать его переменной области видимости модуля. то есть:

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

Если вам может потребоваться внести изменения, а затем повторно инициализировать их, вы можете сделать это в функции инициализации:

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

(Либо lookup.update ({'A': 'AA', ...}), чтобы изменить диктовку на месте, затрагивая всех абонентов, имеющих доступ к старой привязке.)

Однако, если у вас есть эти поиски в каком-то стандартном формате, может быть проще просто загрузить их из файла и создать из него словарь.

Вы можете организовать свои функции по своему желанию. Единственное правило в отношении упорядочения состоит в том, что переменные, к которым осуществляется доступ, должны существовать в то время, когда функция называется - хорошо, если функция имеет ссылки на переменные в теле, которые еще не существуют, если на самом деле ничего нет пытается использовать эту функцию. то есть:

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, "")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...