Mostrando las entradas con la etiqueta PYTHON. Mostrar todas las entradas
Mostrando las entradas con la etiqueta PYTHON. Mostrar todas las entradas

viernes, 11 de marzo de 2022

Clase para el manejo de textos escrita en Python

Clase para el manejo de textos

Clase para el manejo de textos escrita en Python. Esta clase contiene métodos útiles que podrás utilizar en tus proyectos. Puedes usarla mediante herencia o directamente como Text.method ya que todos sus métodos están a nivel de clase.

Listado de paises, código y nombre para un proyecto en Python.

 Listado de paises. El código para cada pais en una variable única, y un listado de items (código y nombre) de paises que podrias utilizar en un select input con Django.

martes, 29 de junio de 2021

Python: Hola Mundo con Kivy


Kivy es una biblioteca de Python de código abierto para el desarrollo rápido de aplicaciones que utilizan interfaces de usuario innovadoras, como aplicaciones multitáctiles.

Hola Mundo con Kivy

Instalación de Kivy

pip install kivy


Código fuente

Creamos un archivo con la extención .py con el siguiente contenido:


import kivy 

# Para crear una interfaz de usuario necesitamos 
# importar el módulo de la aplicación Kivy:
from kivy.app import App

# Importamos una etiqueta con la que 
# mostraremos el texto "Hola Mundo".
from kivy.uix.label import Label

# Cambie esto a su versión de Kivy instalada.
kivy.require("2.0.0")


# Esta es la clase principal de nuestra aplicación. 
# Aquí se construirá la ventanda con una etiqueta 
# con el texto "Hola Mundo".
class HelloWorldKivyApp(App):

    # Método que retorna el widget raiz.
    def build(self):

        # La etiqueta con el texto "Hola Mundo" es 
        # retornada como widget raiz.
        return Label(text="Hello World")


# Aquí es inicializada nuestra clase y el método 
# run es llamado, iniciando así nuestra aplicación.
HelloWorldKivyApp().run()


Ejecutamos nuestro código:

python [nombredetuarchivo].py


¡Y listo!


domingo, 27 de junio de 2021

Python Decimal vs float

Cuando trabajamos con números decimales en Python generalmente recurrimos a la clase interna float, y es que además, cuando escribimos el número flotante de manera literal, Python nos devuelve un objecto de tipo float en vez de un objecto de tipo Decimal. Esto nos va a funcionar para la mayoría de los casos, pero los números float tienen limitaciones que podrían ser problemáticas para otros casos de uso. Simplemente no son lo suficientemente precisos.

Decimal vs flotante en Python

El problema de la aritmética de Punto Flotante

Los números de punto flotante se representan en el hardware de la computadora en fracciones en base 2 (binario). Por ejemplo, la fracción decimal

0.125

…tiene el valor 1/10 + 2/100 + 5/1000, y de la misma manera la fracción binaria

0.001

…tiene el valor 0/2 + 0/4 + 1/8. Estas dos fracciones tienen valores idénticos, la única diferencia real es que la primera está escrita en notación fraccional en base 10 y la segunda en base 2.

Lamentablemente, la mayoría de las fracciones decimales no pueden representarse exactamente como fracciones binarias. Como consecuencia, en general los números de punto flotante decimal que ingresas en tu computador son sólo aproximados por los números de punto flotante binario que realmente se guardan en la máquina.

El problema es más fácil de entender primero en base 10. Considerá la fracción 1/3. Podés aproximarla como una fracción de base 10

0.3

…o, mejor,

0.33

…o, mejor,

0.333

…y así. No importa cuantos dígitos desees escribir, el resultado nunca será exactamente 1/3, pero será una aproximación cada vez mejor de 1/3.

De la misma manera, no importa cuantos dígitos en base 2 quieras usar, el valor decimal 0.1 no puede representarse exactamente como una fracción en base 2. En base 2, 1/10 es la siguiente fracción que se repite infinitamente:

0.0001100110011001100110011001100110011001100110011...

La mayoría de los usuarios no son conscientes de esta aproximación por la forma en que se muestran los valores. Python solamente muestra una aproximación decimal al valor verdadero decimal de la aproximación binaria almacenada por la máquina. En la mayoría de las máquinas, si Python fuera a imprimir el verdadero valor decimal de la aproximación binaria almacenada para 0.1, debería mostrar

