Вы находитесь на странице: 1из 7

Listas y Diccionarios Python en Lenguaje C

En esta ocasión veremos el cómo usar dentro de Lenguaje C las listas y diccionarios creados dentro de Python, y además de

crear listas y diccionarios dentro de C y enviarlos de vuelta a Python.

Listas
Las listas son tipos de datos estructurados parecidos a los arreglos en C y JAVA pero con mayor funcionalidad y menos

complicación que en estos lenguajes. Las listas en Python son dinámicas estas pueden crecer y disminuir de tamaño, pueden

ser usada como pilas y colas, además que sus elementos pueden ser de diferentes tipos.

1 # Creación de una lista vacía


2
3 lista = list()
4
5 lista = []
6
7 # Con datos
8
9 lista = [1,2,3,4,5,6]
10
11 lista = ['Hola','Python','Ismycode']
12
13 lista = ['Hola',1,3.1416,True]

Diccionarios
Son otro tipo de datos estructurado dentro de Python. Son implementaciones de tablas hash. Son una estructura muy parecida

a los arreglos solo que en este caso los índices no son numero si no que son cadena de caracteres se les conoce como llaves

(keys) al igual que en las lista los valores a los que hacer referencia las llaves pueden ser cualquier tipo de dato.

1 # Creación de un diccionario vació


2
3 diccionario = dict()
4
5 diccionario = {}
6
7 # Con datos
8
9 diccionario = {'key1':100, 'key2':300, 'key3':200}
10
11 diccionario = {'Nombre':'Jose', 'Profesión':'Diseñador'}

Para acceder a un dato dentro de un diccionario se hace de igual forma que con una lista. Usando de ejemplo el último

diccionario creado para acceder al dato ‘José’ hacemos.

1 nombre = diccionario['Nombre']

Para mayor conocimiento sobre estos tipos de datos y otros asuntos relacionado recomiendo Dive into python Excelente libro

para comenzar en Python y además el manual de referencia de Python


Dentro de C
Comenzaremos por crear la estructura principal de nuestro modulo que tendrá como nombre DatosModule.c que contendrá dos

funciones lista_C y diccionario_C las cuales solo recibirán sus respectivos objetos.

1 #include<Python.h>
2
3 static PyObject* lista_C(PyObject* self, PyObject* args){
4 PyObject *lista;
5 if (!PyArg_ParseTuple(args,"O";,&lista))
6 return NULL;
7 ..
8 }
9
10 static PyObject* diccionario_C(PyObject* self, PyObject* args){
11 PyObject *dicc;
12 if (!PyArg_ParseTuple(args,"O",&dicc))
13 return NULL;
14 ..
15 }
16
17 static PyMethodDef datosMethods[] =
18 {
19 {"lista_C";, lista_C, METH_VARARGS, "Manejo de listas en C"},
20 {"diccionario_C";, diccionario_C, METH_VARARGS, "Manejo de diccionarios en C"},
21 {NULL, NULL, 0, NULL}
22 };
23
24 PyMODINIT_FUNC
25 initdatos(void)
26 {
27 (void) Py_InitModule("datos", datosMethods);
28 }

Comencemos con las listas como se puede apreciar en el código por medio del PyArg__ParseTuple() colocamos nuestro

objetos sobre una variable del tipo PyObject *.Después verificaremos si es en verdad una lista con PyList_Check, esta nos

devolverá True (diferente de 0) si nuestro objeto es una lista.

Comenzaremos a trabajar sobre la lista teniendo en cuenta que como lista fue pasada por referencia todos los cambios que

realizamos a la lista desde C se verán reflejas en Python si no deseamos esto deberemos trabajar sobre una copia que

podremos generar desde Python o desde C. Para este caso no importa trabajaremos sobre la lista tal y como esta.

