[解決済み] グローバル変数がモジュールレベルで未定義である
質問
(似たような、より一般的な質問がたくさんあります。それらを読んだ後、それらの解決策を試していますが、うまくいかないので、私が見ているもののより状況に特化したバージョンとしてここで質問しています)
私はC#/C++のバックグラウンドがあるため、PythonがどのようにOOPを行うのか、本当に誤解していると思います。 そこで、今まさに私がやろうとしていることがあります。
私はプロジェクトの残りの部分をセットアップするために、部分的にサニティチェックと概念実証として、2つのモジュールから始めています。 1つのモジュールは、複数のモジュールからのデータを保存しながら、私が行くときにファイルに物事を記録します(最終的にそれらをすべてパッケージ化し、要求に応じてそれらをダンプする) PyCharmでこれをすべて行い、ところでそれが示唆するエラー警告に言及し、Python 2.7を使用します。
Module 1:
src\helpers\logHelpers.py
class LogHelpers:
class log:
def classEnter():
#doing stuff
def __init__(self):
self.myLog = LogHelpers.log() #forgot to mention this was here initially
[..] various logging functions and variables to summarize what's happening
__builtin__.mylogger = LogHelpers
Module 2:
src\ULTs\myULTs.py
mylogger.myLog.classEnter()
(モジュールとルートsrcの両方が、空の イニット .pyファイル)
ということで、こちらのまったくもって素晴らしい回答によると( Python - インポートモジュールにおけるグローバル変数の可視化 ) この段階ではうまくいくはずなのですが、'mylogger' が '未解決の参照' になってしまうのです。
ということで、一つのアプローチでした。 また、よりストレートなグローバルなものも試してみました ( Pythonです。モジュール横断型変数を作るには? )
Module 1:
src\helpers\logHelpers.py
class LogHelpers:
class log:
def classEnter(self):
#doing stuff
def __init__(self):
self.myLog = LogHelpers.log() #forgot to mention this was here initially
[..] various logging functions and variables to summarize what's happening
mylogger = LogHelpers
__init__.py
__all__ = ['LogHelpers', hexlogger]
from .logHelpers import *
Module 2:
src\ULTs\myULTs.py
from helpers import mylogger
mylogger.myLog.classEnter()
このバージョンでは、classEnter時に "parameter 'self' unfilled" というエラーが発生します。これは、myloggerが初期化されていないことを意味するようです(誤解を招くエラーコードですが、そのような意味のようです)。
そして、こんなことをやってみた。
Module 1:
src\helpers\logHelpers.py
class LogHelpers:
class log:
def classEnter(self):
#doing stuff
def __init__(self):
self.myLog = LogHelpers.log() #forgot to mention this was here initially
[..] various logging functions and variables to summarize what's happening
__mylogger = LogHelpers
__init__.py
__all__ = ['LogHelpers', hexlogger]
from .logHelpers import *
Module 2:
src\ULTs\myULTs.py
from helpers import mylogger
def someFunction(self):
global mylogger
mylogger.myLog.classEnter()
そして、このバージョンでは、グローバルなmyloggerにカーソルを合わせると、「グローバル変数がモジュールレベルで未定義です」というエラーが発生します。
それから、他のモジュールがそれぞれクラスのインスタンスをトラッキングするというアイデアもあります。
それが、私がやろうとしていることの大まかなところなんです...。 私はできるだけ多くの似たような質問を読んでいますが、それらのすべてがこれらの種類の解決策(うまくいっていないようです)に戻ってくるか、または「それをしないでください」と言うようです(これは一般的に良いアドバイスですが、私は大規模プロジェクトのために複数の進行中の非静的クラスを整理しておくための望ましいPythonyの方法を本当に理解していません - それらをすべて一つのディレクトリに押し込む以外の方法です)。
感想は? (私はどれだけPythonを誤解しているのだろう?)
[EDIT] フィードバックに基づき、内部クラスを完全に削除したミニバージョンを試してみました。 OK、では、言われたことに基づいて、ローカルのミニクラスをしてみました。
class testClass:
def __init__(self):
self.testVar = 2
def incrementVar(self):
self.testVar += 1
myClass = testClass()
経由で設定します。 イニット .py
__all__ = [myClass]
from .logHelpers import myClass
他のモジュールに移動して
from helpers import myClass
class Test_LogHelpers(unittest.TestCase):
def test_mini(self):
myClass.incrementVar()
PyCharmを見ずに直接実行しても、Globalは何も出ません...。
NameError: name 'myClass is not defined
というわけで、まだ振り出しです :( そして、まだ状態を保存する必要があります)
[EDIT] トレースバックを追加しました。
Traceback (most recent call last):
File "C:\Program Files (x86)\JetBrains\PyCharm Community Edition 3.4.1\helpers\pycharm\utrunner.py", line 124, in <module> module = loadSource(a[0])
File "C:\Program Files (x86)\JetBrains\PyCharm Community Edition 3.4.1\helpers\pycharm\utrunner.py", line 40, in loadSource module = imp.load_source(moduleName, fileName)
File "C:\[...mylocation...]\py\src\ULTs\LogHelpers_ULT.py", line 3, in <module> from helpers import myClass
File "C:\[...mylocation...]\py\src\helpers\__init__.py", line 7, in <module>
__all__ = [myClass]
NameError: name 'myClass' is not defined
============================================================================
kk、ミニクラスで動くようになったよ。 なぜ他のアプローチ/やり方がうまくいかなかったのかわかりませんが、これで解決したようです。 (リソース http://docs.python-guide.org/en/latest/writing/structure/ , http://mikegrouchy.com/blog/2012/05/be-pythonic-__init__py.html )
**logHelpers.py**
[... some static logging functionality ...]
class testClass:
def __init__(self):
self.testVar = 2
def incrementVar(self, source):
self.testVar += 1
mylogger.myLog.info(source + " called, new val: " + str(self.testVar))
myClass = testClass()
**test_LogHelpers_ULT.py**
import unittest
from helpers.logHelpers import myClass
class Test_LogHelpers(unittest.TestCase):
def test_mini(self):
myClass.incrementVar("LogHelpers")
なぜか イニット .py (を空白にして)明示的なインポートを行うことで、うまくいきました。 テストファイルの複製を作成し、ログ出力にはヘルパーを呼び出す最初のファイルの '3' とヘルパーを呼び出す2番目のファイルの '4' が正しく出力されていました。
ダニエル・ローズマンの助けと提案に感謝します。 しかし、あなたの回答は非常に有用なフィードバックであったため、「回答あり」とさせていただきます。
解決方法は?
始める前に、PyCharmの警告は実際のPythonのエラーではないことに注意してください:もしあなたのコードを実行したら、おそらくもっと役に立つフィードバックが得られるでしょう(Pythonのような動的言語の静的解析はそこまでしかできないことを忘れないでください、多くのことは実際にコードを実行するまで解決できないのです)。
まず、なぜここでクラスを入れ子にしているのか、その理由がよくわかりません。外側のクラスは全く役に立たないように見えるので、削除してください。
self"のエラーメッセージの理由は、インスタンスメソッドを定義しているためです。
log
. を作成することができます。
mylogger
(ダブルアンダースコアの接頭辞は全く必要ありません) のインスタンスです。
mylogger = log()
- を作成し、それをインポートするか、またはクラスをインポートして、それが使用される場所でインスタンス化します。
つまり、最初のスニペットでは、エラーメッセージは非常に明確です。
mylogger
. 上記の私の推奨する方法を使用すると、次のようになります。
from helpers import mylogger
を直接呼び出して
mylogger.classEnter()
.
最後に、その
global
文は
someFunction
. 自分のスコープ内で名前を再割り当てし、その再割り当てをグローバルスコープに反映させる予定がない限り、名前をグローバルと宣言する必要はありません。ここではそのようなことはしないので
global
.
ちなみに、内側の
log
クラスがあります。一般的に言って、クラスはオブジェクトに何らかの状態を保存する必要がある場合にのみ有用です。ここでは、あなたのdocstringが言うように、ユーティリティメソッドのコレクションを持っています。では、なぜそれらをクラスの中に入れるのでしょうか?の中のトップレベル関数にすればいいのです。
logHelpers
モジュール(ちなみに、Pythonスタイルでは
lower_case_with_underscore
をモジュール名として使用します。したがって、 "log_helpers.py" となります。)
関連
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
PythonによるLeNetネットワークモデルの学習と予測
-
pythonを使ったオフィス自動化コード例
-
Python カメの描画コマンドとその例
-
pythonサイクルタスクスケジューリングツール スケジュール詳解
-
[解決済み】DataFrameのコンストラクタが正しく呼び出されない!エラー
-
[解決済み】Pythonスクリプトで「Expected 2D array, got 1D array instead: 」というエラーが発生?
-
[解決済み】 AttributeError: モジュール 'matplotlib' には属性 'plot' がない。
-
[解決済み] TypeError: 'DataFrame' オブジェクトは呼び出し可能ではない
-
[解決済み】 TypeError: += でサポートされていないオペランド型: 'int' および 'list' です。
-
[解決済み] インポートモジュールにおけるグローバル変数の可視化