>>> print(f"{0.1:.55f}")
0.1000000000000000055511151231257827021181583404541015625

Esos son más dígitos que lo que la mayoría de la gente encuentra útil, por lo que Python mantiene manejable la cantidad de dígitos al mostrar en su lugar un valor redondeado.

Un problema práctico

Tenemos los siguientes números:

a = 10
b = a / 77
c = b * 77

en el ejemplo anterior, a debería ser igual a c, pero no lo es ya que sus valores son los siguientes:
a = 10
b = 0.12987012987012986 
c = 9.999999999999998

El módulo decimal

Afortunadamente Python tiene otra forma de lidiar con los números decimales, que es el módulo decimal. A diferencia de los flotantes, los objectos Decimal definidos en el módulo decimal no son propensos a esta pérdida de precisión, porque no se basan en fracciones binarias.

from decimal import Decimal

>>> Decimal(0.1)

0.1000000000000000055511151231257827021181583404541015625

¡Ups! En el ejemplo anterior hemos obtenido un número con toda la impresición del float. Esto se debe a que Python primero evaluó el flotante 0.1, de modo que el valor que estuvo obteniendo el objeto Decimal en realidad fue este

Decimal(0.1000000000000000055511151231257827021181583404541015625)

La manera correcta de hacer esto es pasandole una representación, del  número que queremos utilizar, en string.

>>> n = Decimal("0.1")

>>> f"{n:.60f}"

'0.100000000000000000000000000000000000000000000000000000000000'


>>> n = Decimal(str(0.1))

>>> f"{n:.60f}"

'0.100000000000000000000000000000000000000000000000000000000000'


¡Problema resuelto!


Si quieres saber más sobre este tema te recomiendo 

decimal- Aritmética decimal de coma fija y coma flotante

Decimal vs float in Python



jueves, 24 de diciembre de 2020

¿Cómo generar backups Django desde archivo Python?


 A continuación el código para generar nuestros backups en Django. Lo incluimos en una tarea automatizada para que el código se ejecute automáticamente cada cierto tiempo. Es necesario que el código sea ejecutado en nuestro entorno virtual.

Para ello hacemos uso de la librería pathlib, útil para trabajar con rutas de archivos y directorios. Ofrece un sin número de método adecuados a la plataforma. Según su documentación, este módulo ofrece clases que representan rutas del sistema de archivos con semántica apropiada para diferentes sistemas operativos. Las clases de ruta se dividen entre rutas puras , que proporcionan operaciones puramente computacionales sin E/S, y rutas concretas , que heredan de rutas puras pero también proporcionan operaciones de E/S.

Y también de hacemos uso de la librería zipfile para comprimir nuestros backups en archivos .zip.


import os
import datetime


from pathlib import Path # https://docs.python.org/3/library/pathlib.html
from zipfile import ZipFile # https://docs.python.org/3/library/zipfile.html


# Importamos los settings de nuestro proyecto.
from app.settings import (setting1, setting2, setting3)

SETTINGS = (setting1, setting2, setting3)

# Directorio donde serán almacenados las copias de seguridad.
BACKUP_DIR_NAME = Path(__file__).resolve().parent.parent / "backups"

# Sufijo que tendrá el nombre del archivo generado Ej. nombre_20201224.zip
FILE_SUFFIX_DATE_FORMAT = "%Y%m%d"

# Cantidad de días que durará una copia de seguridad
# almacenada antes de proceder a borrarla automáticamente.
DAYS_TO_KEEP_BACKUP = 3

# Usaremos esta fecha para comparar los archivos antiguos que serán eliminados.
back_date = datetime.datetime.now() - datetime.timedelta(days=DAYS_TO_KEEP_BACKUP)
back_date = back_date.strftime(FILE_SUFFIX_DATE_FORMAT)


# Eliminamos primero para asegurarnos de que casi siempre haya
# espacio disponible para los nuevos backups que serán creados.

for setting in SETTINGS:
path = BACKUP_DIR_NAME

    # Suponiendo hemos creado una variable NAME en cada uno de nuestros setting
prefix = setting.NAME + "_"

# Listamos los archivos dentro del directorio donde se guardan los backups.
list_files = path.iterdir()

for f in list_files:
if f.suffix.lower() == ".zip":