1 if(PyList_Check(lista) == 1){
2 for (i = 0; i < PyList_Size(lista); i += 1)
3 {
4 printf("\tElemento en la posicion %d %s\n",i,PyString_AsString(PyList_GetItem(lista,i)));
5 }
6 PyList_Append(lista,Py_BuildValue("i",11));
7 PyList_Append(lista,Py_BuildValue("s","IsMyCode"));
8 PyList_Reverse(lista);
9 }
Lo primero que realiza nuestro pequeño modulo es el imprimir todos los elementos. Dentro nuestra del ciclo for se

hace uso de PyList_Size() el cual nos devolverá el tamaño de nuestra lista y usaremos de limite de nuestro ciclo.

Después hacemos uso de PyString_AsString(PyList_GetItem(lista,i)). En este caso PyList_GetItem(lista,i) nos

servirá para conseguir el i elemento de la lista y PyString_AsString convertirá el string devuelto de Python a un

char * que será impreso.

PyList_Append agregara al final un elemento. Este elemento deberá ser construido mediante Py_BuildValue()

donde el primer elemento es una cadena que indicara el tipo de dato a construir y el segundo elemento el dato o

variable en C para convertir en dato a Python.

PyList_Reverse(lista); Cambiara el orden de los elementos como su nombre lo indica los mostrara de atrás para

adelante.

Para una parte de los método que se usan en un datos list dentro de Python se pueden encontrar un semejante en

la biblioteca de Python en C.

Ahora vamos tras los diccionarios. Al igual que en las listas los primero que haremos será verifica que en realidad

se trate de una diccionario Python y enseguida espesaremos con el acceso a datos y creación de nuevos datos.
PyObject *keys
1
if(PyDict_Check(dicc) == 1){
2
keys = PyDict_Keys(dicc);
3
for (i = 0; i < PyList_Size(keys); i += 1)
4
{
5
printf("\tElemento con la llave %s %d\n", PyString_AsString(PyList_GetItem(keys,i)),
6
PyInt_AsLong(PyDict_GetItem(dicc,PyList_GetItem(keys,i))));
7
}
8
PyDict_SetItemString(dicc, "IsMyCode", Py_BuildValue("i",11));
9
PyDict_SetItemString(dicc, "IsMyBlog", Py_BuildValue("s","Cadena de caracteres"));
10
}

Como se puede observar comenzamos con un PyObject *keys; esta variable nos servirá para almacenar una lista con todas las

llave del diccionario que son obtenidas con PyDict_Keys(dicc).

Enseguida nuestra función imprimirá cada una de las llaves y los objetos o elementos asociados a esa llave. El elemento

relacionado a la llave lo obtendremos con las función PyDict_GetItem(dicc,PyList_GetItem(keys,i)) que como se observa el

primer elementos es el diccionarios y el segundo la llave. (Fácil).

Fácil para ingresar un elemento dentro de un diccionarios usamos la función PyDict_SetItemString(dicc, “IsMyCode”,

Py_BuildValue(“i”,11)); donde el primer elemento son el diccionario el segundo la llave y el tercero el valor relacionado a la

llave. En caso de que la llave ya exista y tenga un valor relacionado solo sustituirá el valor relacionado por el nuevo valor. Si es

una llave nueva solo la agregara.


static PyObject* lista_C(PyObject* self, PyObject* args){
1 PyObject *lista;
2 int i;
3 if (!PyArg_ParseTuple(args,"O",&lista))
4 return NULL;
5 if(PyList_Check(lista) == 1){
6 for (i = 0; i < PyList_Size(lista); i += 1)
7 {
8 printf("\tElemento en la posicion %d %s\n",i,PyString_AsString(PyList_GetItem(lista,i)));
9 }
10 PyList_Append(lista,Py_BuildValue("i",11));
11 PyList_Append(lista,Py_BuildValue("s","IsMyCode"));
12 PyList_Reverse(lista);
13
}
14
Py_RETURN_NONE;
15
}
16
17
static PyObject* diccionario_C(PyObject* self, PyObject* args){
18
PyObject *dicc;
19
int i;
20
if (!PyArg_ParseTuple(args,"O",&dicc))
21
return NULL;
22
PyObject *keys;
23
if(PyDict_Check(dicc) == 1){
24
keys = PyDict_Keys(dicc);
25
for (i = 0; i < PyList_Size(keys); i += 1)
26
{
27
printf("\tElemento con la llave %s %d\n", PyString_AsString(PyList_GetItem(keys,i)),
28
29 PyInt_AsLong(PyDict_GetItem(dicc,PyList_GetItem(keys,i))));
30 }
31 PyDict_SetItemString(dicc, "IsMyCode", Py_BuildValue("i",11));
32 PyDict_SetItemString(dicc, "IsMyBlog", Py_BuildValue("s","Cadena de caracteres"));
33 }
34 Py_RETURN_NONE;
}

