任何人都可以帮我解决这个python TypeError

时间:2015-07-28 10:03:16

标签: python

作为一个新学习者的问题,这个问题可能非常简单,但我已经尝试了很多个小时而无法找到答案,抱歉。

这是edx的python课程的一个问题。

我将粘贴所有代码,但是我已经完成了大部分代码并且正确。第4部分是我正在进行的。 首先,文件的内容是:

    # subject trigger named t1

    t1 SUBJECT world

    # title trigger named t2
    t2 TITLE Intel

    # phrase trigger named t3
    t3 PHRASE New York City

    # composite trigger named t4
    t4 AND t2 t3

    # the trigger set contains t1 and t4
    ADD t1 t4

import feedparser
import string
import time
from project_util import translate_html
from Tkinter import *


#======================
# Code for retrieving and parsing RSS feeds
#======================

def process(url):
    """
    Fetches news items from the rss url and parses them.
    Returns a list of NewsStory-s.
    """
    feed = feedparser.parse(url)
    entries = feed.entries
    ret = []
    for entry in entries:
        guid = entry.guid
        title = translate_html(entry.title)
        link = entry.link
        summary = translate_html(entry.summary)
        try:
            subject = translate_html(entry.tags[0]['term'])
        except AttributeError:
            subject = ""
        newsStory = NewsStory(guid, title, subject, summary, link)
        ret.append(newsStory)
    return ret

#======================
# Part 1
# Data structure design
#======================

class NewsStory(object):
    def __init__(self, guid, title, subject, summary, link):
        self.guid = guid
        self.title = title
        self.subject = subject
        self.summary = summary
        self.link = link        
    def getGuid(self):
        return self.guid        
    def getTitle(self):
        return self.title        
    def getSubject(self):
        return self.subject        
    def getSummary(self):
        return self.summary        
    def getLink(self):
        return self.link    

#======================
# Part 2
# Triggers
#======================

class Trigger(object):
    def evaluate(self, story):
        """
        Returns True if an alert should be generated
        for the given news item, or False otherwise.
        """
        raise NotImplementedError

# Whole Word Triggers

class WordTrigger(Trigger):
    def __init__(self, word):
        self.word = word
    def changeText(self, text):
        for i in string.punctuation:
            text = text.replace(i, ' ')
        return text
    def isWordIn(self, text):
        return self.word.upper in self.changeText(self, text.upper()).split()

class TitleTrigger(WordTrigger):
    def evaluate(self, story):
        return self.isWordIn(self, story.getTitle())

class SubjectTrigger(WordTrigger):
    def evaluate(self, story):
        return self.isWordIn(self, story.getSubject())

class SummaryTrigger(WordTrigger):
    def evaluate(self, story):
        return self.isWordIn(self, story.getSummary())


# Composite Triggers

class NotTrigger(Trigger):
    def __init__(self, trigger):
        self.trigger = trigger
    def evaluate(self,story):
        return not self.trigger.evaluate(story)
class AndTrigger(Trigger):
    def __init__(self, trigger1, trigger2):
        self.trigger1 = trigger1
        self.trigger2 = trigger2
    def evaluate(self, story):
        return self.trigger1.evaluate(story) and self.trigger2.evaluate(story)   
class OrTrigger(Trigger):
    def __init__(self, trigger1, trigger2):
        self.trigger1 = trigger1
        self.trigger2 = trigger2
    def evaluate(self, story):
        return self.trigger1.evaluate(story) or self.trigger2.evaluate(story)

# Phrase Trigger

class PhraseTrigger(Trigger):
    def __init__(self, phrase):
        self.phrase = phrase
    def evaluate(self, story):
        return self.phrase in story.getSubject() or self.phrase in story.\
        getSummary() or self.phrase in story.getTitle()
#======================
# Part 3
# Filtering
#======================

def filterStories(stories, triggerlist):
    """
    Takes in a list of NewsStory instances.

    Returns: a list of only the stories for which a trigger in triggerlist fires.
    """
    temp = stories[:]
    for i in stories:
        for j in triggerlist:
            if (not j.evaluate(i)) and j == triggerlist[-1]:
                temp.remove(i)
            elif j.evaluate(i):
                break
    stories = temp[:]
    return stories