try:
suffix = f.name.split("_")[1].split(".")[0]
except (IndexError):
# Si el archivo no tiene la estructura 'name_%Y%m%d.zip'
# entonces no es un archivo que se ha generado aquí.
continue
# Comparamos las fechas de tipo string y funciona ya que:
# '20201221' es menor que '20201224.
if suffix < back_date:
print(f"Eliminando: {f}")
f.unlink(missing_ok=True)



# Ahora procedemos a generar nuestros backups.

for setting in SETTINGS:

# Construimos el nombre que tendrá el archivo de salida, de acuerdo
# a este formato: 'filename_%Y%m%d.json' -> 'ininstancia_20201224.json'.
timestamp = datetime.datetime.now().strftime(FILE_SUFFIX_DATE_FORMAT)
backup_filename = BACKUP_DIR_NAME / f"{setting.NAME}_{timestamp}.json"

# Ejecutamos el comando python manage.py dumpdata...
print(f"dumpdata para {setting.NAME}")
os.system(f"python manage.py dumpdata > {backup_filename}")

# Creamos el archivo .zip y eliminamos el .json.
zip_filename = backup_filename.with_suffix(".zip")
with ZipFile(zip_filename, 'w') as zip:
zip.write(backup_filename, backup_filename.name)

# Eliminamos el archivos .json.
backup_filename.unlink(missing_ok=True)

print(zip_filename, "OK")

lunes, 14 de diciembre de 2020

Borrar los archivos de migraciones en Django

Script para eliminar todos los archivos de migraciones generados en un proyecto Django.


En la mayoría de los casos no es recomendable borrar los archivos de migraciones generados por Django al ejecutar el comando python manage.py makemigrations, ya que esto guarda un historial completo de los cambios realizados en la base de datos, y así Django, al ejecutar el comando python manage.py migrate determina que migraciones se van aplicar en la base de datos en cuestión. Puedes leer más acerca de las migraciones en Django en el siguiente enlace. Pero, en algunos casos, especialmente para proyectos nuevos que aún no han sido implementados en producción, nos resulta útil borrar estas migraciones. 

Por ejemplo:

Cuando estamos creando un nuevo proyecto Django, es frecuente que realicemos cambios en nuestros modelos, cambiando parámetros de nuestros campos, ya sea corrigiendo errores ortográficos en los textos de parámetro help_text o verbose_name, etc., los cuales resultarán en un nuevo archivo de migración creado por Django, aunque estos cambios no sean tan relevantes. Entonces al momento de implementar nuestro proyecto en producción, tendríamos un sin número de migraciones prácticamente innecesarias, ya que bien podrían haberse incluido en las migraciones iniciales. 

Podemos manualmente eliminar cada una de estas migraciones entrando a cada aplicación y eliminar los archivos uno a uno, pero por comodidad siempre preferimos automatizar todo.


"""
Elimina los archivos dentro las carpetas 'migrations'
"""

import os

opt = str(input("Si continua se borrarán todas las migraciones de todas las "
"aplicaciones que se encuentran en el directorio base. Especificamente dentro "
"de los subdirectorios 'migrations'. ¿Desea continuar? yes/no: "))

if opt.lower() != "yes":
exit(0)

def removedir(path):
for name in os.listdir(path):
p = os.path.join(path, name)
if os.path.isdir(p):
removedir(p)
else:
try:
os.remove(p)
except (WindowsError) as e:
print(e)
else:
print("CORRECTO -- ", p)

path1 = os.curdir

# Remover todos los archivos dentro de los
# directorios 'migrations' y __pycache__
for dirname in ["migrations", "__pycache__"]:
for name in os.listdir(path1):
p = os.path.join(path1, name, dirname)
if os.path.isdir(p):
removedir(p)
try:
# Volvemos a crear el __init__.py borrado.
f = open(os.path.join(p, "__init__.py"), "w")
f.close()
except (BaseException) as e:
print(e)


Copias de seguridad periódica en PythonAnywhere

¿Como hacer copias de seguridad  de la base de datos de forma periódica y automática en pythonanywhere.com?

A continuación se muestra el código de forma detallada de como poder realizar nuestros backups de la base de datos mediante la ejecución de tareas.

De manera general lo que haremos es crear un archivo Python dentro de algún directorio de nuestra cuenta en Pythonanywhere, y luego hacer que dicho archivo sea ejecutado de forma periódica mediante la programación de tareas en el mismo Pythonanywhere.

Para empezar creamos nuestro archivo .py importamos los módulos que usaremos:

