質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.77%

pythonのファイル間をまたいだクラス変数の共有について

解決済

回答 2

投稿

  • 評価
  • クリップ 2
  • VIEW 15K+

JapaneseRobot

score 13

前提・実現したいこと

python3.x系でクラス変数について以下のようなテストプログラムを書きました。
目的はクラス変数を用いてモジュール間でまたいで参照できる共通の変数を持たせたかったからです。
サンプルコードでいうところのモジュールtest1, test2でクラス変数A.aの共有がしたかったです。

発生している問題・エラーメッセージ

test1, test2でクラス変数A.aが共有されずに、Aのそれぞれ別のオブジェクトがtest1, test2で作成されているように見えます。

問題1:
クラスAの初期化処理がtest2のなかでAをimportする段階でも呼び出されています。クラスAのA.aを共有したいので初期化処理を再度呼び出されるのは動作として希望するものではありません。

問題2:
A.aに行った変更処理がそれぞれのtest1, test2で相互に適用されていないです。クラス変数を共有したいのでこれは動作として希望するものではありません。

以上の問題はクラス変数の使い方が誤っているのか、認識が誤っているのかどちらでしょうか。
ファイルモジュールをまたいでクラス変数を共有する方法があれば御教授願いたくおもいます。

該当のソースコード

------test1.py------
import test2

class A:
    a = 10
    print("print a from A initialization")
    print(a)

    def print_a(self):
        print("print a from A")
        print(A.a)

def main():
    B1 = test2.B()
    A.a = 100
    print("check1")
    B1.print_a()
    print("check2")
    A1 = A()
    A1.print_a()
    print("check3")


if __name__ == "__main__":
    main()



------test2.py------
class B:
    def print_a(self):
        from test1 import A
        print("print a from B")
        print(A.a)
        A.a = A.a + 10

test1.pyの実行結果

print a from A initialization
10
check1
print a from A initialization
10
print a from B
10
check2
print a from A
100
check3

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+2

原因は、「直接実行された test1.py は test1 モジュールではない」というところにあります。

main.pyを以下の内容で作って、 python main.py で実行すれば、想定通りの挙動になります。

from test1 import A
import test2

def main():
    B1 = test2.B()
    A.a = 100
    print("check1")
    B1.print_a()
    print("check2")
    A1 = A()
    A1.print_a()
    print("check3")


if __name__ == "__main__":
    main()

直接実行されたスクリプト(test1.py)は、モジュール名が __main__ になります。これは、 __name__ 変数に格納されています。このため、test2.pyがimportして参照している test1.A と __main__.A は別物です。

なお、クラス変数を外から書き換えるのはあまり推奨できないので、アーキテクチャを見直した方がよいと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/12/28 17:13

    回答ありがとうございます。
    モジュール名が直接実行されると__main__になることは知りませんでした。
    その後のクラス変数を外から書き換えるのは推奨できないと合わせて、とてもためになりました。
    サンプルコードを変更して実行したところ確かに想定の動作を致しました。

    モジュールを分けることとアーキテクチャの変更の両方を行いたいと思います。
    たいへんありがとうございました。

    キャンセル

+1

モジュールtest1, test2でクラス変数A.aの共有がしたかった

java等で言う「static変数」のことを言ってるようですね。

このへん↓の記事が参考になりますかね。
Pythonにおけるクラスの静的メンバについて - 試験運用中なLinux備忘録

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/12/28 15:37

    回答ありがとうございます。
    まさしくおっしゃる通り、C++などでいうところの静的メンバー変数が作りたかったわけです。
    リンク先を拝見させていただきましたが、ファイルをまたぐように用いる例はそちらにはないようです。

    今回はpythonでのクラス変数([クラス名].[メンバ変数名]で定義された変数)が静的メンバー変数にあたると思い、その点に関してはいただいたリンク先と同じ思想です。しかしながら私が提示したサンプルコードの用にtest1, test2とまたいで使ったときにクラスオブジェクト自体が複数生成されてしまい(初期化処理が2回行われている)、共有がされていないようにみえたため質問させていただきました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.77%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る