nonetype 对象不可订阅 pysimplegui

nonetype object not subscriptable pysimplegui

我正在尝试同时学习 python 和 pysimplegui。还有我老了也没用!

我正在和我 10 岁的儿子(盲人带领盲人)写一个练习程序,运行 遇到了一个我无法解决的问题。

基本上,该程序让您输入要从中选择多少个号码以及要选择多少个号码,然后计算获胜的几率。点击生成为您随机选择号码并将结果打印到 txt 文件以记录您的选择。

一切正常,但是当我关闭 window 时,出现了一个我无法解决的非类型错误。

哪位大侠能帮帮忙吗? 这是违规行

n=int(values['--tn--'])

from os import close
import random
from tkinter import Scrollbar
import PySimpleGUI as sg
import datetime
import math
from time import sleep, time
from PySimpleGUI.PySimpleGUI import Open, WIN_CLOSED, main
import sys


sg.theme('Reddit')
layout = [
    [sg.In(size=(5,1),k="--tn--" ) ]+[sg.Text('Enter total amount of 
numbers',size=(35,1))],
    [sg.In(size=(5,1),k="--pn--")]+[sg.Text('Enter how many numbers 
you are picking',size=(35,1))],
    [sg.Text('Win odds')]+[sg.ML(background_color='light 
coral',text_color='white',key='--oddout--',size=(50,2))],
    [sg.ML(size=(20,30), key='--main--')],
    [sg.Submit('Odds',key='--odds--')]+[sg.Submit('Generate',key='-- 
gen--')]+ [sg.Cancel('Cancel')]+[sg.Save(key='--save--')]+
    [sg.CloseButton('Close',pad=(100,0))]
    ]
window = sg.Window('Lotto number generator',layout)

while True:

event, values = window.read()
n=int(values['--tn--']) 
rr=int(values['--pn--'])       
nf = math.factorial(n)
rf = math.factorial(rr)
winodds = (nf/(rf*math.factorial(n-rr)))
winodds = int(winodds)
now = datetime.datetime.now()

if event == WIN_CLOSED:
        window['--tn--'].update('1')
        break
if event == '--gen--':
    
    r = random.sample(range(1,n),rr)
    for i in r:
        window['--main--'].print(i)
        
   
if event == '--odds--':
    window['--oddout--'].print("Your chances of winning are 
",f'{winodds:,d}', " to 1, Good Luck")
if event == 'Cancel':
    window['--oddout--'].update('') 
    window['--tn--'].update('')
    window['--pn--'].update('')  
if event == '--save--':
    sys.stdout = open("lotto.txt", "w")
    print(values['--main--'])
    sys.stdout=close(fd=0)
    

window.close()

有一点不好,

  1. 您应该先检查 window 关闭事件,而不是先处理 event, values 其他情况,如以下代码。您可能会得到 event, values 作为 None, None 如果不是,则 values['--tn--'] 将与 None['--tn--'] 相同。这就是为什么你有 TypeError: 'NoneType' object is not subscriptable.
while True:
    event, values = window.read()
    if event in (sg.WINDOW_CLOSED, 'Close'):
        break
    # process other events from here
window.close()
  1. 在您的输入字段中,values['--tn--']values['--pn--'] 可能没有正确的整数格式,因此以下代码可能会失败 ValueError: invalid literal for int() with base 10
n=int(values['--tn--']) 
rr=int(values['--pn--'])

这是我避免问题的方法,

def integer(string):
    try:
        value = int(string)
    except:
        value = None
    return value

for string in ("10.5", "", "10"):
    value = integer(string)
    if value is None:
        print(f"{repr(string)} is not a legal integer string !")
    else:
        print(f"{repr(string)} converted to {value} !")
'10.5' is not a legal integer string !
'' is not a legal integer string !
'10' converted to 10 !
  1. 基本上,window 在您点击 window 的关闭按钮 X 后就被销毁了,所以您不应该在上面更新任何内容。
    if event == WIN_CLOSED:
        # window['--tn--'].update('1')
        break

event, values = window.read() 返回 NoneNone['--tn--'] 不存在,因为 None 没有意义 属性,因此出现错误消息。您已使用该测试来避免这种情况,但将其移至尝试使用缺失的 属性 下方。因此错误。

还值得使用 linting 工具提示您调整语法,这会破坏您的代码和良好实践警告。我使用 pylint 和 flake8。以下内容通过整理 linter 消息来解决您的特定错误消息。仍然有一些警告 - 很好的学习练习:)。

"""Learning program."""
from os import close
import random
import PySimpleGUI as sg
import datetime
import math
from PySimpleGUI.PySimpleGUI import Open, WIN_CLOSED, main
import sys


sg.theme('Reddit')
layout = [
    [sg.In(size=(5, 1), k="--tn--")] + 
    [sg.Text('Enter total amount of numbers', size=(35, 1))],
    [sg.In(size=(5, 1), k="--pn--")] +
    [sg.Text('Enter how many numbers you are picking', size=(35, 1))],
    [sg.Text('Win odds')] +
    [sg.ML(
        background_color='light coral', text_color='white', key='--oddout--', size=(50, 2)
    )],
    [sg.ML(size=(20, 30), key='--main--')],
    [sg.Submit('Odds', key='--odds--')] +
    [sg.Submit('Generate', key='--gen--')] +
    [sg.Cancel('Cancel')] +
    [sg.Save(key='--save--')] +
    [sg.CloseButton('Close', pad=(100, 0))]
    ]
window = sg.Window('Lotto number generator', layout)

while True:
    event, values = window.read()
#    Moved the next three lines up and commented update which also errors
    if event == WIN_CLOSED:
#        window['--tn--'].update('1')
        break
    n = int(values['--tn--']) 
    rr = int(values['--pn--'])       
    nf = math.factorial(n)
    rf = math.factorial(rr)
    winodds = (nf/(rf*math.factorial(n-rr)))
    winodds = int(winodds)
    now = datetime.datetime.now()
    if event == '--gen--':
        r = random.sample(range(1, n), rr)
        for i in r:
            window['--main--'].print(i)
    if event == '--odds--':
        window['--oddout--'].print(
            "Your chances of winning are", f'{winodds:,d}', " to 1, Good Luck"
        )
    if event == 'Cancel':
        window['--oddout--'].update('') 
        window['--tn--'].update('')
        window['--pn--'].update('')  
    if event == '--save--':
        sys.stdout = open("lotto.txt", "w")
        print(values['--main--'])
        sys.stdout = close(fd=0)


window.close()

Flake8 特别会提示您遵循没有明显实际目的的做法。以后随着你使用更多的语言,flake8 提示的好处是最终带来巨大好处的好习惯。

当您关闭 window 时,eventvalues 未设置,请参阅下面的示例。

调试时,打印出 eventvalues 的当前值是一个很好的做法,这样可以检查您是否得到了您认为会得到的结果,如下所示:

def test():
    layout = [[sg.In(size=(5, 1), k="--tn--"), sg.Text('Enter total amount of numbers', size=(35, 1))],
              [sg.In(size=(5, 1), k="--pn--"), sg.Text('Enter how many numbers you are picking', size=(35, 1))],
              [sg.Text('Win odds'),
               sg.ML(background_color='light coral', text_color='white', key='--oddout--', size=(50, 2))],
              [sg.ML(size=(20, 30), key='--main--')],
              [sg.Submit('Odds', key='--odds--'), sg.Submit('Generate', key='--gen--'),
               sg.Cancel('Cancel'), sg.Save(key=' - -save - -'), sg.CloseButton('Close', pad=(100, 0))]
              ]

    window = sg.Window('Lotto number generator', layout)

    while True:
        event, values = window.read()
        print(f'event = {event}, values = {values}')

        if event == WIN_CLOSED:
            break
    window.close()

当您关闭 window 时,您会得到

event = None, values = {'--tn--': None, '--pn--': None, '--oddout--': None, '--main--': None}

所以,用 if event == WIN_CLOSED: 开始你的主循环很重要(在这种情况下打破循环)。只有在那之后,你才能继续处理各种事件和值。