import os
import datetime
from zipfile import ZipFile

lunes, 14 de septiembre de 2020

Código para mostrar las diferencias entre tus modelos Django y la base de datos

¿Cómo saber si existen diferencias entre tus modelos Django y la base de datos? 

Es posible que, por lo menos una vez en la vida, hayas tenido problemas aplicando las migraciones de tu proyecto Django.
Las migraciones son la forma en que Django propaga los cambios que realiza en sus modelos (agregar un campo, eliminar un modelo, etc.) en el esquema de su base de datos. Están diseñados para ser en su mayoría automáticos, pero necesitará saber cuándo realizar migraciones, cuándo ejecutarlas y los problemas comunes que puede encontrar. https://docs.djangoproject.com/en/3.1/topics/migrations/

¿Cuáles son los problemas más comunes? 

 El sistema de migraciones de Django es un sistema bastante potente. Te permite realizar varias operaciones importantes en tu base de datos, sin tan siquiera tener que escribir SQL. El sistema puede crear, a partir de los modelos que hayas creado en tus aplicaciones, toda la estructura de la base de datos, las modificaciones que realices a tus modelos se verán reflejadas en tu base de datos con tan solo escribir python manage.py makemigrations y python manage.py migrate. También te permite realizar la operación de manera contraria, creando tus modelos a partir de una base de datos ya existente. Pero, como bien lo dice el equipo de Django en su guía:
"no es perfecto y, para cambios complejos, es posible que no detecte lo que esperaba".
De modo que puedas verte en la necesidad de realizar ajustes en tus modelos o en la base de datos de forma manual. El siguiente código te puede ayudar a encontrar las diferencias existentes entre tus modelos y la base de datos:

from django.db import connections
from django.db.models import ForeignKey, ManyToOneRel, ManyToManyRel, ManyToManyField
from django.db.utils import OperationalError
from django.core.exceptions import ObjectDoesNotExist
from django.conf import settings



def get_cursor(db_alias="default"):
"""
Obtiene el cursor de la conección a la base de datos.
"""
return connections[db_alias].cursor()


def check_database():
"""
Compruba que la información de los modelos está acorde con la información
en la base de datos. Los campos que estén acordes con la información de la
base de datos, serán marcados con una [X]; una casilla vacia en caso contrario [ ].
"""
from django.contrib.contenttypes.models import ContentType
qs = ContentType.objects.all()
cursor = get_cursor()

models_evals = []
dbname = str(settings.DATABASES["default"]["NAME"])
text = f"=======================\nTest: {dbname}\n=======================\n"
print(text)
for ct in qs:
model = ct.model_class()
if (model is None):
continue
models_evals, text = check_model(model, cursor, models_evals, text)
filename = dbname.replace("$", "_").replace(".", "_").replace(" ", "_")
filename = "test/" + filename.split("/")[-1] + ".txt"
f = open(filename, "w")
f.write(text)
f.close()
print(f"Guardado en: '{filename}'")


def check_model(model, cursor, models_evals=[], text=""):
"""
Compara la información de los campos del modelo indicado, con la base de datos.
"""
if (str(model) in models_evals):
return models_evals, text

print("\n----------------------------------")
print(model, model._meta.verbose_name)
text += f"\n{model} | {model._meta.verbose_name}\n"
models_evals.append(str(model))

try:
fields = model._meta.get_fields()
except (AttributeError) as e:
return models_evals, text

manytomanyfieldsmodels = []

for field in fields:
name = field.name

if isinstance(field, ForeignKey):
name = name + "_id"

elif isinstance(field, ManyToManyField):
manytomanyfieldsmodels.append(field.related_model)
print(f"Relación: {field}")
text += f"Relación: {field}\n"
continue

elif (isinstance(field, (ManyToOneRel, ManyToManyRel))):
print(f"Dependiente: {field}")
text += f"Dependiente: {field}\n"
continue

pri = f" - Field: {field.__class__.__name__}( '{name}' )"
try:
cursor.execute(f"SELECT {name} FROM {model._meta.db_table};")
except (OperationalError) as e:
pri = "[ ] "+ pri + f" | Error: {e}"
else:
pri = "[X] " + pri

print(pri)
text += f"{pri}\n"

for many_model in manytomanyfieldsmodels:
models_evals, text = check_model(many_model, cursor, models_evals, text)

return models_evals, text

domingo, 6 de enero de 2019

