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

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

ただいまの
回答率

88.19%

pythonでDictionaryというクラスを継承してUnmoというクラスを実装したい!

解決済

回答 1

投稿 編集

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

oka12

score 8

 前提・実現したいこと

pythonのプログラムでDictionaryというクラスから継承してUnmoというクラスを実行したいです!

Unmoというクラスを実装中に以下のエラーメッセージが発生しました。

 発生している箇所・エラーメッセージ

File "C:\Users\聡一朗\repos\unmo\unmo.py", line 24, in __init__
    'random': RandomResponder('Random', self._dictionary),
TypeError: __init__() takes 2 positional arguments but 3 were given

 該当のソースコード

unmo.py

from responder import WhatResponder, RandomResponder, PatternResponder
from dictionary import Dictionary
from random import choice


class Unmo:
    """人工無脳コアクラス。

    プロパティ:
    name -- 人工無脳コアの名前
    responder_name -- 現在の応答クラスの名前
    """


    def __init__(self, name):
        """文字列を受け取り、コアインスタンスの名前に設定する。
        Responder(What, Random, Pattern)インスタンスを作成し、保持する。
        Dictionaryインスタンスを作成し、保持する。
        """
        self._dictionary = Dictionary()

        self._responders = {
            'what': WhatResponder('What', self._dictionary),
            'random': RandomResponder('Random', self._dictionary),
            'pattern': PatternResponder('Pattern', self._dictionary),
        }
        self._name = name
        self._responder = self._responders['pattern']


    def dialogue(self, text):
        """ユーザーからの入力を受け取り、Responderに処理させた結果を返す。
        呼び出されるたびにランダムでResponderを切り替える。"""
        chosen_key = choice(list(self._responders.keys()))
        self._responder = self._responders[chosen_key]
        return self._responder.response(text)

    @property
    def name(self):
        """人工無脳インスタンスの名前"""
        return self._name

    @property
    def responder_name(self):
        """保持しているResponderの名前"""
        return self._responder.name

dictionary,py

class Dictionary:
    """思考エンジンの辞書クラス。

    クラス変数:
    DICT_RANDOM -- ランダム辞書のファイル名
    DICT_PATTERN -- パターン辞書のファイル名

    プロパティ:
    random -- ランダム辞書
    pattern -- パターン辞書
    """

    DICT_RANDOM = 'dics_random.txt'
    DICT_PATTERN = 'dics_pattern.txt'

    def __init__(self):
        """ファイルから辞書の読み込みを行う。"""
        with open(Dictionary.DICT_RANDOM, encoding='utf-8') as f:
            self._random = [x for x in f.read().splitlines() if x]

        self._pattern = []
        with open(Dictionary.DICT_PATTERN, encoding='utf-8-sig') as f:
            self._pattern = [Dictionary.make_pattern(l) for l in f.read().splitlines() if l]

    @staticmethod
    def make_pattern(line):
        """文字列lineを半角スペースで分割し、{'pattern': [0], 'phrases': [1]}の形式で返す。"""
        pattern, phrases = line.split(" ")
        if pattern and phrases:
            return {'pattern': pattern, 'phrases': phrases.split('|')}


    @property
    def random(self):
        """ランダム辞書"""
        return self._random

    @property
    def pattern(self):
        """パターン辞書"""
        return self._pattern


responder.py

import re

from random import choice

class Responder:
    """AIの応答を制御する思考エンジンの基底クラス。
    継承して使わなければならない。

    メソッド:
    response(str) -- ユーザーの入力strを受け取り、思考結果を返す

    プロパティ:
    name -- Responderオブジェクトの名前
    """

    def __init__(self, name, dictionary):
        """文字列を受け取り、自身のnameに設定する。
        辞書dictionaryを受け取り、自身のdictionaryに保持する。"""
        self._name = name
        self._dictionary = dictionary

    def response(self, *args):
        """文字列を受け取り、思考した結果を返す。"""
        pass

    @property
    def name(self):
        """思考エンジンの名前"""
        return self._name

class WhatResponder(Responder):
    """AIの応答を制御する思考エンジンクラス。
    入力に対して疑問形で聞き返す。"""

    def response(self, text):
        """文字列textを受け取り、'{text}ってなに?'という形式で返す。"""
        return '{}ってなに?'.format(text)

class RandomResponder(Responder):
    """AIの応答を制御する思考エンジンクラス。
    登録された文字列からランダムなものを返す。
    """


    def __init__(self, name):
        """文字列を受け取り、オブジェクトの名前に設定する。
        'dics_random.txt'ファイルから応答文字列のリストを読み込む。"""
        super().__init__(name)
        self.responses = []
        with open('dics_random.txt', mode='r', encoding='utf-8') as f:
            self._responses = [x for x in f.read().splitlines() if x]


    def response(self, _):
        """ユーザーからの入力は受け取るが、使用せずにランダムな応答を返す。"""
        return choice()


    @property
    def name(self):
        """思考エンジンの名前"""
        return self._name

class PatternResponder(Responder):
    """AIの応答を制御する思考エンジンクラス。
    登録されたパターンに反応し、関連する応答を返す。
    """

    def response(self, text):
        """ユーザーの入力に合致するパターンがあれば、関連するフレーズを返す。"""
        for ptn in self.dictionary.pattern:
            matcher = re.match(ptn['pattern'], text)
            if matcher:
                chosen_response = choice(ptn['phrases'])
                return chosen_response.replace('%match%', matcher[0])
        return choice(self._dictionary.random)

 試したこと

同じエラーを探して参考しようとしたのですが(https://teratail.com/questions/139457)、この事例とは異なり引数の数が明らかに違うわけではないのでうまくいきません。もしかしたらエラーの箇所の付近の構文

self._responders = {
            'what': WhatResponder('What', self._dictionary),
            'random': RandomResponder('Random', self._dictionary),
            'pattern': PatternResponder('Pattern', self._dictionary),
        }


の構文内の引数が関係しているように思われるですがいかがでしょうか?

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

0

そもそも提示されているコードはUnmoがDictionaryを継承するようになっていませんが。

エラーの出ている箇所はUnmoやDictionaryの__init__とは関係ありません。よく確認すると、

File "C:\Users\聡一朗\repos\unmo\unmo.py", line 24, in __init__
    'random': RandomResponder('Random', self._dictionary),
TypeError: __init__() takes 2 positional arguments but 3 were given

RandomResponerの__init__は2つの引数しか取らないのに、3つ渡されていますというエラーです。うち1つはselfなので、実際に渡せる引数は1つです。

どうしてself._dictionaryを渡そうと思ったのでしょうか?

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/08/21 00:37

    RandomResponderの実装を直さないと駄目ですね

    キャンセル

  • 2018/08/21 00:41 編集

    RandomResponderに独自の__init__があるので親クラスの__init__を上書きしているというのが直接のエラー原因です
    他にもresponseの実装がおかしかったり、nameが親クラスと重複定義になっていたり、直すべき点は色々あるようです
    記事の「今回のソースはこちら」を見てどうなっているか確認してみてください

    キャンセル

  • 2018/08/21 01:18 編集

    「今回のソースはこちら」の通りにしたらTypeErrorは解決しました。ありがとうございました。でも「今回のソースはこちら」の通りにしたのにPatternResponderクラスでRandomな回答を一、二回繰り返した後新たなエラーが出てうまく実行はできませんでしたが、今回の質問で示したエラーは解決したので解決済みにしようと思います。

    キャンセル

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

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

関連した質問

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