Bueno esto es todo.

Para la creación y retorno de una lista y diccionario los veremos más adelante.

https://ismycode.wordpress.com/2012/03/03/listas-y-diccionarios-python-en-lenguaje-c/
Listas y Diccionarios Python en Lenguaje C II
Retomando el post anterior ahora solo crearemos unas listas dentro de C y la enviaremos de vuelta a Python.

Siguiendo el ejemplo, tenemos que la lista nueva la crearemos mediante PyList_New y como argumento el número de

elementos que contendrá nuestra lista y regresaremos nuestra lista con un simple return ¡Sí fácil!.

1 static PyObject* lista_C(PyObject* self, PyObject* args){


2 int tam; // tamaño de la lista
3 int i; // Contador para recorrer la lista
4 if (!PyArg_ParseTuple(args,"i",&tam))
5 return NULL;
6 PyObject *lista; //nueva lista
7 lista = PyList_New(tam);
8 for (i = 0; i < tam; i += 1)
9 {
10 PyList_SetItem(lista,i,Py_BuildValue("i",i*2));
11 }
12 return lista;
13 }

En este ejemplo con diccionarios crearemos una copia de un diccionario pasado como parámetro, para lo que
usaremos PyDict_Copy. A la copia del diccionario le agregaremos una nueva Llave con un nuevo valor y la regresaremos a
Python con un return.

1 static PyObject* diccionario_C(PyObject* self, PyObject* args){


2 PyObject *dicc;
3 PyObject *new_dicc;
4 if (!PyArg_ParseTuple(args,"O",&dicc))
5 return NULL;
6 if(PyDict_Check(dicc) == 1){
7 new_dicc = PyDict_Copy(dicc);
8 PyDict_SetItemString(new_dicc, "IsMyCode", Py_BuildValue("i",11));
9 return new_dicc;
10 }
11 return NULL;
12 }

Todas las funciones de Python que se pueden usar dentro de C pueden ser consultadas en su manual oficial el cual puede ser
descargado en GNU/Linux y consultado con Devhelp que facilita en mucho las consultas de las referencias.

sudo apt-get install python2.7-doc


1

https://ismycode.wordpress.com/2012/02/29/extenciones-en-lenguaje-c-para-python/
Extensiones en Lenguaje C para Python
Una de las características más importantes de Python es la capacidad de poder escribir extensiones en lenguaje C y C++ para después usarlas

dentro de nuestros scripts. Para poder escribir estas extensiones se hacen uso de varias estructuras.

PyMethodDef
Es una estructura que describen los métodos o funciones de nuestra extensión en C++ o C. Esta estructura cuenta con cuatro

parámetros. {“<<nombre de la función o método>>”,<<Puntero a la función>>,<<Bandera>>,”<<Descripción para docstring>>”}. La

Bandera será un entero que indicara la forma en que se pasaran los parámetros a la función cuando se realiza la llamada. La bandera más

comúnmente usada esMETH_VARARGS el cual indica que la función recibirá una referencia a si mismo y una tupla con los argumentos.

1
static PyMethodDef SpamMethods[] = {
2 ...
3 {"system", spam_system, METH_VARARGS,"Execute a shell command."},
4 ...
{NULL, NULL, 0, NULL} /* Sentinel */
5 };
6
El ejemplo anterior es tomado del manual de Python 2.7 en este se ve como se declara una PyMethodDef que es un arreglo con las

descripciones de todas la funciones de nuestro modulo.

PyMODINIT_FUNC, init<<name>> y Py_InitModule