Cálculo de la cuota de un préstamo con Python



Función en Python para calcular las cuotas de un préstamo según el sistema francés, en el que las cuotas son fijas.

¿Qué es el sistema de amortización francés?

El sistema de amortización francés, es uno de los principales sistemas que se emplean a la hora de amortizar hipotecas. El sistema de amortización francés es aquel que se caracteriza por ser un sistema de amortización de cuotas constantes.

Debido a que las cuotas son constantes, cada mes el banco recibe los intereses en función del capital pendiente de amortizar. Por ello, durante los primeros años de la hipoteca, se paga una cantidad mayor de intereses que de capital y en cambio, durante el período final del préstamo, por pagar más capital e intereses menores.


from decimal import Decimal

def GetValorDeCuotaFija(self, monto, tasa, cuotas, periodo=MENSUAL, limit_dec=None):
    """
    Retorna el valor actual de la cuota, según el método francés,
    en donde las cuotas son fijas. -> float(x)
 
    Formula = R = P [(i (1 + i)**n) / ((1 + i)**n – 1)].
    Donde:
    R = renta (cuota)
    P = principal (préstamo adquirido)
    i = tasa de interés
    n = número de periodos
    -> (Moneda valor, Moneda interes, Moneda monto)
    """
    tasa = tasa / Decimal(100)
    if periodo == DIARIO:
        tasa /= Decimal(30.4167)
    elif periodo == SEMANAL:
        tasa /= Decimal(4.34524)
    if periodo == QUINCENAL:
        tasa /= Decimal(2.0)
    elif periodo == ANUAL:
        tasa *= 12

    # Si no se especifica una tasa, se pone un número casi imperceptible para
    # evitar que la formula lanze una excepción de división por cero.
    if not tasa:
        tasa = Decimal(0.00000000001)
    # Furmula para el cálculo según el sistema francés.
    valor = monto * ( (tasa * ((1 + tasa)**cuotas)) / (((1 + tasa)**cuotas) - 1) )
    interes = valor - monto
    if limit_dec:
        return (round(valor, limit_dec), round(interes, limit_dec), round(monto, limit_dec))
    return (valor, interes, monto)


¿Te diste cuenta que hemos utilizado la clase Decimal del módulo decimal, en vez de un objeto float? La razón principal es la precisión. En este artículo te cuento acerca de las diferencias entre Decimal y float.

Enlaces externos:
Sistema de amortización francés









domingo, 16 de septiembre de 2018

Código para obtener información del Sistema con Python


#InfoSistema.py
"""
DEPENDENCIAS = geoiplookup del paquete geoip-bin
para saber el pais por medio de la IP.
"""
import os
import commands
import datetime
import re
import urllib2


class InfoSistema():
"""
Clase para obtener información del sistema operativo actual.
"""
def GetSystemInfo(self, string=True):
"""
Return a tuple object with the diferent info system if string is True,
return a string.
"""
os = self.GetOS()
system = self.GetSystemName()
platform = self.GetPlatform()
architecture = self.GetArchitecture()
processor = self.GetProcessorName()
machine = self.GetMachine()
login = self.GetLogin()
userpath = self.GetUserPath()
redname = self.GetRedName()

try:
ip = self.GetIpPublica()
except BaseException:
ip = self.GetError()

out = {
"os":os,
"system":system,
"platform":platform,
"architecture":architecture,
"processor":processor,
"machine":machine,
"login":login,
"userpath":userpath,
"redname":redname, "IP":ip
}

if string:
s = """OS: %s\nSys: %s\nPlatform: %s\nArchitecture: %s\nProcessor:
%s\nMachine: %s\nLogin: %s\nUserpath: %s\nRed: %s\n"""
out = s % tuple(out.values())

return out
def GetIpPublica(self):
"""
Obtiene la IP pública del sistema, mediante una lectura a la página web
www.showmyip.com extrayendo de ella la IP pública mostrada.
"""
# Obtenemos el código fuente de la página
s = urllib2.urlopen('http://www.showmyip.com').read()

# Con expresiones regulares se obtiene todo lo que venga después del
# 'displaycopy'. Esta línea es un pedazo de Javascript que imprime en
# la página la IP
m = re.search('(?<=displaycopy).*', s)
ip = m.group(0)

# Reemplazamos por nada los datos que no sirven
ip = ip.replace("('", "")
ip = ip.replace("');", "")

