1

Al intentar ejecutar mi código me lanza el siguiente error:

[NameError: name 'self' is not defined]

Esto me ocurre cada vez que utilizo self. Este es mi código:

from tkinter import*

class __init__(self,contenedor):

    self.e1 = Label(contendeor, text ="Etiqueta1", fg="black", bg="white")
    self.e1.pack()

ventana =Tk()
miInterfaz= Interfaz (ventana)
ventana.mainloop()

¿Cómo puedo solucionarlo?

FJSevilla
  • 55,603
  • 7
  • 35
  • 58
  • Miguel, he revertido la edición. Lo único nuevo que aportas es que añadias una captura de pantalla del código en vez del código como texto. Por favor, no postees código como una imágen, dificulta la lectura, búsqueda y reproducción del mismo.. Puedes editar la pregunta si deseas modificar cosas pero deja el código como texto, formateado correctamente. Un saludo. – FJSevilla Aug 30 '17 at 19:44

2 Answers2

3

Estas usando el método especial __init__ como nombre de clase y no como método de la clase (no se que intentas hacer en esa línea, posiblemente estes confundiendo conceptos.).

El método __init__ se encarga de inicializar la clase, de darle un determinado estado a tu objeto nada más ser instanciado. Se ejecuta automáticamente al instanciar la clase y es algo similar a lo que se conoce como "constructor" en otros lenguajes. En tu caso se se encarga de recibir como parámetro la instancia raíz para tu Label y de crearlo.

Mírate estas dos preguntas para más información:

Debes usar la palabra reservada class para definir una clase y def para definir métodos (como el método __init__).


El uso de for modulo import * es una muy mala práctica que debes evitar, más aun si estas aprendiendo (ver PEP 8). El código es menos legible y puede inducir a errores al sobrescribir por error algún método (sobretodo en bibliotecas complejas). Te lo vas a encontrar a menudo, sobretodo en tutoriales de Tkinter (en parte, por culpa de la documentación de effbot.org), lo cual no implica que no sea una mala idea, como el famoso using namespace std; de C++... :). No pasa nada en un ejemplo simple como este, pero para no coger malos hábitos, mejor evitarlo. Recuerda el zen de Python:

"Explícito es mejor que implícito"

En su lugar usa una de las siguientes formas:

  • from tkinter import Label, Tk
  • import tkinter

o la más generalizada (para ahorrarse caracteres):

  • import tkinter as tk

El parámetro self es una convención. Los métodos de instancia deben recibir como primer parámetro la referencia a la instancia de la clase a la que pertenecen. self es solo eso, la referencia a la instancia a la que pertenece el método. Cuando se llama un método de instancia es pasado automáticamente. Delante de los atributos (como en el __init__) indican que son atributos de instancia.

Si tenemos la clase:

class Foo:
    def bar():
        print("Soy un método de la instancia: ", self)

Instanciamos y llamamos a su método así:

>>> instancia = Foo()
>>> instancia.bar()
Soy un método de la instancia:  <__main__.Foo object at 0x7f4e0a267080>

Esto es lo mismo que hacer (para que se entienda lo que es self):

>>> instancia = Foo()
>>> Foo.bar(instancia)
Soy un método de la instancia:  <__main__.Foo object at 0x7f8436622cc0>

Puedes ver una explicación mucho más extendida en la siguiente publicación:


Tu código no tiene más problemas, aparte de un error tipográfico en el primer parámetro al instanciar Label, debería ser así:

import tkinter as tk

class Interfaz():  #Definición de tu clase llamada Intefaz
    def __init__(self, contenedor):   #Definición de su método __init__ Intefaz
        self.e1 = tk.Label(contenedor, text ="Etiqueta1", fg="black", bg="white")
        self.e1.pack()

ventana = tk.Tk()              #Instancia de la clase Tk.
miInterfaz= Interfaz(ventana)  #Instancia de tu clase Interfaz.
ventana.mainloop()            
FJSevilla
  • 55,603
  • 7
  • 35
  • 58
1

Class es una palabra reservada para crear una clase.

__init__ sirve como función 'contructor' en otros lenguajes. Por tanto sebe ser algo así.

try:
    # Python2
    from Tkinter import * 
except ImportError:
    # Python3
    from tkinter import * 

class Interfaz:

    def __init__(self, contenedor):
        self.e1 = Label(contenedor, text ="Etiqueta1", fg="black", bg="white")
        self.e1.pack()

ventana =Tk()
miInterfaz= Interfaz (ventana)
ventana.mainloop()

También note un error en el segundo contenedor. Si eres nuevo en Python te recomiendo empezar por programas que usen la linea de comandos, en lugar de pasar directamente a la interface gráfica.

Alejandro Ruiz
  • 344
  • 2
  • 6