Estas forman parte de la función de inicialización de nuestro modulo en donde PyMODINIT_FUNC es el tipo de datos que retornara

nuestra función, init<<name>> es el nombre de nuestra función y donde cambiaremos<<name>> por el nombre de nuestro modulo.

y Py_InitModule que es la función encargada de crear nuestro modulo objeto en base al PyMethodDef. Retomando el ejemplo anterior su

respectiva función de inicialización seria la siguiente.

1 PyMODINIT_FUNC
2 initspam(void)
3 {
(void) Py_InitModule("spam", SpamMethods);
4 }
5
PyObject*
Todos los tipos de datos y objetos en Python son tratados bajo C y C++ con este tipo de datos que es una referencia al objetos. Es necesarios

para guardar cada uno de los valores pasados al módulo.

PyArg_ParseTuple
Si en la descripción de la funciones en PyMethodDef hicimos uso de METH_VARARGS esta función nos ayudara a asignar a cada uno de

los objetos dentro la tupla a cada una de nuestras variables objetos dentro de C y C++. La sintaxis de esta es la siguiente.

1 int PyArg_ParseTuple(PyObject *args, const char *format, ...)

Donde args son los argumentos pasados en la llamada a la función, *formats es una cadena de caracteres la cual le dirá a la función los tipos

de datos a recibir y el orden en los que se desean recibir, y por ultimo todas las referencias a las variables donde serán almacenados nuestro

parámetros, Esta función regresara True si todo sale bien False si sale mal (obvio) por lo cual será necesario el manejo de excepción que se

verá en otro post. En el siguiente ejemplo se muestra un uso de esta función.

1 static PyObject *spam_system(PyObject *self, PyObject *args) {


2 const char *command;
3 int sts;
4 if (!PyArg_ParseTuple(args, "s", &command))
5 return NULL;
6 sts = system(command);
7 return Py_BuildValue("i", sts);
8 }

En esta función se reciben los parámetros, que por la cadena se observa solo un dato de tipo string “s” es pasado como parámetro, este sera

almacenado en command una variable del tipo char *. Los caracteres a usar para determinar cada uno de los objetos recibidos en los

parámetros los puedes encontrar aquí.

El ejemplo completo se ve de esta forma.

1 #include<Python.h>
2
3 static PyObject *spam_system(PyObject *self, PyObject *args) {
4 const char *command;
5 int sts;
6 if (!PyArg_ParseTuple(args, "s", &command))
7 return NULL;
8 sts = system(command);
9 return Py_BuildValue("i", sts);
10 }
11
12 static PyMethodDef SpamMethods[] = {
13 {"system", spam_system, METH_VARARGS,"Execute a shell command."},
14 {NULL, NULL, 0, NULL} /* Sentinel */
15 };
16
17 PyMODINIT_FUNC
18 initspam(void)
19 {
20 (void) Py_InitModule("spam", SpamMethods);
21 }

Es importante colocar #include<Python> este tiene todas las definiciones para las funciones de Python así como las constantes usadas.

Compilación de nuestro modulo


Para compilar nuestro modulo haremos uso de distutils, una herramienta incorporada en Python encargada de compilar y enlazar todo lo

necesario para nuestro modulo parecido a un archivo Makefile simplificado. Basta con escribir un archivo setup.py y dentro de él lo

siguiente.

1 from distutils.core import setup, Extension


2
3 module1 = Extension('demo',sources = ['demo.c'])
4
5 setup (name = 'PackageName',
6 version = '1.0',
7 description = 'This is a demo package',
8 ext_modules = [module1])</pre>

Es necesario cambiar los nombres de los modulo por el nuestro, así como nuestros datos. Solo bastaría correr nuestro script para construir

nuestro modulo.

1 $ python setup.py build

Una vez construido se puede hacer uso de nuestros modulos desde la terminal interactiva de Python o desde el código de nuestro script.

1 import spam
2 spam.system("clear")

¡Espero sea de utilidad!. Parte de este post fue tomado del manual de Python.

Вам также может понравиться