繁体   English   中英

在if语句永远不会为False的情况下设置为True的变量

[英]variable that is set to True in if statement never becomes False

我有一个矩形坐标列表,正在迭代以测试与每个坐标的碰撞。 列表如下所示: self.rectangle_list = [(200, 30, 100, 10), (200, 60, 100, 10), (200, 90, 100, 10), (200, 120, 100, 10), (200, 150, 100, 10)] 我的for循环代码如下。

        mouse_x, mouse_y = event_obj.pos # mouse_x, mouse_y are the coordinates of the mouse.
        for rects in self.rectangle_list:
            x, y, w, h = rects
            if x <= mouse_x <= x + w and y <= mouse_y <= y + h:
                self.hovering = True
            else:
                self.hovering = False
        print(self.hovering)

当我打印出self.hovering ,只有当鼠标光标在列表中最后一个矩形的坐标中时,它才会变为True。

当我在if语句下移动self.hovering ,它可以工作,但是在不满足if条件时,请勿将self.hovering设置回False。

重现该问题的示例代码如下:

import pygame as pg


class RenderRects:
    def __init__(self, surface, rects_to_render=0):
        self.surface = surface
        self.rects_to_render = rects_to_render
        self.rectangle_list = []
        self.hovering = False

    def render_rects(self):
        y_padding = 0
        for rects in range(self.rects_to_render):
            y_padding += 30
            menu_items_rect = (200, y_padding, 100, 10)
            pg.draw.rect(self.surface, (255, 0, 0), menu_items_rect)
            if len(self.rectangle_list) > 5:
                del self.rectangle_list[4:]
            self.rectangle_list.append(menu_items_rect)

    def check_for_rect_collision(self, event_obj):
       #-----------------Where problem is-----------#
        mx, my = event_obj.pos
        for rects in self.rectangle_list:
            x, y, w, h = rects
            if x <= mx <= x + w and y <= my <= y + h:
                self.hovering = True
            else:
                self.hovering = False
        print(self.hovering)
        #-----------------Where problem is-----------#

    def update_rects(self, event_obj):
        if event_obj.type == pg.MOUSEMOTION:
            self.check_for_rect_collision(event_obj)

def main():
    WIDTH = 800
    HEIGHT = 600
    display = pg.display.set_mode((WIDTH, HEIGHT))

    R = RenderRects(display, rects_to_render=5)

    running = True
    while running:
        for e in pg.event.get():
            if e.type == pg.QUIT:
                running = False
                pg.quit()
                quit()

            R.update_rects(e)

        display.fill((255, 255, 255))
        R.render_rects()
        pg.display.flip()

if __name__ == '__main__':
    main()

您可以为列表中的每个矩形在循环内设置self.hovering 这意味着,在循环之后, self.hovering的值self.hovering对应于最后一个矩形的“悬停状态”。

我认为您想在循环之前设置self.hovering = False ,如果其中一个矩形符合您的条件,则在循环中将其设置为True 这样, self.hovering == True仅在至少一个矩形与您的条件匹配时才成立。

这是您的问题的一个简单示例:

numbers = [2,3,4]
contains_odd = False
for number in numbers:
    if number % 2 == 0:
        contains_odd = False # this is wrong!
    else:
        contains_odd = True
# contains_odd == (numbers[2] % 2 == 1) == False

解决方案是:

numbers = [2,3,4]
contains_odd = False
for number in numbers:
    if number % 2 == 1:
        contains_odd = True

# contains_odd == True

您的if陈述式有问题:

if x <= mouse_x <= x + w and y <= mouse_y <= y + h:
                self.hovering = True

您不能像在以下情况中那样小于/大于: x <= mouse_x <= x + w 这确实可以转换为:

if x <= (mouse_x <= x + w) ....

并且由于True == 1False == 0 ,所以这意味着如果mouse_x <= x + wTrue ,则x <= (mouse_x <= x + w)实际上变为x <= 1


编辑-添加了其他问题解释 (建议给迈克尔·霍夫Michael Hoff

您的循环也有问题。 在循环中, 为每个矩形对设置变量self.hovering 这意味着您将不断用当前矩形的状态覆盖self.hovering的值---如果任何一个矩形都在悬停,则不会。

相反,因为你不在乎self.hovering有史以来 True ,你应该只设置在值True情况:

self.hovering = False # assume it's not hovering at first
for rects in self.rectangle_list:
    x, y, w, h = rects
    if x <= mouse_x and mouse_x <= x + w and y <= mouse_y  and mouse_y <= y + h:
        self.hovering = True # now it will always be True

虽然这解决了循环问题,但仍然有点低效,因为即使您找到使self.hovering = True的对,它仍将继续循环对。 要在找到“好”对时停止循环,可以使用break ,它会过早地结束循环。

self.hovering = False # assume it's not hovering at first
for rects in self.rectangle_list:
    x, y, w, h = rects
    if x <= mouse_x and mouse_x <= x + w and y <= mouse_y  and mouse_y <= y + h:
        self.hovering = True # now it will always be True
        break # exit the loop, since we've found what we're looking for

代码在列表中进行迭代,并且在每个步骤之后self.hovering都会更改。 因此,最后一个矩形决定打印哪个值,因为它是唯一影响它的值,因为在循环之外调用了打印功能。

更新
如果希望在任何矩形适合的情况下将其设置为True,则可以使用:

any([x <= mouse_x <= x + w and y <= mouse_y <= y + h for x,y,w,h in self.rectangle_list])

Any是一个内置函数,可将其作为参数进行迭代。 只要iterable中的任何值为True,否则返回True。 在这种情况下,给它一个由所谓的列表理解创建的列表。 列表理解等效于以下内容:

lis = []
for x, y, w, h in self.rectangle_list:
    lis.append(x <= mouse_x <= x + w and y <= mouse_y <= y + h)

但是,它不需要先创建一个空列表,因此更加紧凑。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM