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

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

ただいまの
回答率

90.33%

  • Python 3.x

    7456questions

    Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

  • オブジェクト指向

    298questions

    オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

Python メソッド間の変数の呼び出しについて

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 1,599
退会済みユーザー

退会済みユーザー

Pythonを勉強しておりまして、現在は主にオブジェクト指向の考え方を学んでおります(オブジェクト指向はほとんど初学です)。これまでに書いたシンプルなプログラムをクラスとメソッドで書き換えているのですが、わからない点があるので教えてください。(関数を使ったほうが良いところもあるかもしれませんが、勉強のつもりで書き換えました)

やってみたこと

名前が

Darth
Luke
Darth
Lea
Darth
Lea
Lea
Luke
Darth
Lea
...

のように続いているファイルをnameslist.txtとして、この名前の数をカウントするプログラムを以下のように書いてみました。

手順は、「ファイルの読み込み」->「名前の重複がないリストを作成」-> 「そのリストをelementとして読み込んだファイルの名前をカウント」です。

ファイルの読み込みと、重複するリストの生成は別々の役割を担うので、クラスを分けました。

class Read_file: #ファイルの読み込み
    def __init__(self):
        self.file = []

    def read_file(self):
        with open('nameslist.txt', 'r') as fi:
            name = fi.read()
        self.file = name.split("\n")
        return self.file

class Undup_list: 
    def __init__(self, list):
        self.list = list

    def undup_list(self): #名前の取り出し
        new_list = []
        for x in self.list:  # creating unduplicated name list
            if x not in new_list:
                    new_list.append(x)
        return sorted(new_list)

    def count_element(self, element): #elementの数をカウント

        return self.list.count(element)

if __name__=='__main__'
    name_in = []
    name_list =[]
    name_count =[]
    file_in = Read_file() #インスタンス生成
    name_in = file_in.read_file()

    name = Undup_list(name_in) #インスタンス生成
    name_list = name.undup_list()

    for i in range(len(name_list)): #counting names
        name_count.append(name.count_element(name_list[i]))
    print(dict(zip(name_list, name_count))) #辞書に変換

 質問内容

クラス Read_file で読み込んだリスト(self.file)を、クラス Undup_listで使うことは可能でしょうか? つまり、それぞれが関数として書かれているならば、関数の中で他の関数を呼び出すことは可能ですが、クラス間ではこれは可能なのでしょうか?

その他

もしこのコードの中で、こういうふうに書き換えればもっと短くなるというところがあれば教えていただけるとうれしいです。

いずれの内容も、高度なオブジェクト指向の内容を含んでいても構いません。

以上よろしくお願い致します。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

checkベストアンサー

+1

クラス Read_file で読み込んだリスト(self.file)を、クラス Undup_listで使うことは可能でしょうか? つまり、それぞれが関数として書かれているならば、関数の中で他の関数を呼び出すことは可能ですが、クラス間ではこれは可能なのでしょうか?

Undup_listクラスの初期化(__init__)時に、Read_fileクラスのインスタンスを引数で受け取るようにしたらいいのではないでしょうか。

# Read_file クラスは変更なし

class Undup_list: 
    def __init__(self, reader): # 変更
        self.reader = reader # 変更

    def undup_list(self):
        new_list = []
        for x in self.reader.read_file(): # 変更(Read_file.read_file メソッド実行)
            if x not in new_list:
                    new_list.append(x)
        return sorted(new_list)

    def count_element(self, element):
        return self.reader.file.count(element) # 変更

if __name__=='__main__'
    name_in = []
    name_list =[]
    name_count =[]
    file_in = Read_file()
    # name_in = file_in.read_file() # 削除

    name = Undup_list(file_in) # 変更(Read_file クラスのインスタンスを指定)
    name_list = name.undup_list()

    for i in range(len(name_list)):
        name_count.append(name.count_element(name_list[i]))
    print(dict(zip(name_list, name_count)))

もしこのコードの中で、こういうふうに書き換えればもっと短くなるというところがあれば教えていただけるとうれしいです。

コードは短くなりませんが、以下の一般的なオブジェクト指向を踏まえて実装しましたので例示します。

・クラス名は名詞(例: 車)
・メンバ変数はオブジェクトの状態や特性を保持する(例: 車.色)
・メソッドはオブジェクトに対する操作(例: 車.走行)

class NameList(list):
    """名前のリスト

    NameList は組み込みの list のサブクラスです。
    標準の list メソッドに加えてファイルから名前を読み込む load メソッドを実装しています。
    """
    def __init__(self, path=None):
        """名前のリストを初期化します。

        Args:
            path (str): ファイルから名前を読み込む場合にパスを指定します。
        """
        super().__init__()

        if path:
            self.load(path)

    def load(self, path):
        """ファイルから名前を読み込んで末尾に追加します。

        Args:
            path (str): ファイルパスを指定します。
        """
        with open(path, 'r') as fp:
            self.extend(fp.read().splitlines())


