尝试在OOP类中执行函数时出错

2024-10-01 13:45:58 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在使用“morepythonprogramming for初学者”这本书,我正在从中复制代码。你知道吗

我正在尝试创建一个函数来在屏幕上创建名为print_text()的文本,其中包含一系列呈现文本所需的参数。你知道吗

函数如下:

def print_text(font, x, y, text, colour=(255, 255, 255), shadow=True):
    if shadow:
        txtimg = font.render(text, True, (0,0,0))
        surface.blit(txtimg, (x-2,y-2))
    txtimg = font.render(text, True, colour)
    surface.blit(txtimg, (x, y))

以下是整个程序:

# Trivia Game
#
# An editable quiz. Accumulate ALL the points.
# This has 11 questions so far.
#
# -------------------------------------------------

import pygame, sys
from pygame.locals import *

class Trivia(object):
    def __init__(self, filename):
        self.data = []
        self.current = 0
        self.total = 0
        self.correct = 0
        self.score = 0
        self.scored = False
        self.failed = False
        self.wronganswer = 0
        self.colour = [white, white, white, white]

        txt = open("trivia.txt", "r")
        tdata = txt.readlines()
        txt.close()

        for text_line in tdata:
            self.data.append(text_line.strip())
            self.total += 1

    def print_text(font, x, y, text, colour=(255, 255, 255), shadow=True):
        if shadow:
            txtimg = font.render(text, True, (0,0,0))
            surface.blit(txtimg, (x-2,y-2))
        txtimg = font.render(text, True, colour)
        surface.blit(txtimg, (x, y))

    def show_question(self):
        trivia.print_text(font1, 210, 5, "TRIVIA GAME")
        print_text(font2, 192, 500-20, "press keys 1,2,3,4 to answer", blue)
        print_text(font2, 530, 5, "SCORE:", blue)
        print_text(font2, 550, 25, str(self.score), blue)

        self.correct = int(self.data[self.current+5])

        question = self.current // 6 + 1
        print_text(font1, 5, 80, "QUESTION " + str(question))
        print_text(font2, 20, 120, self.data[self.current], white)

        if self.scored:
            self.colour = [white, white, white, white]
            self.colour[self.correct-1] = green
            print_text(font1, 230, 380, "CORRECT!", green)
            print_text(font2, 170, 420, "Press Enter For Next Question", green)
        elif self.failed:
            self.colour = [white, white, white, white]
            self.colour[self.wronganswer-1] = red
            self.colour[self.correct-1] = green
            print_text(font1, 230, 380, "INCORRECT!", red)
            print_text(font2, 170, 420, "Press Enter For Next Question", red)

        print_text(font1, 5, 170, "ANSWERS")
        print_text(font2, 20, 210, "1 - " + self.data[self.current+1], self.colour[0])
        print_text(font2, 20, 240, "2 - " + self.data[self.current+2], self.colour[1])
        print_text(font2, 20, 270, "3 - " + self.data[self.current+3], self.colour[2])
        print_text(font2, 20, 300, "4 - " + self.data[self.current+4], self.colour[3])

    def handle_input(self,number):
        if not self.scored and not self.failed:
            if number == self.correct:
                self.scored = True
                self.score += 1
            else:
                self.failed = True
                self.wronganswer = number

    def next_question(self):
        if self.scored or self.failed:
            self.scored = False
            self.failed = False
            self.correct = 0
            self.colour = [white, white, white, white]
            self.current += 6
            if self.current >= self.total:
                self.current = 0

# main program

pygame.init()

surface = pygame.display.set_mode((600, 500))
pygame.display.set_caption("School")

font1 = pygame.font.Font(None, 40)
font2 = pygame.font.Font(None, 24)

white = 255, 255, 255
blue = 0, 0, 255
green = 0, 255, 0
red = 255, 0, 0
black = 0, 0, 0

trivia = Trivia("trivia_data.txt")