这就是我所做的并且正确无误。因为下一个函数需要TitleTrigger,SubjectTrigger,SummaryTrigger,NotTrigger,AndTrigger,PhraseTrigger,OrTrigger,并且所有触发器都需要NewsStory,所以我保留它们。

#======================
# Part 4
# User-Specified Triggers
#======================

def makeTrigger(triggerMap, triggerType, params, name):
    """
    Takes in a map of names to trigger instance, the type of trigger to make,
    and the list of parameters to the constructor, and adds a new trigger
    to the trigger map dictionary.
    triggerMap: dictionary with names as keys (strings) and triggers as values
    triggerType: string indicating the type of trigger to make (ex: "TITLE")
    params: list of strings with the inputs to the trigger constructor (ex: ["world"])
    name: a string representing the name of the new trigger (ex: "t1")
    Modifies triggerMap, adding a new key-value pair for this trigger.
    Returns a new instance of a trigger (ex: TitleTrigger, AndTrigger).
    """
    if triggerType == 'TITLE':
        triggerMap[name] = TitleTrigger
    if triggerType == 'SUBJECT':
        triggerMap[name] = SubjectTrigger
    if triggerType == 'PHRASE':
        triggerMap[name] = PhraseTrigger
    if triggerType == 'SUMMARY':
        triggerMap[name] = SummaryTrigger
    if triggerType == 'AND':
        triggerMap[name] = AndTrigger
    if triggerType == 'OR':
        triggerMap[name] = OrTrigger
    if triggerType == 'NOT':
        triggerMap[name] = NotTrigger

    if triggerType == 'AND' or triggerType == 'OR':
        tempt = triggerMap[name](triggerMap[params[0]],triggerMap[params[1]])
    elif triggerType == 'NOT':
        tempt = NotTrigger(triggerMap[params[0]])
    else:
        params = ' '.join(params)
        tempt = triggerMap[name](params)
    return tempt

def readTriggerConfig(filename):

    triggerfile = open(filename, "r")
    all = [ line.rstrip() for line in triggerfile.readlines() ]
    lines = []
    for line in all:
        if len(line) == 0 or line[0] == '#':
            continue
        lines.append(line)

    triggers = []
    triggerMap = {}

    for line in lines:

        linesplit = line.split(" ")

        # Making a new trigger
        if linesplit[0] != "ADD":
            trigger = makeTrigger(triggerMap, linesplit[1],
                                  linesplit[2:], linesplit[0])

        # Add the triggers to the list
        else:
            for name in linesplit[1:]:
                triggers.append(triggerMap[name])

    return triggers

这是我正在研究的部分,readTriggerConfig由老师提供。

import thread

SLEEPTIME = 60 #seconds -- how often we poll


def main_thread(master):
    # A sample trigger list - you'll replace
    # this with something more configurable in Problem 11
    try:

        # TODO: Problem 11
        # After implementing makeTrigger, uncomment the line below:
        triggerlist = readTriggerConfig("triggers.txt")

        # **** from here down is about drawing ****
        frame = Frame(master)
        frame.pack(side=BOTTOM)
        scrollbar = Scrollbar(master)
        scrollbar.pack(side=RIGHT,fill=Y)

        t = "Google & Yahoo Top News"
        title = StringVar()
        title.set(t)
        ttl = Label(master, textvariable=title, font=("Helvetica", 18))
        ttl.pack(side=TOP)
        cont = Text(master, font=("Helvetica",14), yscrollcommand=scrollbar.set)
        cont.pack(side=BOTTOM)
        cont.tag_config("title", justify='center')
        button = Button(frame, text="Exit", command=root.destroy)
        button.pack(side=BOTTOM)

        # Gather stories
        guidShown = []
        def get_cont(newstory):
            if newstory.getGuid() not in guidShown:
                cont.insert(END, newstory.getTitle()+"\n", "title")
                cont.insert(END, "\n---------------------------------------------------------------\n", "title")
                cont.insert(END, newstory.getSummary())
                cont.insert(END, "\n*********************************************************************\n", "title")
                guidShown.append(newstory.getGuid())

        while True:

            print "Polling . . .",
            # Get stories from Google's Top Stories RSS news feed
            stories = process("http://news.google.com/?output=rss")

            # Get stories from Yahoo's Top Stories RSS news feed
            stories.extend(process("http://rss.news.yahoo.com/rss/topstories"))

            # Process the stories
            stories = filterStories(stories, triggerlist)

            map(get_cont, stories)
            scrollbar.config(command=cont.yview)


            print "Sleeping..."
            time.sleep(SLEEPTIME)

    except Exception as e:
        print e


