2

这是一个初学者 OO Python 问题。我希望初学者有一个stackoverflow,如果我可以问这个而不会得到反对票。所以,我们开始吧。

当我运行此代码时:

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)方法中停止过程流,而且在包含它的整个类中停止过程流?

顺便说一句,感谢Stephen Holiday分享代码。

4

3 回答 3

4

发生这种情况是因为尽管我在 getFeatures(self) 中添加了 return 语句,但流程会跳转到调用随机模块 (random.shuffle(featureset)) 的下一个类方法(即 trainAndTest(self,trainingPercent=0.80))。

要记住的重要一点是,这None是一个完全有效的值。您的 return 语句getFeatures()完全按照它的指示执行并返回有效值。只有在特殊情况下,或者您明确表示,才会停止这种流动。

与其问你如何“从类中返回”,你可能想要研究的是检查你调用的函数的返回值,并在你继续之前确保它是你期望的。您可以在两个地方执行此操作:

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

...

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

在第一个地方,你可以检查if featureset is None,如果它是 None 则做出反应。
在第二个地方,你可以先检查并在那里做出反应,而不是盲目返回。

第二。您可以选择引发异常。异常是代码遇到错误并且无法继续的情况。然后,调用函数负责处理它或让它顺着链向上。如果没有处理异常,您的应用程序将崩溃。如您所见,您从 random 类中引发了一个异常,因为您允许 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 回答