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

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

ただいまの
回答率

88.57%

Python:他のクラス内容を変更したい

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 1,823

sponge_yukari

score 12

こんにちわ。
初歩的な部分な気がするのですが、たどり着けないので質問します。


 環境

  • Python 3.6
  • (PyQt5)

 やりたいこと

ファイルが3つあります。
main.py、A.py、B.py

mainでAとBを使います。

from . import A
class main:
  AA = A.Aclass()
  BB = B.Bclass()
  def print_a(self):
    print(self.AA.a)

Aで使っているaという変数があります。
これをmainから参照しています。

class Aclass:
  a = "a"

aを、Bから変更したいです。
変更するのはmainで使用しているaと同じオブジェクト(同じID)です。
Bからaを変更すれば、mainでprint()等した際にちゃんと変更されている状態を目指してます。

 試したこと

class Aclass:
  a = "a"
  def set_a(self, value):
    global a
    self.a = value


これでaの共有ができないかと考えたのですが、B側でAのインスタンスを作っても同じIDにはならなかったので、うまくいきませんでした。

 条件

 その他

PyQt5で画面を作成しています。
その際、プログレスバーをダイアログ画面で表示して、その中に1つのラベルとプログレスバーを表示します。
ラベルには、現在の作業内容を表示します。
作業は、関数内で行います。
ラベル内容の変更は、その処理の関数の行に入る直前に変更します。
処理をクラスごとに分ける関係で、プログレスバーの画面を表示・実行した場所とは別のクラス(ファイル)でラベルの変更を行うこともあります。

このパターンを行う際に、今回の質問内容がほしくなりました。
サンプルが用意できなかったことと、変数の共有等の初歩的な可能性が高いと思い、今回はこのような形の質問方法にしました。


Javaの場合、static等を使えば似たようなことができたと思うのですが、Pythonでは再現できないということでしょうか。

以上です

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

+2

class Aclass:
  a = "a"
  def set_a(self, value):
    global a
    self.a = value

ちょっとpython的には残念なコードになっています。コードを見るとJavaとかに慣れている人なのかな? という気がしますが、pythonのオブジェクト指向は少しスタイルが違うので注意しましょう。

# globalというのはここの名前空間のこと
# a = "hoge"

class Aclass:
  a = "a"  # ここに書くとクラス変数になる。
  def set_a(self, value):
    global a  # globalはクラス変数ではない
    self.a = value  # self.a = valueではインスタンス変数にアクセスしてaというインスタンス変数を作成する

今回はインスタンス変数にしたいのだと思うので、コンストラクタの__init__()の中でインスタンス変数self.aを作成するようにします。あとは必要に応じてセッターなりゲッターなりを作れば良いです(ただしpythonの場合、セッターとゲッターは作らないで済ませるか、プロパティにして済ませることが多い気がしますが)。

class Aclass:
    def __init__(self):
        self.a = "a"  # インスタンス変数を作る正しい方法
    def set_a(self, value):
        self.a = value

ちなみに、クラス変数を変更したい場合、Aclass.aとしてアクセスするか、self.__class__.aとしてアクセスするかのどちらかを使うことになります。ケースバイケースで。


いずれにせよ、tiitoiさんが指摘されているように何らかのオブジェクトをBに渡さないと駄目ですね。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/11/12 14:04

    クラス変数に対してself.aで使えていたので、ずっと間違えていたようですね。
    __init__内にselfで書く方法は知っていましたが、やってませんでした。
    この機会に改めてみようと思います。
    ありがとうございました。

    キャンセル

  • 2018/11/12 14:10

    そうですね。self経由でクラス変数にアクセスできてしまう仕様になっています。何もしなければそのままクラス変数が見えますが、self.aに対して代入を書いた瞬間に、インスタンス変数self.aが生成されるという仕組みです(コンストラクタにしろこの仕組みでオブジェクトに動的にattributeを追加しているに過ぎません)。

    キャンセル

checkベストアンサー

+1

このように利用する側のクラスに利用される側のオブジェクトを渡すしかないです。

class A:
    def __init__(self):
        self.a = 'hoge'

class B:
    def __init__(self, A):
        self.A = A

    def process(self):
        self.A.a = 'fuga'

objA = A()
objB = B(objA)
print(objA.a)  # hoge

objB.process()
print(objA.a)  # fuga

処理をクラスごとに分ける関係で、プログレスバーの画面を表示・実行した場所とは別のクラス(ファイル)でラベルの変更を行うこともあります。
このパターンを行う際に、今回の質問内容がほしくなりました。

Qt でプログレスバーの更新を行うなら、シグナルスロットを使いましょう。
進捗が変化した際に発呼するシグナルを処理用のクラスに作成し、QProgressBar の setValue() 関数に connect します。
connect はメイン関数側で行います。
そうすれば、作業を行うクラスからプログレスバーを直接いじる必要がなくなります。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/11/12 14:08

    Bに対して参照渡ししてあげる感じでしょうか。
    やはり初歩的なものだったようですね。

    Qtの件までありがとうございます。
    シグナルスロットはまだあまり理解できていませんが、試してみます。

    キャンセル

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

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

関連した質問

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