if __name__ == '__main__':

    root = Tk()
    root.title("Some RSS parser")
    thread.start_new_thread(main_thread, (root,))
    root.mainloop()

最后一部分由teacher.thanks提供

我在SubjectTrigger,TitleTrigger,PhraseTrigger和AndTrigger中添加了一个名为getWord的方法,以获取单词,短语以查看诱惑是否正确,并在返回之前执行此操作:

print tempt
print tempt.getWord()
return tempt

它给了我:

<__main__.SubjectTrigger object at 0x000000000849B898>
world
<__main__.TitleTrigger object at 0x000000000849B8D0>
Intel
<__main__.PhraseTrigger object at 0x000000000849B898>
New York City
<__main__.AndTrigger object at 0x000000000849B8D0>
(<class '__main__.TitleTrigger'>, <class '__main__.PhraseTrigger'>)
Polling . . .
Traceback (most recent call last):
  File "C:\Users\Administrator\Desktop\python\ProblemSet7\ps7.py", line 292, in main_thread
    stories = filterStories(stories, triggerlist)
  File "C:\Users\Administrator\Desktop\python\ProblemSet7\ps7.py", line 161, in filterStories
    if (not j.evaluate(i)) and j == triggerlist[-1]:
TypeError: unbound method evaluate() must be called with SubjectTrigger instance as first argument (got NewsStory instance instead)

似乎我已经得到了正确的诱惑,但在第161行中有一些错误

2 个答案:

答案 0 :(得分:0)

至少部分问题是这行代码:

WordTrigger.changeText(self, text.upper()).split()

您已将changeText定义为实例方法,但您在类本身上调用它。尝试将其更改为:

self.changeText(text.upper()).split()

您还需要对WordTrigger的其他子类进行类似的转换。

答案 1 :(得分:0)

你的第一个问题显然是一个带有意外数量的参数的实例创建,但第二个问题是你要丢弃可以准确告诉你在哪里的追溯。在您的代码中:

def main_thread(master):
    # A sample trigger list - you'll replace
    # this with something more configurable in Problem 11
    try:
        pass  # Lots of code here
    except Exception as e:
        print e

您捕获任何异常,并仅打印异常。正常行为将打印出它发生的完整回溯。完全删除此try-except子句,或使用traceback模块恢复更多信息:

except:
    import traceback
    traceback.print_exc()

进一步阅读时,您的核心问题似乎在makeTrigger,特别是它如何在triggerMap中使用不同的类型。它试图首先将一个类分配到地图中,然后使用该类创建一个实例,但逻辑是有缺陷的:

if triggerType == 'AND' or triggerType == 'OR':
    tempt = triggerMap[name](triggerMap[params[0]],triggerMap[params[1]])
if triggerType == 'NOT':
    tempt = NotTrigger(triggerMap[params[0]])
else:
    params = ' '.join(params)
    tempt = triggerMap[name](params)

首先,正如您所发现的那样,第一个if与后者不同;这个块不是三个分支,而是顺序的两个分支路径,可以使用elif轻松修复。其次,triggerMap[name]永远不会被设置为创建的实例。这打破了逻辑触发器中的假设,其中triggerMap[params[n]]应该是触发器实例,而不是类。尝试评估triggerMap条目导致未绑定的方法调用。解决此问题的一种方法是triggerMap[name] = tempt

我们也可以减少特殊情况;我会考虑用字典替换triggerType ifs,并且可能使用子类在参数类型(触发器,单词或短语)之间进行选择。