¿Por qué aparece "AttributeError: el objeto NoneType no tiene atributo" usando Tkinter? ¿De dónde vino el valor Ninguno?

Resuelto Arnkrishn asked hace 15 años • 4 respuestas

He creado esta sencilla GUI:

from tkinter import *

root = Tk()

def grabText(event):
    print(entryBox.get())    

entryBox = Entry(root, width=60).grid(row=2, column=1, sticky=W)

grabBtn = Button(root, text="Grab")
grabBtn.grid(row=8, column=1)
grabBtn.bind('<Button-1>', grabText)

root.mainloop()

Cuando hago clic en el Grabbotón, ocurre un error:

C:\Python> python.exe myFiles\testBed.py
Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Python\lib\lib-tk\Tkinter.py", line 1403, in __call__
    return self.func(*args)
  File "myFiles\testBed.py", line 10, in grabText
    if entryBox.get().strip()=="":
AttributeError: 'NoneType' object has no attribute 'get'

¿Por qué está entryBoxconfigurado en None?


Consulte también ¿Por qué aparece AttributeError: el objeto 'NoneType' no tiene el atributo 'algo'? para el caso general.

Arnkrishn avatar Jul 09 '09 10:07 Arnkrishn
Aceptado

Las funciones y griddel objeto y de todos los demás widgets devuelven . En Python, cuando lo hace , el resultado de la expresión es lo que regresa, por lo tanto, regresará .packplaceEntryNonea().b()b()Entry(...).grid(...)None

Deberías dividirlo en dos líneas como esta:

entryBox = Entry(root, width=60)
entryBox.grid(row=2, column=1, sticky=W)

De esa manera, tu Entryreferencia se almacena entryBoxy se presenta como esperas. Esto tiene el efecto secundario adicional de hacer que su diseño sea más fácil de entender y mantener si recopila todas sus declaraciones gridy/o packen bloques.

Cassie Meharry avatar Jul 09 '2009 03:07 Cassie Meharry

Cambie esta línea:

entryBox=Entry(root,width=60).grid(row=2, column=1,sticky=W)

en estas dos líneas:

entryBox=Entry(root,width=60)
entryBox.grid(row=2, column=1,sticky=W)

Tal como ya lo haces correctamente con grabBtn!

Alex Martelli avatar Jul 09 '2009 05:07 Alex Martelli

Solución alternativa para Python3.8+versiones que permite poner todo esto en una línea usando walrus operator:

(entryBox := Entry(root, width=60)).grid(row=2, column=1, sticky=W)

Ahora entryBoxnos referiremos al Entrywidget y también lo empaquetaremos.

Para la gestión de caracteres por línea puedo sugerir algo como esto:

(var := Button(
    text='fine', command=some_func, width=20, height=15, activebackground='grey'
)).grid(row=0, column=0, columnspan=0, rowspan=0, sticky='news')

Pero en ese momento también podría hacer esto "normalmente" (como lo sugieren otras respuestas)

Fuentes:

  • PEP 572 -- Expresiones de asignación
  • En mi opinión, gran video explicativo sobrewalrus operator
Matiiss avatar Aug 14 '2021 10:08 Matiiss