class Counter(dict):
    """要素をキーとして、カウンタを値として保存する辞書

    Counter は dict のサブクラスです。
    標準の dict メソッドのうち、update メソッドをオーバーライドします。
    """
    def __init__(self, iterable=None):
        """カウンタを初期化します。

        Args:
            iterable (collections.Iterable): 初期化時にカウントする対象がある場合に指定します。
        """
        super().__init__()

        if iterable:
            self.update(iterable)

    def __missing__(self, key):
        # 要素が存在しない場合は 0 を返します。
        return 0

    def update(self, iterable):
        """カウンタを更新します。

        Args:
            iterable (Counter or collections.Iterable):
                カウント対象のイテラブルオブジェクトを指定します。
                Counter オブジェクトの場合、カウンタを合算します。
                collections.Iterable の場合、カウンタをインクリメントします。
        """
        if isinstance(iterable, Counter):
            for key, count in iterable.items():
                self[key] += count
        else:
            for item in iterable:
                self[item] += 1


if __name__=='__main__'
    print(Counter(NameList('nameslist.txt')))

なお、同等のことを普通に実装するなら以下のようになると思います。

from collections import Counter

if __name__ == '__main__':
    with open('nameslist.txt', 'r') as fp:
        lines = fp.read().splitlines()

    print(dict(Counter(lines)))

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/04/15 06:00 編集

    本当に丁寧な回答をいただきありがとうございます。助かりました!頂いた後者のソースコードは、後日勉強用に使わせていただきます。

    キャンセル

  • 2017/04/15 06:50

    何度も申し訳ありません。再度質問させてください。

    最初に頂いたソースコードのUndup_listクラスで
    for x in self.reader.read_file():
    と書き換えていただきましたが、これはどういう風に解釈したら良いのでしょうか?別クラスの変数self.readerを用いて、なぜread_file()メソッドが呼び出せるのかわかりません。

    また、インスタンスを生成する前の変数self.readerはクラスのデータ(情報)を持っていると考えてよいのでしょうか?(私が勉強した限りでは、クラスを使ってインスタンスを生成してからメソッドを呼び出す方法が主でした.)

    お手数をおかけしますが、以上よろしくお願いします。

    キャンセル

  • 2017/04/15 15:41 編集

    ①最後の if __name__ == '__main__': ブロックは以下のとおりです。

    file_in = Read_file()
    name = Undup_list(file_in)

    最初に、Read_file クラスのインスタンスである file_in オブジェクトを作成しています。
    次に、Undup_list クラスのインスタンスである name オブジェクトを作成しています。
    このとき、file_in オブジェクトを初期化引数として渡しています。

    ②Undup_list クラスの初期化(__init__)メソッドは以下のとおりです。

    class Undup_list:
    def __init__(self, reader): # 変更
    self.reader = reader # 変更

    Undup_list クラスは、インスタンスの初期化時に、引数 reader を受け取って、
    メンバ変数 self.reader として保存しています。
    上述①のとおり、引数 reader には、file_in オブジェクトが渡ってきます。

    ③Undup_list クラスの undup_list メソッドは以下のとおりです。

    def undup_list(self):
    new_list = []
    for x in self.reader.read_file(): # 変更(Read_file.read_file メソッド実行)

    self.reader は、上述②のとおり、初期化引数 reader で受け取った file_in オブジェクトを
    保持するメンバ変数です。
    file_in オブジェクトは、Read_file クラスのインスタンスであるため、
    self.reader.read_file メソッドが呼び出せることがわかると思います。

    キャンセル

  • 2017/04/16 01:45 編集

    お忙しい中、丁寧なコメント本当にありがとうございます。とても勉強になります。
    今回は、クラスRead_file()から生成されたインスタンスfile_inを引数として、Undup_listクラスからインスタンスnameを生成している(頂いたコメントの①)ので、Undup_listクラス内でRead_file()クラスのメンバ変数を使えることはよくわかりました。

    本当にありがとうございました。:)

    キャンセル

  • 2017/04/16 21:53

    一般的に継承は、クラスが is-a 関係の場合に行います。
    つまり、"サブクラスは、スーパークラスの一種である"場合です。
    "ファイルリーダー(Read_file)は、重複なしリスト(Undup_list)の一種である"は
    成立しないため、継承関係にはならないと思います。

    新たな質問は、新しく質問を作成されると、
    他の方からの回答も得られやすくなって良いと思います。

    キャンセル

  • 2017/04/16 21:55

    ご丁寧に答えていただきありがとうございます。何度も申し訳ありませんでした。

    次回以降は分けて行なうようにします。今回はお手数おかけしました。

    キャンセル

  • 2017/04/16 22:08

    すみません、タイミングが悪かったみたいですね。
    また、コメントの返信に時間がかかってしまってすみません。

    キャンセル

+1

すみません、コメント欄と間違えました。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/04/16 21:55

    ご丁寧に答えていただきありがとうございます。何度も申し訳ありませんでした。

    次回以降は分けて行なうようにします。今回はお手数おかけしました。

    キャンセル

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

  • Python 3.x

    7456questions

    Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

  • オブジェクト指向

    298questions

    オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。