return ip

def GetUsuario(self):
"""
Obtiene el nombre del usuario actual.
"""
usuario = os.getlogin()
return usuario
def GetNombreSistema(self):
"""
Obtiene el nombre del sistema.
"""
nombre = os.name
return nombre
def GetSistema(self):
"""
Obtiene una tupla con el nombre del sistema operativo, nombre del
equipo, version del nucleo fecha de lanzamiento, arquitectura.
"""
sistema = os.uname()
return sistema
def GetFecha(self):
"""
Obtiene la fecha y hora actual del Sistema.
"""
fecha = datetime.datetime.today()
return fecha
def GetPais(self, IP=None):
"""
Obtiene el país de la IP pública pasada como parámetro por medio del
programa en consola 'geoiplookp'. Si no se especifica una IP como
parámetro, se usará la IP pública del sistema actual realizando una
llamada a la función interna self.GetIpPublica().
"""
if IP == None:
IP = self.GetIpPublica()

pais = commands.getoutput("geoiplookup "+str(IP))

if pais == "sh: geoiplookup: not found":
print("El programa geoiplookup, no está instalado")

# Opción para instalar geoiplookup
resp = raw_input("Instalar geoiplookup? s/n ")

if resp.lower() == "s":
print("Instalando Espere...")
#Instalacion del programa geoiplookup
os.system("sudo apt-get install geoip-bin")
pais = commands.getoutput("geoiplookup "+str(IP))
return pais
else:
# si el programa geoiplookup no esta instalado
return None

elif len(str(pais)) > 200:
print("No se pudo obtener el país para la IP "+str(IP))
# Si no se puede obtener el pais de la direccion IP.
return False
else:
return pais

if __name__ == "__main__":
info = InfoSistema()
funciones={
"1":"info.GetIpPublica()",
"2":"info.GetUsuario()",
"3":"info.GetNombreSistema()",
"4":"info.GetSistema()",
"5":"info.GetFecha()",
"6":"info.GetPais()",
"7":"exit()"
}

while True:
print("Elija:....................")
elegir = raw_input("""Ip Publica: 1 \nUsuario: 2 \n
Nombre del Sistema: 3 \nSistema: 4 \n
Fecha: 5 \nPais: 6 \nSalir: 7 \n""")
f = funciones[elegir]
exec f"print({f})"

Trabajar con listas en Python

Una lista en Python es una estructura de datos y un tipo de dato en Python, lo que en otros lenguajes de programación conocemos como arrays o matrices. Lo especial de las listas en Python es que estas pueden almacenar cualquier tipo de datos, ejemplo:


["código", "fuente", 36, [43, "a"], 0.4345, {"dicc": "Hola Mundo"}]



# ¿Cómo crear una lista en Python?
lista = ["Windows", "Linux", "Android"]



# ¿Cómo añadir un elemento a la lista en Python?
lista.append("Mac OS")


# ¿Cómo eliminar un elemento de la lista en Python?
# Puedes eliminar el elemento por su indice en la lista.
# Puedes eliminar el elemento por su nombre en la lista.
lista.pop(2) # elimina a "Android"
lista.remove("Windows") # elimina a "Windows"
lista.clear() # elimina todos los elementos.


# ¿Como obtener un elemento de la lista?
e = lista.index(0) # obtiene el primer elemento.
e = lista.


# ¿Cómo saber la cantidad de elementos de una lista en Python?
cantidad = lista.count()


# ¿Cómo ordenar los elementos de una lista en Python?
lista.sort()


# ¿Cómo cambiar el orden de los elementos de una lista en Python?
lista.reverse()

sábado, 15 de septiembre de 2018

¿Cómo crear una ventana en Python con wxPython?




#!/usr/bin/env python
# -*- coding: utf-8 -*-


# Importamos la librería gráfica wxPython.
import wx


