2

これは初心者のOOPythonの質問です。反対票を獲得せずにこれを尋ねることができれば、初心者のためのスタックオーバーフローがあったらいいのにと思います。だから、ここに行きます。

このコードを実行すると:

from nltk import NaiveBayesClassifier,classify
import USSSALoader
import random

class genderPredictor():

    def getFeatures(self):
        if self._loadNames() != None:
            maleNames,femaleNames=self._loadNames()
        else:
            print "There is no training file."
            return

        featureset = list()
        for nameTuple in maleNames:
            features = self._nameFeatures(nameTuple[0])
            featureset.append((features,'M'))

        for nameTuple in femaleNames:
            features = self._nameFeatures(nameTuple[0])
            featureset.append((features,'F'))

        return featureset

    def trainAndTest(self,trainingPercent=0.80):
        featureset = self.getFeatures()
        random.shuffle(featureset)

        name_count = len(featureset)

        cut_point=int(name_count*trainingPercent)

        train_set = featureset[:cut_point]
        test_set  = featureset[cut_point:]

        self.train(train_set)

        return self.test(test_set)

    def classify(self,name):
        feats=self._nameFeatures(name)
        return self.classifier.classify(feats)

    def train(self,train_set):
        self.classifier = NaiveBayesClassifier.train(train_set)
        return self.classifier

    def test(self,test_set):
       return classify.accuracy(self.classifier,test_set)

    def getMostInformativeFeatures(self,n=5):
        return self.classifier.most_informative_features(n)

    def _loadNames(self):
        return USSSALoader.getNameList()

    def _nameFeatures(self,name):
        name=name.upper()
        return {
            'last_letter': name[-1],
            'last_two' : name[-2:],
            'last_is_vowel' : (name[-1] in 'AEIOUY')
        }

if __name__ == "__main__":
    gp = genderPredictor()
    accuracy=gp.trainAndTest()

そして、をself._loadNames()返しますNone、私はこのエラーを受け取りました(ランダムにインポートされたモジュールから):

shuffle C:\Python27\lib\random.py   285     
TypeError: object of type 'NoneType' has no len()

returnこれは、ステートメントをに入れたにもかかわらず、フローがランダムモジュール()を呼び出すgetFeatures(self)次のクラスメソッド()にジャンプするために発生しました。trainAndTest(self,trainingPercent=0.80)random.shuffle(featureset)

だから、私は知りたいのです:getFeatures(self)メソッドだけでなく、それを含むクラス全体でプロシージャフローを停止する方法は?

ちなみに、コードを共有してくれたStephenHolidayに感謝します。

4

3 に答える 3

4

これは、getFeatures(self)にreturnステートメントを配置したにもかかわらず、フローがランダムモジュール(random.shuffle(featureset))を呼び出す次のクラスメソッド(trainAndTest(self、trainingPercent = 0.80))にジャンプするために発生しました。

覚えておくべき重要なことはNone、それが完全に有効な値であるということです。のreturnステートメントは、getFeatures()指示されたとおりに実行し、有効な値を返します。例外的な状況、または明示的にあなただけがその流れを止めます。

「クラスから戻る」方法を尋ねる代わりに、調べる必要があるのは、呼び出す関数の戻り値をチェックし、先に進む前に期待どおりであることを確認することです。これを行うことができる場所は2つあります。

def trainAndTest(self,trainingPercent=0.80):
    featureset = self.getFeatures()

...

def _loadNames(self):
    return USSSALoader.getNameList()

最初の場所で、を確認if featureset is Noneし、Noneの場合は対応できます。
2番目のスポットでは、盲目的に戻る代わりに、最初にチェックしてそこで反応することができます。

第二に。例外を発生させるオプションがあります。例外は、コードでエラーが発生し、続行できない状況です。その場合、それを処理するか、チェーンに乗せるかは、呼び出し元の関数の責任です。例外を処理するものがない場合、アプリケーションはクラッシュします。ご覧のとおり、Noneがshuffle呼び出しに入るのを許可しているため、ランダムクラスから例外が発生しています。

names = USSSALoader.getNameList()
if names is None:
    # raise an exception?
    # do something else?
    # ask the user to do something?

その時点での問題は、有効なリストの代わりにNoneを取得したときに、プログラムに何をさせたいかということです。ランダムに発生する例外と同様の例外が必要ですが、より有用でアプリケーションに固有のものが必要ですか?または、デフォルトのリストを取得する他のメソッドを呼び出したいだけかもしれません。アプリケーションが終了以外のことを行う状況でも、名前のリストがありませんか?それは回復不可能な状況になります。

names = USSSALoader.getNameList()
if names is None:
    raise ValueError("USSSALoader didn't return any "
                     "valid names! Can't continue!")

アップデート

あなたのコメントから、私はあなたが望む特定の取り扱いを追加したいと思いました。Pythonには、さまざまな状況を表すためのいくつかの組み込みの例外タイプがあります。発生させる可能性が最も高いのはIOErrorで、ファイルが見つからなかったことを示します。「ファイル」とはUSSSALoader.getNameList()、使用する必要のあるファイルが見つからないことを意味すると思います。

names = USSSALoader.getNameList()
if names is None:
    raise IOError("No USSSALoader file found")

この時点で、呼び出しチェーンの上位にある関数がそれを処理しない限り、プログラムはトレースバックエラーで終了します。

于 2012-07-16T00:52:57.380 に答える
0

「クラス全体からの復帰」に勝るものはありません。戻り値がそれらを取得する関数で有効になるように、コードを整理する必要があります。これらの関数は、値をテストして次に何をするかを決定できます。クラス境界はプログラムフローに影響を与えず、メソッドの名前空間にのみ影響を与えます。

于 2012-07-16T00:51:54.390 に答える
0

通常、ここで行うことは、関数を呼び出した後に有効性をチェックすることです。例:

featureset = self.getFeatures()
if not featureset:
    # You could log an error message if you expected to get something, etc.
    return
于 2012-07-16T00:53:20.763 に答える