2016-01-17 5 views
2

Я, наконец, попал в Python и заметил что-то странное, что работает на Java, но не в Python.Определение переменных модуля из функций

Когда я печатаю следующее:

fn = "" # Local filename storage. 

def read(filename): 
    fn = filename 
    return open(filename, 'r').read() 

Мой flake8 ЛИНТЕР для Atom дает мне следующую ошибку:

F841 - local variable 'fn' is assigned to but never used.

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

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

+0

'fn' присваивается, но вместо' fn' код использует 'filename'. Почему вы не используете 'fn'? 'return open (fn, 'r'). read()' – falsetru

+0

@falsetru Я обращаюсь к файловому уровню 'fn' из другого класса. Его хранилище для последующего использования. – finnrayment

+0

Затем вам нужно объявить его глобальным 'global fn' – falsetru

ответ

1

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

import sys 

def read(filename):   
    module = sys.modules[__name__] 
    setattr(module, 'fn', filename) 
    return open(filename, 'r').read() 

Однако, это очень странная необходимость. Подумайте о том, чтобы изменить свою архитектуру.

UPD: Давайте рассмотрим пример:

# module1 
# uncomment it to fix NameError and AttributeError 
# some_var = '' 

def foo(val): 
    global some_var 
    some_var = val 


# module2 
from module1 import * 
print(some_var) # raises NameError: name 'some_var' is not defined 

foo('bar') 
print(some_var) # still raises NameError: name 'some_var' is not defined 


# module3 
import module1 
print(module1.some_var) # raises AttributeError: 'module' object has no attribute 'some_var' 

foo('bar') 
print(module1.some_var) # prints 'bar' even without some_var = '' definition in the module1 

Таким образом, это не так очевидно, как global ведет себя в процессе импорта. Я думаю, что ручное выполнение setattr(module, 'attr_name', value) во время вызова read() более понятно.

+0

В чем ключевое различие между вашим ответом и другим в функциональности и лежащих в основе разработках? – finnrayment

+0

При таком подходе вы можете установить переменную во время выполнения функции 'read' не только для модуля, где он был определен.Между тем, любое выполнение кода во время 'import' приводит к очень плохо проверяемым архитектурам. Попытайтесь избежать этого. Часто во время тестирования вы не можете пропустить импорт, однако вам нужно, чтобы какой-то код был издеваемым/заглушенным. –

+0

И разница между этим и глобальными определениями? – finnrayment

1

Если вы хотите объявить fn как глобальную переменную (уровень модуля), используйте global statement.

def read(filename): 
    global fn # <----- 
    fn = filename 
    return open(filename, 'r').read() 

BTW, ; не является обязательным. Не используйте его.

+0

Хорошо. Я попробую это. BTW, глобализует его из переменной-уровня, импортируя его автоматически при вызове 'from io import *'? – finnrayment

+0

@frayment, да, если вы не определяете '__all__', чтобы вручную его контролировать. См. Https://docs.python.org/2/tutorial/modules.html#importing-from-a-package – falsetru

+1

Чтобы получить доступ к 'fn' из другого модуля после импорта, вам необходимо не только определить его как 'global' в функции' read() ', но также определить его на уровне модуля (например, как' fn = '' '). Без такого определения вы не получите доступ к 'fn' после выполнения' из io import * 'и перед вызовом' read() '. –

Смежные вопросы