# loop

while True:
    for event in pygame.event.get():
        if event.type == QUIT:
            sys.exit()
        elif event.type == KEYUP:
            if event.key == pygame.K_ESCAPE:
                sys.exit()
            elif event.key == pygame.K_1:
                trivia.handle_input(1)
            elif event.key == pygame.K_2:
                trivia.handle_input(2)
            elif event.key == pygame.K_3:
                trivia.handle_input(3)
            elif event.key == pygame.K_4:
                trivia.handle_input(4)
            elif event.key == pygame.K_RETURN:
                trivia.next_question()

    surface.fill((black))
    trivia.show_question()

    pygame.display.update()

运行此程序时出现的错误是:

Traceback (most recent call last):
  File "C:\Users\PylonBuffering\Desktop\Pylon Buffering\Games\Other\Trivia Game\Trivia Game.pyw", line 126, in <module>
    trivia.show_question()
  File "C:\Users\PylonBuffering\Desktop\Pylon Buffering\Games\Other\Trivia Game\Trivia Game.pyw", line 39, in show_question
    trivia.print_text(font1, 210, 5, "TRIVIA GAME")
  File "C:\Users\PylonBuffering\Desktop\Pylon Buffering\Games\Other\Trivia Game\Trivia Game.pyw", line 33, in print_text
    txtimg = font.render(text, True, (0,0,0))
AttributeError: 'Trivia' object has no attribute 'render'

帮帮我。如果你发现这个问题已经解决了,请把我链接到它。你知道吗


Tags: textselfeventtrueifcurrentpygameprint
2条回答

问题是您将函数print_text声明为Trivia类的方法。您实际需要的是在全局范围内声明它。你知道吗

要解决此问题,请将print_text函数从这里移出Trivia类:

        self.total += 1 # Do not move this line. I have only provided it for context

def print_text(font, x, y, text, colour=(255, 255, 255), shadow=True):
    if shadow:
        txtimg = font.render(text, True, (0,0,0))
        surface.blit(txtimg, (x-2,y-2))
    txtimg = font.render(text, True, colour)
    surface.blit(txtimg, (x, y))

def show_question(self): # Do not move this line. I have only provided it for context

。。。到此处:

black = 0, 0, 0 # Do not move this line. I have only provided it for context

def print_text(font, x, y, text, colour=(255, 255, 255), shadow=True):
    if shadow:
        txtimg = font.render(text, True, (0,0,0))
        surface.blit(txtimg, (x-2,y-2))
    txtimg = font.render(text, True, colour)
    surface.blit(txtimg, (x, y))

trivia = Trivia("trivia_data.txt") # Do not move this line. I have only provided it for context

这是因为您没有在print_text中添加self参数。如果调用一个方法(如“属于类的函数”),那么传入函数的第一个参数始终是实例本身,而不管其名称如何。因此,如果调用trivia.print_text(font1, ...),参数font自动成为trivia的值,x得到font1的值,依此类推。你知道吗

要亲自验证,请尝试以下操作:

class Test:
    def func():
        print "test"

test = Test()
test.func()

这将提高:

TypeError: func() takes no arguments (1 given)

传递的参数func是实例test。Python将test.func()转换为Test.func(test)。你知道吗

另一个问题是,您从show_question调用print_text时没有self前缀。这样python就找不到print_text,因为函数不在名称空间中。你知道吗

您不应该从类内部调用trivia,而应该使用self(请参见show_question第1行)。你知道吗

所以有三种选择:

  • font之前添加self(不要忘记在所有print_text调用之前添加实例(selftrivia)前缀)
  • print_text移出类的上下文(在print_text调用之前删除所有实例前缀(selftrivia
  • 将decorator @staticmethod添加到print_text,这样可以防止python将实例作为参数传递(不要忘记所有self调用之前的实例(selftrivia)前缀)

相关问题 更多 >