# Nuestra clase que hereda de wx.Frame y que representará la ventana.
class MyFrame(wx.Frame):

    # Función donde se inicializa, donde se crean o se declaran los
    # miembros (variables) de la clase.
    def __init__(self, parent, id, title):
        # Inicializamos la clase wx.Frame de la cual heredará esta.
        wx.Frame.__init__(self, parent, id, title)
        # Creamos una lista de elementos a mostrar.
        self.listbox_1 = wx.ListBox(self, -1)
        # Creamos 2 botones.
        self.button_1 = wx.Button(self, -1, u"Click aquí")
        self.button_2 = wx.Button(self, -1, u"Cerrar")
        # Llmamos otros métodos que creamos para la inicialización.
        self.__do_layout()
        self.__set_properties()
        self.__set_event()
    

    # Esta función ordenará los elementos de nuestra ventana,
    # mediante el uso de sizers.
    def __do_layout(self):
        # Creamos los sizers de tipo BoxSizer donde los elementos se
        # irán incluyendo de manera vertical y horizontalmente.
        sizer_1 = wx.BoxSizer(wx.VERTICAL)
        sizer_2 = wx.BoxSizer(wx.HORIZONTAL)
        # Incluímos los elementos en los sizers mediante su método Add,
        # con los siguientes argumentos:
        #    1. Nombre del elemento a agregar (variable)
        #    2. Proporción que ocupará el elemento dentro del sizer.
        #    3. Margenes que tendrá el elemento: wx.ALL = Todos.
        #    4. Espacio de los margenes.
        sizer_1.Add(self.listbox_1, 1, wx.EXPAND|wx.ALL, 5)
        sizer_2.Add(self.button_1, 0, wx.ALL, 5)
        sizer_2.Add(self.button_2, 0, wx.ALL, 5)
        sizer_1.Add(sizer_2, 0, wx.ALL, 5)
        # Establecemos el sizer principal a la ventana.
        self.SetSizer(sizer_1)
        self.Layout()
    
    # Esta función establecerá las propiedades a los elementos.
    def __set_properties(self):
        # Tamaño de la ventana.
        self.SetSize( (800, 600) )
        # Color de fondo de uno de los miembros (elementos)
        self.button_1.SetBackgroundColour( wx.Colour(200, 255, 100) )
        # Fuente del texto del listbox_1.
        self.listbox_1.SetFont( wx.Font(24, wx.DEFAULT, wx.NORMAL, wx.NORMAL) )

    # Esta función establecerá los diferentes eventos a los elementos.
    def __set_event(self):
        self.Bind(wx.EVT_BUTTON, self.OnButton1, self.button_1)
        self.Bind(wx.EVT_BUTTON, self.OnButton2, self.button_2)
    
    # Función al precionar el button_1
    def OnButton1(self, event):
        # Agregamos un texto al listbox_1.
        self.listbox_1.Append(u"Precionado")
        event.Skip()
    
    # Función al preccionar el button_2
    def OnButton2(self, event):
        self.Close()
        event.Skip()
    
    

# Instaciamos la clase App donde se ejecutará nuestra ventana.
app = wx.App(0)
# Instanciamos la clase MyFrame que representa nuestra ventana.
frame = MyFrame(None, -1, "Hola Mundo")
# Mostramos la ventana.
frame.Show()
# Esto crea una especie de bucle mientras nuestra ventana este abierta.
app.MainLoop()

¿Cómo crear una lista en Python?

# Crear una lista en python es bastante sencillo. Una lista Python es un objeto capaz de almacenar cualquier otro tipo de objeto en una misma instancia, puedes almacenar cadenas de textos, enteros, diccionarios, e inclusive listas (listas dentro de otra lista...).
# Para crear la lista en Python usamos los corchetes [], o podemos utilizar la palabra clave list().


# Ejemplo 1. Lista de Strings:
lenguajes = ["Python", "Ruby", "C++", "Visual Basic"]
# Resultado: ["Python", "Ruby", "C++", "Visual Basic"]


# Ejemplo 2. Lista de enteros:
numeros = [1, 3, 5, 7, 9]
# Resultado: [1, 3, 5, 7, 9]


# Ejemplo 3: Listas de listas:
lista = [["Python", "Ruby", "C++", "Visual Basic"], [1, 3, 5, 7, 9]]
# Resultado: [["Python", "Ruby", "C++", "Visual Basic"], [1, 3, 5, 7, 9]]


# Ejemplo 4: Listas de varios elementos:
varios = ["Python", 1, 4.5, dict(), list()]
# Resultado: ["Python", 1, 4.5, {}, []]


# También puedes hacer esto:
vocales = ["a", "e", "i", "o", "u"]
enteros = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
lista = vocales + enteros
# Resultado: ["a", "e", "i", "o", "u", 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]


# También puedes hacerlo de esta forma:
lista = lista("hola", "mundo", 8)
# Resultado: ["hola", "mundo", 8]