2013-04-20 2 views
0

При импорте из модуля string для использования с функцией синтаксического анализа.UnboundLocalError при использовании модуля внутри функции?

from string import punctuation 


def parsing_func(data): 
    if not any(i==v for i in data for v in punctuation.replace('_', '')): 
     print data 

Использование string «s punctuation как в этой функции выше, все работает отлично.

Я тогда хотел проверить данные против нескольких меньших знаков препинания. Поэтому я изменил parsing_func к этому:

def parsing_func(data): 
    punctuation = punctuation.replace('_', '') 
    punctuation = punctuation.replace('()', '') 
    if not any(i==v for i in data for v in punctuation): 
     print data 

но это возвращает:

Traceback (most recent call last): 
    File "parser.py", line 58, in <module> 
    parsing_func(data) 
    File "ex.py", line 8, in parsing_func 
    punctuation = punctuation.replace('_', '') 
UnboundLocalError: local variable 'punctuation' referenced before assignment 

Итак, я делаю тест функция проверки punctuation:

def test_func1(): 
    print type(punctuation), punctuation 

>>> <type 'str'> !"#$%&'()*+,-./:;<=>[email protected][\]^_`{|}~ 

, которая печатает нормально, нет ошибки и показывает type str. Наконец, я пытаюсь собрать print и операцию строки один за другим.

def test_func2(): 
    print type(punctuation), punctuation 
    punctuation = punctuation.replace('_', '') 

но теперь print оператор возвращает ошибка:

Traceback (most recent call last): 
    File "parser.py", line 9, in <module> 
    test_func2() 
    File "parser.py", line 5, in test_func2 
    print type(punctuation), punctuation 
UnboundLocalError: local variable 'punctuation' referenced before assignment 

Является ли это namespace ошибки и почему test_func2 возвращает ошибку при переходе к печати, а не на строковой операции?

ответ

1

Вы присваивание punctuation внутри вашей функции, так что Python рассматривает его в качестве локальной переменной: поэтому он не использует глобальное имя на всех. Используйте другое имя для назначения.

1

У вас есть как локальные punctuation, так и глобальные punctuation в вашей второй функции. Вы можете переименовать его:

def parsing_func(data): 
    punct = punctuation.replace('_', '') 
    punct = punctuation.replace('()', '') 

    if not any(i == v for i in data for v in punct): 
     print data 

Или сделать punctuation явно глобальный:

def parsing_func(data): 
    global punctuation 

    punctuation = punctuation.replace('_', '') 
    punctuation = punctuation.replace('()', '') 

    if not any(i==v for i in data for v in punctuation): 
     print data 

Обратите внимание, что это изменяет punctuation во всем мире, так что я бы не сделать это.

Вы также можете сделать это с помощью наборов:

def has_punctuation(data): 
    punct = set(punctuation) - set('_()') 

    return punct & set(data) # Intersection of the two sets 
+0

Ваш последний пример предполагает, 'data' не нужны дубликаты или заказ. –

+1

@Lattyware: Он выглядел как только что проверенный код OP, чтобы увидеть, содержит ли строка какие-либо знаки препинания, поэтому я не думаю, что это требует какого-либо заказа. – Blender

+0

Это хороший момент, я не думал об этом как о замене теста. –

1

Проблема в том, что вы пытаетесь назначить глобальное имя - punctuation, которое Python не разрешает, поэтому вместо этого он создает локальную переменную punctuation. На этом этапе он пытается найти вверх punctuation с правой стороны и получает локальную переменную, которая еще не существует.

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

def parsing_func(data): 
    less_punctuation = punctuation.replace('_', '') 
    less_punctuation = less_punctuation.replace('()', '') 
    if not any(i in less_punctuation for i in data): 
     print data 

Стоит также отметить мое использование in для проверки членства - это и более удобным для чтения и быстрее.В общем, членство тесты быстрее на множествах, и с помощью набора, можно также удалить значения в более удобном для восприятия виде:

def parsing_func(data): 
    less_punctuation = set(punctuation) - set("_()") 
    if not any(i in less_punctuation for i in data): 
     print data 
Смежные вопросы