# Copyright (C) 2001-2020, Python Software Foundation # This file is distributed under the same license as the Python package. # Maintained by the python-doc-es workteam. # docs-es@python.org / # https://mail.python.org/mailman3/lists/docs-es.python.org/ # Check https://github.com/python/python-docs-es/blob/3.8/TRANSLATORS to # get the list of volunteers # msgid "" msgstr "" "Project-Id-Version: Python 3.8\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-11-21 16:38-0300\n" "PO-Revision-Date: 2021-11-12 10:39+0800\n" "Last-Translator: Rodrigo Tobar \n" "Language: es\n" "Language-Team: python-doc-es\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 2.16.0\n" #: ../Doc/extending/newtypes_tutorial.rst:7 msgid "Defining Extension Types: Tutorial" msgstr "Definición de tipos de extensión: Tutorial" #: ../Doc/extending/newtypes_tutorial.rst:14 msgid "" "Python allows the writer of a C extension module to define new types that " "can be manipulated from Python code, much like the built-in :class:`str` " "and :class:`list` types. The code for all extension types follows a " "pattern, but there are some details that you need to understand before you " "can get started. This document is a gentle introduction to the topic." msgstr "" "Python le permite al escritor de un módulo de extensión C definir nuevos " "tipos que pueden ser manipulados desde el código Python, al igual que los " "tipos incorporados :class:`str` y :class:`list`. El código para todos los " "tipos de extensión sigue un patrón, pero hay algunos detalles que debe " "comprender antes de comenzar. Este documento es una introducción suave al " "tema." #: ../Doc/extending/newtypes_tutorial.rst:24 msgid "The Basics" msgstr "Lo básico" #: ../Doc/extending/newtypes_tutorial.rst:26 #, fuzzy msgid "" "The :term:`CPython` runtime sees all Python objects as variables of type :c:" "expr:`PyObject*`, which serves as a \"base type\" for all Python objects. " "The :c:type:`PyObject` structure itself only contains the object's :term:" "`reference count` and a pointer to the object's \"type object\". This is " "where the action is; the type object determines which (C) functions get " "called by the interpreter when, for instance, an attribute gets looked up on " "an object, a method called, or it is multiplied by another object. These C " "functions are called \"type methods\"." msgstr "" "El tiempo de ejecución :term:`CPython` ve todos los objetos de Python como " "variables de tipo :c:type:`PyObject\\*`, que sirve como un \"tipo base\" " "para todos los objetos de Python. La estructura :c:type:`PyObject` solo " "contiene el :term:`reference count` del objeto y un puntero al \"objeto " "tipo\" del objeto. Aquí es donde está la acción; el objeto tipo determina " "qué funciones (C) llama el intérprete cuando, por ejemplo, se busca un " "atributo en un objeto, se llama un método o se multiplica por otro objeto. " "Estas funciones de C se denominan \"métodos de tipo\"." #: ../Doc/extending/newtypes_tutorial.rst:35 msgid "" "So, if you want to define a new extension type, you need to create a new " "type object." msgstr "" "Por lo tanto, si desea definir un nuevo tipo de extensión, debe crear un " "nuevo objeto de tipo." #: ../Doc/extending/newtypes_tutorial.rst:38 #, fuzzy msgid "" "This sort of thing can only be explained by example, so here's a minimal, " "but complete, module that defines a new type named :class:`!Custom` inside a " "C extension module :mod:`!custom`:" msgstr "" "Este tipo de cosas solo se pueden explicar con un ejemplo, por lo que aquí " "hay un módulo mínimo, pero completo, que define un nuevo tipo llamado :class:" "`Custom` dentro de un módulo de extensión C :mod:`custom`:" #: ../Doc/extending/newtypes_tutorial.rst:43 msgid "" "What we're showing here is the traditional way of defining *static* " "extension types. It should be adequate for most uses. The C API also " "allows defining heap-allocated extension types using the :c:func:" "`PyType_FromSpec` function, which isn't covered in this tutorial." msgstr "" "Lo que estamos mostrando aquí es la forma tradicional de definir tipos de " "extensión *estáticos*. Debe ser adecuado para la mayoría de los usos. La API " "de C también permite definir tipos de extensiones asignadas en el montón " "utilizando la función :c:func:`PyType_FromSpec`, que no se trata en este " "tutorial." #: ../Doc/extending/newtypes_tutorial.rst:48 msgid "" "#define PY_SSIZE_T_CLEAN\n" "#include \n" "\n" "typedef struct {\n" " PyObject_HEAD\n" " /* Type-specific fields go here. */\n" "} CustomObject;\n" "\n" "static PyTypeObject CustomType = {\n" " .ob_base = PyVarObject_HEAD_INIT(NULL, 0)\n" " .tp_name = \"custom.Custom\",\n" " .tp_doc = PyDoc_STR(\"Custom objects\"),\n" " .tp_basicsize = sizeof(CustomObject),\n" " .tp_itemsize = 0,\n" " .tp_flags = Py_TPFLAGS_DEFAULT,\n" " .tp_new = PyType_GenericNew,\n" "};\n" "\n" "static PyModuleDef custommodule = {\n" " .m_base = PyModuleDef_HEAD_INIT,\n" " .m_name = \"custom\",\n" " .m_doc = \"Example module that creates an extension type.\",\n" " .m_size = -1,\n" "};\n" "\n" "PyMODINIT_FUNC\n" "PyInit_custom(void)\n" "{\n" " PyObject *m;\n" " if (PyType_Ready(&CustomType) < 0)\n" " return NULL;\n" "\n" " m = PyModule_Create(&custommodule);\n" " if (m == NULL)\n" " return NULL;\n" "\n" " if (PyModule_AddObjectRef(m, \"Custom\", (PyObject *) &CustomType) < 0) " "{\n" " Py_DECREF(m);\n" " return NULL;\n" " }\n" "\n" " return m;\n" "}\n" msgstr "" #: ../Doc/extending/newtypes_tutorial.rst:50 msgid "" "Now that's quite a bit to take in at once, but hopefully bits will seem " "familiar from the previous chapter. This file defines three things:" msgstr "" "Ahora, eso es bastante para asimilar a la vez, pero espero que los " "fragmentos le resulten familiares del capítulo anterior. Este archivo define " "tres cosas:" #: ../Doc/extending/newtypes_tutorial.rst:53 #, fuzzy msgid "" "What a :class:`!Custom` **object** contains: this is the ``CustomObject`` " "struct, which is allocated once for each :class:`!Custom` instance." msgstr "" "Lo que contiene un **objeto** :class:`Custom`: esta es la estructura " "``CustomObject``, que se asigna una vez para cada instancia de :class:" "`Custom`." #: ../Doc/extending/newtypes_tutorial.rst:55 #, fuzzy msgid "" "How the :class:`!Custom` **type** behaves: this is the ``CustomType`` " "struct, which defines a set of flags and function pointers that the " "interpreter inspects when specific operations are requested." msgstr "" "Cómo se comporta :class:`Custom` **type**: esta es la estructura " "``CustomType``, que define un conjunto de indicadores y punteros de función " "que el intérprete inspecciona cuando se solicitan operaciones específicas." #: ../Doc/extending/newtypes_tutorial.rst:58 #, fuzzy msgid "" "How to initialize the :mod:`!custom` module: this is the ``PyInit_custom`` " "function and the associated ``custommodule`` struct." msgstr "" "Cómo inicializar el módulo :mod:`custom`: esta es la función " "``PyInit_custom`` y la estructura asociada ``custommodule``." #: ../Doc/extending/newtypes_tutorial.rst:61 msgid "The first bit is::" msgstr "La primera parte es::" #: ../Doc/extending/newtypes_tutorial.rst:63 msgid "" "typedef struct {\n" " PyObject_HEAD\n" "} CustomObject;" msgstr "" #: ../Doc/extending/newtypes_tutorial.rst:67 #, fuzzy msgid "" "This is what a Custom object will contain. ``PyObject_HEAD`` is mandatory " "at the start of each object struct and defines a field called ``ob_base`` of " "type :c:type:`PyObject`, containing a pointer to a type object and a " "reference count (these can be accessed using the macros :c:macro:`Py_TYPE` " "and :c:macro:`Py_REFCNT` respectively). The reason for the macro is to " "abstract away the layout and to enable additional fields in :ref:`debug " "builds `." msgstr "" "Esto es lo que contendrá un objeto personalizado. ``PyObject_HEAD`` es " "obligatorio al comienzo de cada estructura de objeto y define un campo " "llamado ``ob_base`` de tipo :c:type:`PyObject`, que contiene un puntero a un " "objeto de tipo y un recuento de referencia (estos pueden ser accedidos " "mediante las macros :c:macro:`Py_REFCNT` y :c:macro:`Py_TYPE` " "respectivamente). El motivo de la macro es abstraer el diseño y habilitar " "campos adicionales en las :ref:`compilaciones de depuración `." #: ../Doc/extending/newtypes_tutorial.rst:76 msgid "" "There is no semicolon above after the :c:macro:`PyObject_HEAD` macro. Be " "wary of adding one by accident: some compilers will complain." msgstr "" "No hay punto y coma (;) arriba después de la macro :c:macro:`PyObject_HEAD`. " "Tenga cuidado de agregar uno por accidente: algunos compiladores se quejarán." #: ../Doc/extending/newtypes_tutorial.rst:79 msgid "" "Of course, objects generally store additional data besides the standard " "``PyObject_HEAD`` boilerplate; for example, here is the definition for " "standard Python floats::" msgstr "" "Por supuesto, los objetos generalmente almacenan datos adicionales además " "del estándar ``PyObject_HEAD`` repetitivo; por ejemplo, aquí está la " "definición de puntos flotantes del estándar de Python::" #: ../Doc/extending/newtypes_tutorial.rst:83 msgid "" "typedef struct {\n" " PyObject_HEAD\n" " double ob_fval;\n" "} PyFloatObject;" msgstr "" #: ../Doc/extending/newtypes_tutorial.rst:88 msgid "The second bit is the definition of the type object. ::" msgstr "La segunda parte es la definición del tipo de objeto. ::" #: ../Doc/extending/newtypes_tutorial.rst:90 msgid "" "static PyTypeObject CustomType = {\n" " .ob_base = PyVarObject_HEAD_INIT(NULL, 0)\n" " .tp_name = \"custom.Custom\",\n" " .tp_doc = PyDoc_STR(\"Custom objects\"),\n" " .tp_basicsize = sizeof(CustomObject),\n" " .tp_itemsize = 0,\n" " .tp_flags = Py_TPFLAGS_DEFAULT,\n" " .tp_new = PyType_GenericNew,\n" "};" msgstr "" #: ../Doc/extending/newtypes_tutorial.rst:101 msgid "" "We recommend using C99-style designated initializers as above, to avoid " "listing all the :c:type:`PyTypeObject` fields that you don't care about and " "also to avoid caring about the fields' declaration order." msgstr "" "Recomendamos utilizar los inicializadores designados al estilo C99 como se " "indica arriba, para evitar enumerar todos los campos :c:type:`PyTypeObject` " "que no le interesan y también para evitar preocuparse por el orden de " "declaración de los campos." #: ../Doc/extending/newtypes_tutorial.rst:105 msgid "" "The actual definition of :c:type:`PyTypeObject` in :file:`object.h` has many " "more :ref:`fields ` than the definition above. The remaining " "fields will be filled with zeros by the C compiler, and it's common practice " "to not specify them explicitly unless you need them." msgstr "" "La definición real de :c:type:`PyTypeObject` en :file:`object.h` tiene " "muchos más :ref:`campos ` que la definición anterior. El " "compilador de C rellenará los campos restantes con ceros, y es una práctica " "común no especificarlos explícitamente a menos que los necesite." #: ../Doc/extending/newtypes_tutorial.rst:110 msgid "We're going to pick it apart, one field at a time::" msgstr "Lo vamos a separar, un campo a la vez:" #: ../Doc/extending/newtypes_tutorial.rst:112 msgid ".ob_base = PyVarObject_HEAD_INIT(NULL, 0)" msgstr "" #: ../Doc/extending/newtypes_tutorial.rst:114 msgid "" "This line is mandatory boilerplate to initialize the ``ob_base`` field " "mentioned above. ::" msgstr "" "Esta línea es obligatoria para inicializar el campo ``ob_base`` mencionado " "anteriormente. ::" #: ../Doc/extending/newtypes_tutorial.rst:117 msgid ".tp_name = \"custom.Custom\"," msgstr "" #: ../Doc/extending/newtypes_tutorial.rst:119 msgid "" "The name of our type. This will appear in the default textual " "representation of our objects and in some error messages, for example:" msgstr "" "El nombre de nuestro tipo. Esto aparecerá en la representación textual " "predeterminada de nuestros objetos y en algunos mensajes de error, por " "ejemplo:" #: ../Doc/extending/newtypes_tutorial.rst:122 msgid "" ">>> \"\" + custom.Custom()\n" "Traceback (most recent call last):\n" " File \"\", line 1, in \n" "TypeError: can only concatenate str (not \"custom.Custom\") to str" msgstr "" #: ../Doc/extending/newtypes_tutorial.rst:129 #, fuzzy msgid "" "Note that the name is a dotted name that includes both the module name and " "the name of the type within the module. The module in this case is :mod:`!" "custom` and the type is :class:`!Custom`, so we set the type name to :class:" "`!custom.Custom`. Using the real dotted import path is important to make " "your type compatible with the :mod:`pydoc` and :mod:`pickle` modules. ::" msgstr "" "Tenga en cuenta que el nombre es un nombre punteado que incluye tanto el " "nombre del módulo como el nombre del tipo dentro del módulo. El módulo en " "este caso es :mod:`custom` y el tipo es :class:`Custom`, por lo que " "establecemos el nombre del tipo en :class:`custom.Custom`. Usar la ruta de " "importación punteada real es importante para que su tipo sea compatible con " "los módulos :mod:`pydoc` y :mod:`pickle`. ::" #: ../Doc/extending/newtypes_tutorial.rst:135 msgid "" ".tp_basicsize = sizeof(CustomObject),\n" ".tp_itemsize = 0," msgstr "" #: ../Doc/extending/newtypes_tutorial.rst:138 #, fuzzy msgid "" "This is so that Python knows how much memory to allocate when creating new :" "class:`!Custom` instances. :c:member:`~PyTypeObject.tp_itemsize` is only " "used for variable-sized objects and should otherwise be zero." msgstr "" "Esto es para que Python sepa cuánta memoria asignar al crear instancias " "nuevas :class:`Custom`. :c:member:`~PyTypeObject.tp_itemsize` solo se usa " "para objetos de tamaño variable y, de lo contrario, debería ser cero." #: ../Doc/extending/newtypes_tutorial.rst:144 #, fuzzy msgid "" "If you want your type to be subclassable from Python, and your type has the " "same :c:member:`~PyTypeObject.tp_basicsize` as its base type, you may have " "problems with multiple inheritance. A Python subclass of your type will " "have to list your type first in its :attr:`~type.__bases__`, or else it will " "not be able to call your type's :meth:`~object.__new__` method without " "getting an error. You can avoid this problem by ensuring that your type has " "a larger value for :c:member:`~PyTypeObject.tp_basicsize` than its base type " "does. Most of the time, this will be true anyway, because either your base " "type will be :class:`object`, or else you will be adding data members to " "your base type, and therefore increasing its size." msgstr "" "Si desea que su tipo pueda tener subclases desde Python, y su tipo tiene el " "mismo :c:member:`~PyTypeObject.tp_basicsize` como su tipo base, puede tener " "problemas con la herencia múltiple. Una subclase de Python de su tipo tendrá " "que enumerar su tipo primero en su :attr:`~class.__bases__`, o de lo " "contrario no podrá llamar al método de su tipo :meth:`__new__` sin obtener " "un error. Puede evitar este problema asegurándose de que su tipo tenga un " "valor mayor para :c:member:`~PyTypeObject.tp_basicsize` que su tipo base. La " "mayoría de las veces, esto será cierto de todos modos, porque su tipo base " "será :class:`object`, o de lo contrario agregará miembros de datos a su tipo " "base y, por lo tanto, aumentará su tamaño." #: ../Doc/extending/newtypes_tutorial.rst:154 #, fuzzy msgid "We set the class flags to :c:macro:`Py_TPFLAGS_DEFAULT`. ::" msgstr "Configuramos las banderas de clase a :const:`Py_TPFLAGS_DEFAULT`. ::" #: ../Doc/extending/newtypes_tutorial.rst:156 msgid ".tp_flags = Py_TPFLAGS_DEFAULT," msgstr "" #: ../Doc/extending/newtypes_tutorial.rst:158 msgid "" "All types should include this constant in their flags. It enables all of " "the members defined until at least Python 3.3. If you need further members, " "you will need to OR the corresponding flags." msgstr "" "Todos los tipos deben incluir esta constante en sus banderas. Habilita todos " "los miembros definidos hasta al menos Python 3.3. Si necesita más miembros, " "necesitará O (*OR*) las banderas correspondientes." #: ../Doc/extending/newtypes_tutorial.rst:162 msgid "" "We provide a doc string for the type in :c:member:`~PyTypeObject.tp_doc`. ::" msgstr "" "Proporcionamos una cadena de documentos para el tipo en :c:member:" "`~PyTypeObject.tp_doc`. ::" #: ../Doc/extending/newtypes_tutorial.rst:164 msgid ".tp_doc = PyDoc_STR(\"Custom objects\")," msgstr "" #: ../Doc/extending/newtypes_tutorial.rst:166 #, fuzzy msgid "" "To enable object creation, we have to provide a :c:member:`~PyTypeObject." "tp_new` handler. This is the equivalent of the Python method :meth:`~object." "__new__`, but has to be specified explicitly. In this case, we can just use " "the default implementation provided by the API function :c:func:" "`PyType_GenericNew`. ::" msgstr "" "Para habilitar la creación de objetos, debemos proporcionar un controlador :" "c:member:`~PyTypeObject.tp_new`. Este es el equivalente del método Python :" "meth:`__new__`, pero debe especificarse explícitamente. En este caso, " "podemos usar la implementación predeterminada proporcionada por la función " "API :c:func:`PyType_GenericNew`. ::" #: ../Doc/extending/newtypes_tutorial.rst:171 msgid ".tp_new = PyType_GenericNew," msgstr "" #: ../Doc/extending/newtypes_tutorial.rst:173 #, fuzzy msgid "" "Everything else in the file should be familiar, except for some code in :c:" "func:`!PyInit_custom`::" msgstr "" "Todo lo demás en el archivo debe ser familiar, excepto algún código en :c:" "func:`PyInit_custom`::" #: ../Doc/extending/newtypes_tutorial.rst:176 msgid "" "if (PyType_Ready(&CustomType) < 0)\n" " return;" msgstr "" #: ../Doc/extending/newtypes_tutorial.rst:179 #, fuzzy msgid "" "This initializes the :class:`!Custom` type, filling in a number of members " "to the appropriate default values, including :c:member:`~PyObject.ob_type` " "that we initially set to ``NULL``. ::" msgstr "" "Esto inicializa el tipo :class:`Custom`, completando un número de miembros " "con los valores predeterminados apropiados, que incluyen :attr:`ob_type` que " "inicialmente configuramos en ``NULL``. ::" #: ../Doc/extending/newtypes_tutorial.rst:183 msgid "" "if (PyModule_AddObjectRef(m, \"Custom\", (PyObject *) &CustomType) < 0) {\n" " Py_DECREF(m);\n" " return NULL;\n" "}" msgstr "" #: ../Doc/extending/newtypes_tutorial.rst:188 #, fuzzy msgid "" "This adds the type to the module dictionary. This allows us to create :" "class:`!Custom` instances by calling the :class:`!Custom` class:" msgstr "" "Esto agrega el tipo al diccionario del módulo. Esto nos permite crear " "instancias :class:`Custom` llamando la clase :class:`Custom`:" #: ../Doc/extending/newtypes_tutorial.rst:191 msgid "" ">>> import custom\n" ">>> mycustom = custom.Custom()" msgstr "" #: ../Doc/extending/newtypes_tutorial.rst:196 #, fuzzy msgid "" "That's it! All that remains is to build it; put the above code in a file " "called :file:`custom.c`," msgstr "" "¡Eso es! Todo lo que queda es construirlo; ponga el código anterior en un " "archivo llamado :file:`custom.c` y:" #: ../Doc/extending/newtypes_tutorial.rst:199 msgid "" "[build-system]\n" "requires = [\"setuptools\"]\n" "build-backend = \"setuptools.build_meta\"\n" "\n" "[project]\n" "name = \"custom\"\n" "version = \"1\"\n" msgstr "" #: ../Doc/extending/newtypes_tutorial.rst:201 #, fuzzy msgid "in a file called :file:`pyproject.toml`, and" msgstr "en un archivo llamado :file:`setup.py`; luego escribiendo" #: ../Doc/extending/newtypes_tutorial.rst:203 msgid "" "from setuptools import Extension, setup\n" "setup(ext_modules=[Extension(\"custom\", [\"custom.c\"])])" msgstr "" #: ../Doc/extending/newtypes_tutorial.rst:208 msgid "in a file called :file:`setup.py`; then typing" msgstr "en un archivo llamado :file:`setup.py`; luego escribiendo" #: ../Doc/extending/newtypes_tutorial.rst:210 #: ../Doc/extending/newtypes_tutorial.rst:525 msgid "$ python -m pip install ." msgstr "" #: ../Doc/extending/newtypes_tutorial.rst:214 #, fuzzy msgid "" "in a shell should produce a file :file:`custom.so` in a subdirectory and " "install it; now fire up Python --- you should be able to ``import custom`` " "and play around with ``Custom`` objects." msgstr "" "en un shell debería producir un archivo :file:`custom.so` en un " "subdirectorio; muévete a ese directorio y abre Python --- deberías poder " "``import custom`` y jugar con objetos personalizados." #: ../Doc/extending/newtypes_tutorial.rst:218 msgid "That wasn't so hard, was it?" msgstr "Eso no fue tan difícil, ¿verdad?" #: ../Doc/extending/newtypes_tutorial.rst:220 msgid "" "Of course, the current Custom type is pretty uninteresting. It has no data " "and doesn't do anything. It can't even be subclassed." msgstr "" "Por supuesto, el tipo personalizado actual es bastante poco interesante. No " "tiene datos y no hace nada. Ni siquiera se puede subclasificar." #: ../Doc/extending/newtypes_tutorial.rst:225 msgid "Adding data and methods to the Basic example" msgstr "Agregar datos y métodos al ejemplo básico" #: ../Doc/extending/newtypes_tutorial.rst:227 #, fuzzy msgid "" "Let's extend the basic example to add some data and methods. Let's also " "make the type usable as a base class. We'll create a new module, :mod:`!" "custom2` that adds these capabilities:" msgstr "" "Extendamos el ejemplo básico para agregar algunos datos y métodos. También " "hagamos que el tipo sea utilizable como una clase base. Crearemos un nuevo " "módulo, :mod:`custom2` que agrega estas capacidades:" #: ../Doc/extending/newtypes_tutorial.rst:231 msgid "" "#define PY_SSIZE_T_CLEAN\n" "#include \n" "#include /* for offsetof() */\n" "\n" "typedef struct {\n" " PyObject_HEAD\n" " PyObject *first; /* first name */\n" " PyObject *last; /* last name */\n" " int number;\n" "} CustomObject;\n" "\n" "static void\n" "Custom_dealloc(CustomObject *self)\n" "{\n" " Py_XDECREF(self->first);\n" " Py_XDECREF(self->last);\n" " Py_TYPE(self)->tp_free((PyObject *) self);\n" "}\n" "\n" "static PyObject *\n" "Custom_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\n" "{\n" " CustomObject *self;\n" " self = (CustomObject *) type->tp_alloc(type, 0);\n" " if (self != NULL) {\n" " self->first = PyUnicode_FromString(\"\");\n" " if (self->first == NULL) {\n" " Py_DECREF(self);\n" " return NULL;\n" " }\n" " self->last = PyUnicode_FromString(\"\");\n" " if (self->last == NULL) {\n" " Py_DECREF(self);\n" " return NULL;\n" " }\n" " self->number = 0;\n" " }\n" " return (PyObject *) self;\n" "}\n" "\n" "static int\n" "Custom_init(CustomObject *self, PyObject *args, PyObject *kwds)\n" "{\n" " static char *kwlist[] = {\"first\", \"last\", \"number\", NULL};\n" " PyObject *first = NULL, *last = NULL;\n" "\n" " if (!PyArg_ParseTupleAndKeywords(args, kwds, \"|OOi\", kwlist,\n" " &first, &last,\n" " &self->number))\n" " return -1;\n" "\n" " if (first) {\n" " Py_XSETREF(self->first, Py_NewRef(first));\n" " }\n" " if (last) {\n" " Py_XSETREF(self->last, Py_NewRef(last));\n" " }\n" " return 0;\n" "}\n" "\n" "static PyMemberDef Custom_members[] = {\n" " {\"first\", Py_T_OBJECT_EX, offsetof(CustomObject, first), 0,\n" " \"first name\"},\n" " {\"last\", Py_T_OBJECT_EX, offsetof(CustomObject, last), 0,\n" " \"last name\"},\n" " {\"number\", Py_T_INT, offsetof(CustomObject, number), 0,\n" " \"custom number\"},\n" " {NULL} /* Sentinel */\n" "};\n" "\n" "static PyObject *\n" "Custom_name(CustomObject *self, PyObject *Py_UNUSED(ignored))\n" "{\n" " if (self->first == NULL) {\n" " PyErr_SetString(PyExc_AttributeError, \"first\");\n" " return NULL;\n" " }\n" " if (self->last == NULL) {\n" " PyErr_SetString(PyExc_AttributeError, \"last\");\n" " return NULL;\n" " }\n" " return PyUnicode_FromFormat(\"%S %S\", self->first, self->last);\n" "}\n" "\n" "static PyMethodDef Custom_methods[] = {\n" " {\"name\", (PyCFunction) Custom_name, METH_NOARGS,\n" " \"Return the name, combining the first and last name\"\n" " },\n" " {NULL} /* Sentinel */\n" "};\n" "\n" "static PyTypeObject CustomType = {\n" " .ob_base = PyVarObject_HEAD_INIT(NULL, 0)\n" " .tp_name = \"custom2.Custom\",\n" " .tp_doc = PyDoc_STR(\"Custom objects\"),\n" " .tp_basicsize = sizeof(CustomObject),\n" " .tp_itemsize = 0,\n" " .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,\n" " .tp_new = Custom_new,\n" " .tp_init = (initproc) Custom_init,\n" " .tp_dealloc = (destructor) Custom_dealloc,\n" " .tp_members = Custom_members,\n" " .tp_methods = Custom_methods,\n" "};\n" "\n" "static PyModuleDef custommodule = {\n" " .m_base =PyModuleDef_HEAD_INIT,\n" " .m_name = \"custom2\",\n" " .m_doc = \"Example module that creates an extension type.\",\n" " .m_size = -1,\n" "};\n" "\n" "PyMODINIT_FUNC\n" "PyInit_custom2(void)\n" "{\n" " PyObject *m;\n" " if (PyType_Ready(&CustomType) < 0)\n" " return NULL;\n" "\n" " m = PyModule_Create(&custommodule);\n" " if (m == NULL)\n" " return NULL;\n" "\n" " if (PyModule_AddObjectRef(m, \"Custom\", (PyObject *) &CustomType) < 0) " "{\n" " Py_DECREF(m);\n" " return NULL;\n" " }\n" "\n" " return m;\n" "}\n" msgstr "" #: ../Doc/extending/newtypes_tutorial.rst:234 msgid "This version of the module has a number of changes." msgstr "Esta versión del módulo tiene una serie de cambios." #: ../Doc/extending/newtypes_tutorial.rst:236 #, fuzzy msgid "" "The :class:`!Custom` type now has three data attributes in its C struct, " "*first*, *last*, and *number*. The *first* and *last* variables are Python " "strings containing first and last names. The *number* attribute is a C " "integer." msgstr "" "El tipo :class:`Custom` ahora tiene tres atributos de datos en su estructura " "C, *first*, *last* y *number*. Las variables *first* y *last* son cadenas de " "caracteres de Python que contienen nombres y apellidos. El atributo *number* " "es un entero C." #: ../Doc/extending/newtypes_tutorial.rst:240 msgid "The object structure is updated accordingly::" msgstr "La estructura del objeto se actualiza en consecuencia::" #: ../Doc/extending/newtypes_tutorial.rst:242 msgid "" "typedef struct {\n" " PyObject_HEAD\n" " PyObject *first; /* first name */\n" " PyObject *last; /* last name */\n" " int number;\n" "} CustomObject;" msgstr "" #: ../Doc/extending/newtypes_tutorial.rst:249 msgid "" "Because we now have data to manage, we have to be more careful about object " "allocation and deallocation. At a minimum, we need a deallocation method::" msgstr "" "Debido a que ahora tenemos datos para administrar, debemos ser más " "cuidadosos con la asignación de objetos y la desasignación. Como mínimo, " "necesitamos un método de desasignación::" #: ../Doc/extending/newtypes_tutorial.rst:252 msgid "" "static void\n" "Custom_dealloc(CustomObject *self)\n" "{\n" " Py_XDECREF(self->first);\n" " Py_XDECREF(self->last);\n" " Py_TYPE(self)->tp_free((PyObject *) self);\n" "}" msgstr "" #: ../Doc/extending/newtypes_tutorial.rst:260 msgid "which is assigned to the :c:member:`~PyTypeObject.tp_dealloc` member::" msgstr "que se asigna al miembro :c:member:`~PyTypeObject.tp_dealloc`::" #: ../Doc/extending/newtypes_tutorial.rst:262 msgid ".tp_dealloc = (destructor) Custom_dealloc," msgstr "" #: ../Doc/extending/newtypes_tutorial.rst:264 #, fuzzy msgid "" "This method first clears the reference counts of the two Python attributes. :" "c:func:`Py_XDECREF` correctly handles the case where its argument is " "``NULL`` (which might happen here if ``tp_new`` failed midway). It then " "calls the :c:member:`~PyTypeObject.tp_free` member of the object's type " "(computed by ``Py_TYPE(self)``) to free the object's memory. Note that the " "object's type might not be :class:`!CustomType`, because the object may be " "an instance of a subclass." msgstr "" "Este método primero borra los recuentos de referencia de los dos atributos " "de Python. :c:func:`Py_XDECREF` maneja correctamente el caso donde su " "argumento es ``NULL`` (lo que podría ocurrir aquí si ``tp_new`` fallara a " "mitad de camino). Luego llama al miembro :c:member:`~PyTypeObject.tp_free` " "del tipo de objeto (calculado por ``Py_TYPE(self)``) para liberar la memoria " "del objeto. Tenga en cuenta que el tipo de objeto podría no ser :class:" "`CustomType`, porque el objeto puede ser una instancia de una subclase." #: ../Doc/extending/newtypes_tutorial.rst:273 msgid "" "The explicit cast to ``destructor`` above is needed because we defined " "``Custom_dealloc`` to take a ``CustomObject *`` argument, but the " "``tp_dealloc`` function pointer expects to receive a ``PyObject *`` " "argument. Otherwise, the compiler will emit a warning. This is object-" "oriented polymorphism, in C!" msgstr "" "La conversión explícita a ``destructor`` anterior es necesaria porque " "definimos ``Custom_dealloc`` para tomar un argumento ``CustomObject *``, " "pero el puntero de función ``tp_dealloc`` espera recibir un argumento " "``PyObject *``. De lo contrario, el compilador emitirá una advertencia. Este " "es un polimorfismo orientado a objetos, en C!" #: ../Doc/extending/newtypes_tutorial.rst:279 msgid "" "We want to make sure that the first and last names are initialized to empty " "strings, so we provide a ``tp_new`` implementation::" msgstr "" "Queremos asegurarnos de que el nombre y el apellido se inicialicen en " "cadenas de caracteres vacías, por lo que proporcionamos una implementación " "``tp_new``::" #: ../Doc/extending/newtypes_tutorial.rst:282 msgid "" "static PyObject *\n" "Custom_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\n" "{\n" " CustomObject *self;\n" " self = (CustomObject *) type->tp_alloc(type, 0);\n" " if (self != NULL) {\n" " self->first = PyUnicode_FromString(\"\");\n" " if (self->first == NULL) {\n" " Py_DECREF(self);\n" " return NULL;\n" " }\n" " self->last = PyUnicode_FromString(\"\");\n" " if (self->last == NULL) {\n" " Py_DECREF(self);\n" " return NULL;\n" " }\n" " self->number = 0;\n" " }\n" " return (PyObject *) self;\n" "}" msgstr "" #: ../Doc/extending/newtypes_tutorial.rst:303 msgid "and install it in the :c:member:`~PyTypeObject.tp_new` member::" msgstr "e instalarlo en el miembro :c:member:`~PyTypeObject.tp_new`::" #: ../Doc/extending/newtypes_tutorial.rst:305 msgid ".tp_new = Custom_new," msgstr "" #: ../Doc/extending/newtypes_tutorial.rst:307 #, fuzzy msgid "" "The ``tp_new`` handler is responsible for creating (as opposed to " "initializing) objects of the type. It is exposed in Python as the :meth:" "`~object.__new__` method. It is not required to define a ``tp_new`` member, " "and indeed many extension types will simply reuse :c:func:" "`PyType_GenericNew` as done in the first version of the :class:`!Custom` " "type above. In this case, we use the ``tp_new`` handler to initialize the " "``first`` and ``last`` attributes to non-``NULL`` default values." msgstr "" "El controlador ``tp_new`` es responsable de crear (en lugar de inicializar) " "objetos del tipo. Está expuesto en Python como el método :meth:`__new__`. No " "es necesario definir un miembro ``tp_new``, y de hecho muchos tipos de " "extensiones simplemente reutilizarán :c:func:`PyType_GenericNew` como se " "hizo en la primera versión del tipo ``Personalizado`` anterior. En este " "caso, usamos el controlador ``tp_new`` para inicializar los atributos " "``first`` y ``last`` a valores predeterminados que no sean ``NULL``." #: ../Doc/extending/newtypes_tutorial.rst:315 msgid "" "``tp_new`` is passed the type being instantiated (not necessarily " "``CustomType``, if a subclass is instantiated) and any arguments passed when " "the type was called, and is expected to return the instance created. " "``tp_new`` handlers always accept positional and keyword arguments, but they " "often ignore the arguments, leaving the argument handling to initializer (a." "k.a. ``tp_init`` in C or ``__init__`` in Python) methods." msgstr "" "``tp_new`` se pasa el tipo que se instancia (no necesariamente " "``CustomType``, si se instancia una subclase) y cualquier argumento pasado " "cuando se llamó al tipo, y se espera que retorna la instancia creada. Los " "manejadores ``tp_new`` siempre aceptan argumentos posicionales y de palabras " "clave, pero a menudo ignoran los argumentos, dejando el manejo de argumentos " "al inicializador (también conocido como, ``tp_init`` en C o ``__init__`` en " "Python)." #: ../Doc/extending/newtypes_tutorial.rst:323 msgid "" "``tp_new`` shouldn't call ``tp_init`` explicitly, as the interpreter will do " "it itself." msgstr "" "``tp_new`` no debería llamar explícitamente a ``tp_init``, ya que el " "intérprete lo hará por sí mismo." #: ../Doc/extending/newtypes_tutorial.rst:326 msgid "" "The ``tp_new`` implementation calls the :c:member:`~PyTypeObject.tp_alloc` " "slot to allocate memory::" msgstr "" "La implementación ``tp_new`` llama al :c:member:`~PyTypeObject.tp_alloc` " "para asignar memoria::" #: ../Doc/extending/newtypes_tutorial.rst:329 msgid "self = (CustomObject *) type->tp_alloc(type, 0);" msgstr "" #: ../Doc/extending/newtypes_tutorial.rst:331 msgid "" "Since memory allocation may fail, we must check the :c:member:`~PyTypeObject." "tp_alloc` result against ``NULL`` before proceeding." msgstr "" "Como la asignación de memoria puede fallar, debemos verificar el resultado :" "c:member:`~PyTypeObject.tp_alloc` contra ``NULL`` antes de continuar." #: ../Doc/extending/newtypes_tutorial.rst:335 msgid "" "We didn't fill the :c:member:`~PyTypeObject.tp_alloc` slot ourselves. " "Rather :c:func:`PyType_Ready` fills it for us by inheriting it from our base " "class, which is :class:`object` by default. Most types use the default " "allocation strategy." msgstr "" "No llenamos la ranura :c:member:`~PyTypeObject.tp_alloc` nosotros mismos. " "Más bien :c:func:`PyType_Ready` lo llena para nosotros al heredarlo de " "nuestra clase base, que es :class:`object` por defecto. La mayoría de los " "tipos utilizan la estrategia de asignación predeterminada." #: ../Doc/extending/newtypes_tutorial.rst:341 #, fuzzy msgid "" "If you are creating a co-operative :c:member:`~PyTypeObject.tp_new` (one " "that calls a base type's :c:member:`~PyTypeObject.tp_new` or :meth:`~object." "__new__`), you must *not* try to determine what method to call using method " "resolution order at runtime. Always statically determine what type you are " "going to call, and call its :c:member:`~PyTypeObject.tp_new` directly, or " "via ``type->tp_base->tp_new``. If you do not do this, Python subclasses of " "your type that also inherit from other Python-defined classes may not work " "correctly. (Specifically, you may not be able to create instances of such " "subclasses without getting a :exc:`TypeError`.)" msgstr "" "Si está creando una cooperativa :c:member:`~PyTypeObject.tp_new` (una que " "llama a un tipo base :c:member:`~PyTypeObject.tp_new` o :meth:`__new__`), " "*no* debe intentar determinar a qué método llamar utilizando el orden de " "resolución del método en tiempo de ejecución. Siempre determine " "estáticamente a qué tipo va a llamar, y llame a su :c:member:`~PyTypeObject." "tp_new` directamente, o mediante ``type->tp_base->tp_new``. Si no hace esto, " "las subclases de Python de su tipo que también heredan de otras clases " "definidas por Python pueden no funcionar correctamente. (Específicamente, es " "posible que no pueda crear instancias de tales subclases sin obtener un :exc:" "`TypeError`)." #: ../Doc/extending/newtypes_tutorial.rst:351 msgid "" "We also define an initialization function which accepts arguments to provide " "initial values for our instance::" msgstr "" "También definimos una función de inicialización que acepta argumentos para " "proporcionar valores iniciales para nuestra instancia::" #: ../Doc/extending/newtypes_tutorial.rst:354 msgid "" "static int\n" "Custom_init(CustomObject *self, PyObject *args, PyObject *kwds)\n" "{\n" " static char *kwlist[] = {\"first\", \"last\", \"number\", NULL};\n" " PyObject *first = NULL, *last = NULL, *tmp;\n" "\n" " if (!PyArg_ParseTupleAndKeywords(args, kwds, \"|OOi\", kwlist,\n" " &first, &last,\n" " &self->number))\n" " return -1;\n" "\n" " if (first) {\n" " tmp = self->first;\n" " Py_INCREF(first);\n" " self->first = first;\n" " Py_XDECREF(tmp);\n" " }\n" " if (last) {\n" " tmp = self->last;\n" " Py_INCREF(last);\n" " self->last = last;\n" " Py_XDECREF(tmp);\n" " }\n" " return 0;\n" "}" msgstr "" #: ../Doc/extending/newtypes_tutorial.rst:380 msgid "by filling the :c:member:`~PyTypeObject.tp_init` slot. ::" msgstr "rellenando la ranura :c:member:`~PyTypeObject.tp_init`. ::" #: ../Doc/extending/newtypes_tutorial.rst:382 msgid ".tp_init = (initproc) Custom_init," msgstr "" #: ../Doc/extending/newtypes_tutorial.rst:384 #, fuzzy msgid "" "The :c:member:`~PyTypeObject.tp_init` slot is exposed in Python as the :meth:" "`~object.__init__` method. It is used to initialize an object after it's " "created. Initializers always accept positional and keyword arguments, and " "they should return either ``0`` on success or ``-1`` on error." msgstr "" "La ranura :c:member:`~PyTypeObject.tp_init` está expuesta en Python como el " "método :meth:`__init__`. Se utiliza para inicializar un objeto una vez " "creado. Los inicializadores siempre aceptan argumentos posicionales y de " "palabras clave, y deben retornar ``0`` en caso de éxito o ``-1`` en caso de " "error." #: ../Doc/extending/newtypes_tutorial.rst:389 #, fuzzy msgid "" "Unlike the ``tp_new`` handler, there is no guarantee that ``tp_init`` is " "called at all (for example, the :mod:`pickle` module by default doesn't " "call :meth:`~object.__init__` on unpickled instances). It can also be " "called multiple times. Anyone can call the :meth:`!__init__` method on our " "objects. For this reason, we have to be extra careful when assigning the " "new attribute values. We might be tempted, for example to assign the " "``first`` member like this::" msgstr "" "A diferencia del controlador ``tp_new``, no hay garantía de que se llame a " "``tp_init`` (por ejemplo, el módulo :mod:`pickle` por defecto no llama a :" "meth:`__init__` en instancias no controladas ) También se puede llamar " "varias veces. Cualquiera puede llamar al método :meth:`__init__` en nuestros " "objetos. Por esta razón, debemos tener mucho cuidado al asignar los nuevos " "valores de atributo. Podríamos sentirnos tentados, por ejemplo, a asignar el " "``primer`` miembro de esta manera:" #: ../Doc/extending/newtypes_tutorial.rst:397 msgid "" "if (first) {\n" " Py_XDECREF(self->first);\n" " Py_INCREF(first);\n" " self->first = first;\n" "}" msgstr "" #: ../Doc/extending/newtypes_tutorial.rst:403 msgid "" "But this would be risky. Our type doesn't restrict the type of the " "``first`` member, so it could be any kind of object. It could have a " "destructor that causes code to be executed that tries to access the " "``first`` member; or that destructor could release the :term:`Global " "interpreter Lock ` and let arbitrary code run in other threads that " "accesses and modifies our object." msgstr "" "Pero esto sería arriesgado. Nuestro tipo no restringe el tipo del ``primer`` " "miembro, por lo que podría ser cualquier tipo de objeto. Podría tener un " "destructor que haga que se ejecute código que intente acceder al ``primer`` " "miembro; o ese destructor podría liberar el :term:`Global Interpreter Lock " "` y permite que se ejecute código arbitrario en otros hilos que acceden " "y modifican nuestro objeto." #: ../Doc/extending/newtypes_tutorial.rst:410 msgid "" "To be paranoid and protect ourselves against this possibility, we almost " "always reassign members before decrementing their reference counts. When " "don't we have to do this?" msgstr "" "Para ser paranoicos y protegernos de esta posibilidad, casi siempre " "reasignamos miembros antes de disminuir sus recuentos de referencias. " "¿Cuándo no tenemos que hacer esto?" #: ../Doc/extending/newtypes_tutorial.rst:414 msgid "when we absolutely know that the reference count is greater than 1;" msgstr "" "cuando sabemos absolutamente que el recuento de referencia es mayor que 1;" #: ../Doc/extending/newtypes_tutorial.rst:416 msgid "" "when we know that deallocation of the object [#]_ will neither release the :" "term:`GIL` nor cause any calls back into our type's code;" msgstr "" "cuando sabemos que la desasignación del objeto [#]_ no liberará el :term:" "`GIL` ni causará ninguna llamada al código de nuestro tipo;" #: ../Doc/extending/newtypes_tutorial.rst:419 msgid "" "when decrementing a reference count in a :c:member:`~PyTypeObject." "tp_dealloc` handler on a type which doesn't support cyclic garbage " "collection [#]_." msgstr "" "al disminuir un recuento de referencias en un manejador :c:member:" "`~PyTypeObject.tp_dealloc` en un tipo que no admite la recolección de basura " "cíclica [#]_." #: ../Doc/extending/newtypes_tutorial.rst:422 msgid "" "We want to expose our instance variables as attributes. There are a number " "of ways to do that. The simplest way is to define member definitions::" msgstr "" "Queremos exponer nuestras variables de instancia como atributos. Hay varias " "formas de hacerlo. La forma más simple es definir definiciones de miembros::" #: ../Doc/extending/newtypes_tutorial.rst:425 msgid "" "static PyMemberDef Custom_members[] = {\n" " {\"first\", Py_T_OBJECT_EX, offsetof(CustomObject, first), 0,\n" " \"first name\"},\n" " {\"last\", Py_T_OBJECT_EX, offsetof(CustomObject, last), 0,\n" " \"last name\"},\n" " {\"number\", Py_T_INT, offsetof(CustomObject, number), 0,\n" " \"custom number\"},\n" " {NULL} /* Sentinel */\n" "};" msgstr "" #: ../Doc/extending/newtypes_tutorial.rst:435 msgid "" "and put the definitions in the :c:member:`~PyTypeObject.tp_members` slot::" msgstr "" "y poner las definiciones en la ranura :c:member:`~PyTypeObject.tp_members`::" #: ../Doc/extending/newtypes_tutorial.rst:437 msgid ".tp_members = Custom_members," msgstr "" #: ../Doc/extending/newtypes_tutorial.rst:439 msgid "" "Each member definition has a member name, type, offset, access flags and " "documentation string. See the :ref:`Generic-Attribute-Management` section " "below for details." msgstr "" "Cada definición de miembro tiene un nombre de miembro, tipo, desplazamiento, " "banderas de acceso y cadena de caracteres de documentación. Consulte la " "sección :ref:`Generic-Attribute-Management` a continuación para obtener más " "detalles." #: ../Doc/extending/newtypes_tutorial.rst:443 msgid "" "A disadvantage of this approach is that it doesn't provide a way to restrict " "the types of objects that can be assigned to the Python attributes. We " "expect the first and last names to be strings, but any Python objects can be " "assigned. Further, the attributes can be deleted, setting the C pointers to " "``NULL``. Even though we can make sure the members are initialized to non-" "``NULL`` values, the members can be set to ``NULL`` if the attributes are " "deleted." msgstr "" "Una desventaja de este enfoque es que no proporciona una forma de restringir " "los tipos de objetos que se pueden asignar a los atributos de Python. " "Esperamos que el nombre y el apellido sean cadenas, pero se pueden asignar " "objetos de Python. Además, los atributos se pueden eliminar, configurando " "los punteros C en ``NULL``. Si bien podemos asegurarnos de que los miembros " "se inicialicen en valores que no sean ``NULL``, los miembros se pueden " "establecer en ``NULL`` si se eliminan los atributos." #: ../Doc/extending/newtypes_tutorial.rst:450 #, fuzzy msgid "" "We define a single method, :meth:`!Custom.name`, that outputs the objects " "name as the concatenation of the first and last names. ::" msgstr "" "Definimos un método único, :meth:`Custom.name()`, que genera el nombre de " "los objetos como la concatenación de los nombres y apellidos. ::" #: ../Doc/extending/newtypes_tutorial.rst:453 msgid "" "static PyObject *\n" "Custom_name(CustomObject *self, PyObject *Py_UNUSED(ignored))\n" "{\n" " if (self->first == NULL) {\n" " PyErr_SetString(PyExc_AttributeError, \"first\");\n" " return NULL;\n" " }\n" " if (self->last == NULL) {\n" " PyErr_SetString(PyExc_AttributeError, \"last\");\n" " return NULL;\n" " }\n" " return PyUnicode_FromFormat(\"%S %S\", self->first, self->last);\n" "}" msgstr "" #: ../Doc/extending/newtypes_tutorial.rst:467 #, fuzzy msgid "" "The method is implemented as a C function that takes a :class:`!Custom` (or :" "class:`!Custom` subclass) instance as the first argument. Methods always " "take an instance as the first argument. Methods often take positional and " "keyword arguments as well, but in this case we don't take any and don't need " "to accept a positional argument tuple or keyword argument dictionary. This " "method is equivalent to the Python method:" msgstr "" "El método se implementa como una función C que toma una instancia de :class:" "`Custom` (o subclase :class:`Custom`) como primer argumento. Los métodos " "siempre toman una instancia como primer argumento. Los métodos a menudo " "también toman argumentos posicionales y de palabras clave, pero en este caso " "no tomamos ninguno y no necesitamos aceptar una tupla de argumentos " "posicionales o un diccionario de argumentos de palabras clave. Este método " "es equivalente al método Python:" #: ../Doc/extending/newtypes_tutorial.rst:474 #, python-format msgid "" "def name(self):\n" " return \"%s %s\" % (self.first, self.last)" msgstr "" #: ../Doc/extending/newtypes_tutorial.rst:479 #, fuzzy msgid "" "Note that we have to check for the possibility that our :attr:`!first` and :" "attr:`!last` members are ``NULL``. This is because they can be deleted, in " "which case they are set to ``NULL``. It would be better to prevent deletion " "of these attributes and to restrict the attribute values to be strings. " "We'll see how to do that in the next section." msgstr "" "Tenga en cuenta que tenemos que verificar la posibilidad de que nuestros " "miembros :attr:`first` y :attr:`last` sean ``NULL``. Esto se debe a que se " "pueden eliminar, en cuyo caso se establecen en ``NULL``. Sería mejor evitar " "la eliminación de estos atributos y restringir los valores de los atributos " "para que sean cadenas de caracteres. Veremos cómo hacerlo en la siguiente " "sección." #: ../Doc/extending/newtypes_tutorial.rst:485 msgid "" "Now that we've defined the method, we need to create an array of method " "definitions::" msgstr "" "Ahora que hemos definido el método, necesitamos crear un arreglo de " "definiciones de métodos::" #: ../Doc/extending/newtypes_tutorial.rst:488 msgid "" "static PyMethodDef Custom_methods[] = {\n" " {\"name\", (PyCFunction) Custom_name, METH_NOARGS,\n" " \"Return the name, combining the first and last name\"\n" " },\n" " {NULL} /* Sentinel */\n" "};" msgstr "" #: ../Doc/extending/newtypes_tutorial.rst:495 #, fuzzy msgid "" "(note that we used the :c:macro:`METH_NOARGS` flag to indicate that the " "method is expecting no arguments other than *self*)" msgstr "" "(tenga en cuenta que usamos el indicador :const:`METH_NOARGS` para indicar " "que el método no espera argumentos distintos de *self*)" #: ../Doc/extending/newtypes_tutorial.rst:498 msgid "and assign it to the :c:member:`~PyTypeObject.tp_methods` slot::" msgstr "y asignarlo a la ranura :c:member:`~PyTypeObject.tp_methods`::" #: ../Doc/extending/newtypes_tutorial.rst:500 msgid ".tp_methods = Custom_methods," msgstr "" #: ../Doc/extending/newtypes_tutorial.rst:502 #, fuzzy msgid "" "Finally, we'll make our type usable as a base class for subclassing. We've " "written our methods carefully so far so that they don't make any assumptions " "about the type of the object being created or used, so all we need to do is " "to add the :c:macro:`Py_TPFLAGS_BASETYPE` to our class flag definition::" msgstr "" "Finalmente, haremos que nuestro tipo sea utilizable como una clase base para " "la subclase. Hemos escrito nuestros métodos cuidadosamente hasta ahora para " "que no hagan suposiciones sobre el tipo de objeto que se está creando o " "utilizando, por lo que todo lo que tenemos que hacer es agregar :const:" "`Py_TPFLAGS_BASETYPE` a nuestra definición de bandera de clase::" #: ../Doc/extending/newtypes_tutorial.rst:507 msgid ".tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE," msgstr "" #: ../Doc/extending/newtypes_tutorial.rst:509 #, fuzzy msgid "" "We rename :c:func:`!PyInit_custom` to :c:func:`!PyInit_custom2`, update the " "module name in the :c:type:`PyModuleDef` struct, and update the full class " "name in the :c:type:`PyTypeObject` struct." msgstr "" "Cambiamos el nombre de :c:func:`PyInit_custom` a :c:func:`PyInit_custom2`, " "actualizamos el nombre del módulo en la estructura :c:type:`PyModuleDef` y " "actualizamos el nombre completo de la clase en la estructura :c:type:" "`PyTypeObject`." #: ../Doc/extending/newtypes_tutorial.rst:513 #, fuzzy msgid "Finally, we update our :file:`setup.py` file to include the new module," msgstr "" "Finalmente, actualizamos nuestro archivo :file:`setup.py` para construir el " "nuevo módulo:" #: ../Doc/extending/newtypes_tutorial.rst:515 msgid "" "from setuptools import Extension, setup\n" "setup(ext_modules=[\n" " Extension(\"custom\", [\"custom.c\"]),\n" " Extension(\"custom2\", [\"custom2.c\"]),\n" "])" msgstr "" #: ../Doc/extending/newtypes_tutorial.rst:523 msgid "and then we re-install so that we can ``import custom2``:" msgstr "" #: ../Doc/extending/newtypes_tutorial.rst:530 msgid "Providing finer control over data attributes" msgstr "Proporcionar un control más preciso sobre los atributos de datos" #: ../Doc/extending/newtypes_tutorial.rst:532 #, fuzzy msgid "" "In this section, we'll provide finer control over how the :attr:`!first` " "and :attr:`!last` attributes are set in the :class:`!Custom` example. In the " "previous version of our module, the instance variables :attr:`!first` and :" "attr:`!last` could be set to non-string values or even deleted. We want to " "make sure that these attributes always contain strings." msgstr "" "En esta sección, proporcionaremos un control más preciso sobre cómo se " "establecen los atributos :attr:`first` y :attr:`last` en el ejemplo :class:" "`Custom`. En la versión anterior de nuestro módulo, las variables de " "instancia :attr:`first` y :attr:`last` podrían establecerse en valores que " "no sean de cadena o incluso eliminarse. Queremos asegurarnos de que estos " "atributos siempre contengan cadenas." #: ../Doc/extending/newtypes_tutorial.rst:538 msgid "" "#define PY_SSIZE_T_CLEAN\n" "#include \n" "#include /* for offsetof() */\n" "\n" "typedef struct {\n" " PyObject_HEAD\n" " PyObject *first; /* first name */\n" " PyObject *last; /* last name */\n" " int number;\n" "} CustomObject;\n" "\n" "static void\n" "Custom_dealloc(CustomObject *self)\n" "{\n" " Py_XDECREF(self->first);\n" " Py_XDECREF(self->last);\n" " Py_TYPE(self)->tp_free((PyObject *) self);\n" "}\n" "\n" "static PyObject *\n" "Custom_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\n" "{\n" " CustomObject *self;\n" " self = (CustomObject *) type->tp_alloc(type, 0);\n" " if (self != NULL) {\n" " self->first = PyUnicode_FromString(\"\");\n" " if (self->first == NULL) {\n" " Py_DECREF(self);\n" " return NULL;\n" " }\n" " self->last = PyUnicode_FromString(\"\");\n" " if (self->last == NULL) {\n" " Py_DECREF(self);\n" " return NULL;\n" " }\n" " self->number = 0;\n" " }\n" " return (PyObject *) self;\n" "}\n" "\n" "static int\n" "Custom_init(CustomObject *self, PyObject *args, PyObject *kwds)\n" "{\n" " static char *kwlist[] = {\"first\", \"last\", \"number\", NULL};\n" " PyObject *first = NULL, *last = NULL;\n" "\n" " if (!PyArg_ParseTupleAndKeywords(args, kwds, \"|UUi\", kwlist,\n" " &first, &last,\n" " &self->number))\n" " return -1;\n" "\n" " if (first) {\n" " Py_SETREF(self->first, Py_NewRef(first));\n" " }\n" " if (last) {\n" " Py_SETREF(self->last, Py_NewRef(last));\n" " }\n" " return 0;\n" "}\n" "\n" "static PyMemberDef Custom_members[] = {\n" " {\"number\", Py_T_INT, offsetof(CustomObject, number), 0,\n" " \"custom number\"},\n" " {NULL} /* Sentinel */\n" "};\n" "\n" "static PyObject *\n" "Custom_getfirst(CustomObject *self, void *closure)\n" "{\n" " return Py_NewRef(self->first);\n" "}\n" "\n" "static int\n" "Custom_setfirst(CustomObject *self, PyObject *value, void *closure)\n" "{\n" " if (value == NULL) {\n" " PyErr_SetString(PyExc_TypeError, \"Cannot delete the first " "attribute\");\n" " return -1;\n" " }\n" " if (!PyUnicode_Check(value)) {\n" " PyErr_SetString(PyExc_TypeError,\n" " \"The first attribute value must be a string\");\n" " return -1;\n" " }\n" " Py_SETREF(self->first, Py_NewRef(value));\n" " return 0;\n" "}\n" "\n" "static PyObject *\n" "Custom_getlast(CustomObject *self, void *closure)\n" "{\n" " return Py_NewRef(self->last);\n" "}\n" "\n" "static int\n" "Custom_setlast(CustomObject *self, PyObject *value, void *closure)\n" "{\n" " if (value == NULL) {\n" " PyErr_SetString(PyExc_TypeError, \"Cannot delete the last " "attribute\");\n" " return -1;\n" " }\n" " if (!PyUnicode_Check(value)) {\n" " PyErr_SetString(PyExc_TypeError,\n" " \"The last attribute value must be a string\");\n" " return -1;\n" " }\n" " Py_SETREF(self->last, Py_NewRef(value));\n" " return 0;\n" "}\n" "\n" "static PyGetSetDef Custom_getsetters[] = {\n" " {\"first\", (getter) Custom_getfirst, (setter) Custom_setfirst,\n" " \"first name\", NULL},\n" " {\"last\", (getter) Custom_getlast, (setter) Custom_setlast,\n" " \"last name\", NULL},\n" " {NULL} /* Sentinel */\n" "};\n" "\n" "static PyObject *\n" "Custom_name(CustomObject *self, PyObject *Py_UNUSED(ignored))\n" "{\n" " return PyUnicode_FromFormat(\"%S %S\", self->first, self->last);\n" "}\n" "\n" "static PyMethodDef Custom_methods[] = {\n" " {\"name\", (PyCFunction) Custom_name, METH_NOARGS,\n" " \"Return the name, combining the first and last name\"\n" " },\n" " {NULL} /* Sentinel */\n" "};\n" "\n" "static PyTypeObject CustomType = {\n" " .ob_base = PyVarObject_HEAD_INIT(NULL, 0)\n" " .tp_name = \"custom3.Custom\",\n" " .tp_doc = PyDoc_STR(\"Custom objects\"),\n" " .tp_basicsize = sizeof(CustomObject),\n" " .tp_itemsize = 0,\n" " .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,\n" " .tp_new = Custom_new,\n" " .tp_init = (initproc) Custom_init,\n" " .tp_dealloc = (destructor) Custom_dealloc,\n" " .tp_members = Custom_members,\n" " .tp_methods = Custom_methods,\n" " .tp_getset = Custom_getsetters,\n" "};\n" "\n" "static PyModuleDef custommodule = {\n" " .m_base = PyModuleDef_HEAD_INIT,\n" " .m_name = \"custom3\",\n" " .m_doc = \"Example module that creates an extension type.\",\n" " .m_size = -1,\n" "};\n" "\n" "PyMODINIT_FUNC\n" "PyInit_custom3(void)\n" "{\n" " PyObject *m;\n" " if (PyType_Ready(&CustomType) < 0)\n" " return NULL;\n" "\n" " m = PyModule_Create(&custommodule);\n" " if (m == NULL)\n" " return NULL;\n" "\n" " if (PyModule_AddObjectRef(m, \"Custom\", (PyObject *) &CustomType) < 0) " "{\n" " Py_DECREF(m);\n" " return NULL;\n" " }\n" "\n" " return m;\n" "}\n" msgstr "" #: ../Doc/extending/newtypes_tutorial.rst:541 #, fuzzy msgid "" "To provide greater control, over the :attr:`!first` and :attr:`!last` " "attributes, we'll use custom getter and setter functions. Here are the " "functions for getting and setting the :attr:`!first` attribute::" msgstr "" "Para proporcionar un mayor control sobre los atributos :attr:`first` y :attr:" "`last`, usaremos funciones personalizadas *getter* y *setter*. Estas son las " "funciones para obtener y configurar el atributo :attr:`first`::" #: ../Doc/extending/newtypes_tutorial.rst:545 msgid "" "static PyObject *\n" "Custom_getfirst(CustomObject *self, void *closure)\n" "{\n" " Py_INCREF(self->first);\n" " return self->first;\n" "}\n" "\n" "static int\n" "Custom_setfirst(CustomObject *self, PyObject *value, void *closure)\n" "{\n" " PyObject *tmp;\n" " if (value == NULL) {\n" " PyErr_SetString(PyExc_TypeError, \"Cannot delete the first " "attribute\");\n" " return -1;\n" " }\n" " if (!PyUnicode_Check(value)) {\n" " PyErr_SetString(PyExc_TypeError,\n" " \"The first attribute value must be a string\");\n" " return -1;\n" " }\n" " tmp = self->first;\n" " Py_INCREF(value);\n" " self->first = value;\n" " Py_DECREF(tmp);\n" " return 0;\n" "}" msgstr "" #: ../Doc/extending/newtypes_tutorial.rst:572 #, fuzzy msgid "" "The getter function is passed a :class:`!Custom` object and a \"closure\", " "which is a void pointer. In this case, the closure is ignored. (The " "closure supports an advanced usage in which definition data is passed to the " "getter and setter. This could, for example, be used to allow a single set of " "getter and setter functions that decide the attribute to get or set based on " "data in the closure.)" msgstr "" "La función *getter* se pasa al objeto :class:`Custom` y un \"cierre\" " "(*closure*), que es un puntero nulo. En este caso, se ignora el cierre. (El " "cierre admite un uso avanzado en el que los datos de definición se pasan al " "captador y al definidor. Esto podría, por ejemplo, usarse para permitir un " "solo conjunto de funciones de captador y definidor que deciden que el " "atributo se obtenga o establezca en función de los datos en el cierre.)" #: ../Doc/extending/newtypes_tutorial.rst:578 #, fuzzy msgid "" "The setter function is passed the :class:`!Custom` object, the new value, " "and the closure. The new value may be ``NULL``, in which case the attribute " "is being deleted. In our setter, we raise an error if the attribute is " "deleted or if its new value is not a string." msgstr "" "La función *setter* pasa el objeto :class:`Custom`, el nuevo valor y el " "cierre. El nuevo valor puede ser ``NULL``, en cuyo caso se está eliminando " "el atributo. En nuestro *setter*, generamos un error si el atributo se " "elimina o si su nuevo valor no es una cadena." #: ../Doc/extending/newtypes_tutorial.rst:583 msgid "We create an array of :c:type:`PyGetSetDef` structures::" msgstr "Creamos un arreglo de estructuras :c:type:`PyGetSetDef`::" #: ../Doc/extending/newtypes_tutorial.rst:585 msgid "" "static PyGetSetDef Custom_getsetters[] = {\n" " {\"first\", (getter) Custom_getfirst, (setter) Custom_setfirst,\n" " \"first name\", NULL},\n" " {\"last\", (getter) Custom_getlast, (setter) Custom_setlast,\n" " \"last name\", NULL},\n" " {NULL} /* Sentinel */\n" "};" msgstr "" #: ../Doc/extending/newtypes_tutorial.rst:593 msgid "and register it in the :c:member:`~PyTypeObject.tp_getset` slot::" msgstr "y lo registra en la ranura :c:member:`~PyTypeObject.tp_getset`::" #: ../Doc/extending/newtypes_tutorial.rst:595 msgid ".tp_getset = Custom_getsetters," msgstr "" #: ../Doc/extending/newtypes_tutorial.rst:597 msgid "" "The last item in a :c:type:`PyGetSetDef` structure is the \"closure\" " "mentioned above. In this case, we aren't using a closure, so we just pass " "``NULL``." msgstr "" "El último elemento en la estructura :c:type:`PyGetSetDef` es el \"cierre\" " "(*closure*) mencionado anteriormente. En este caso, no estamos usando un " "cierre, por lo que simplemente pasamos ``NULL``." #: ../Doc/extending/newtypes_tutorial.rst:600 msgid "We also remove the member definitions for these attributes::" msgstr "También eliminamos las definiciones de miembro para estos atributos::" #: ../Doc/extending/newtypes_tutorial.rst:602 msgid "" "static PyMemberDef Custom_members[] = {\n" " {\"number\", Py_T_INT, offsetof(CustomObject, number), 0,\n" " \"custom number\"},\n" " {NULL} /* Sentinel */\n" "};" msgstr "" #: ../Doc/extending/newtypes_tutorial.rst:608 msgid "" "We also need to update the :c:member:`~PyTypeObject.tp_init` handler to only " "allow strings [#]_ to be passed::" msgstr "" "También necesitamos actualizar el manejador :c:member:`~PyTypeObject." "tp_init` para permitir que solo se pasen las cadenas [#]_::" #: ../Doc/extending/newtypes_tutorial.rst:611 msgid "" "static int\n" "Custom_init(CustomObject *self, PyObject *args, PyObject *kwds)\n" "{\n" " static char *kwlist[] = {\"first\", \"last\", \"number\", NULL};\n" " PyObject *first = NULL, *last = NULL, *tmp;\n" "\n" " if (!PyArg_ParseTupleAndKeywords(args, kwds, \"|UUi\", kwlist,\n" " &first, &last,\n" " &self->number))\n" " return -1;\n" "\n" " if (first) {\n" " tmp = self->first;\n" " Py_INCREF(first);\n" " self->first = first;\n" " Py_DECREF(tmp);\n" " }\n" " if (last) {\n" " tmp = self->last;\n" " Py_INCREF(last);\n" " self->last = last;\n" " Py_DECREF(tmp);\n" " }\n" " return 0;\n" "}" msgstr "" #: ../Doc/extending/newtypes_tutorial.rst:637 msgid "" "With these changes, we can assure that the ``first`` and ``last`` members " "are never ``NULL`` so we can remove checks for ``NULL`` values in almost all " "cases. This means that most of the :c:func:`Py_XDECREF` calls can be " "converted to :c:func:`Py_DECREF` calls. The only place we can't change " "these calls is in the ``tp_dealloc`` implementation, where there is the " "possibility that the initialization of these members failed in ``tp_new``." msgstr "" "Con estos cambios, podemos asegurar que los miembros ``primero`` y " "``último`` nunca sean ``NULL``, por lo que podemos eliminar las " "comprobaciones de los valores ``NULL`` en casi todos los casos. Esto " "significa que la mayoría de las llamadas :c:func:`Py_XDECREF` se pueden " "convertir en llamadas :c:func:`Py_DECREF`. El único lugar donde no podemos " "cambiar estas llamadas es en la implementación ``tp_dealloc``, donde existe " "la posibilidad de que la inicialización de estos miembros falle en " "``tp_new``." #: ../Doc/extending/newtypes_tutorial.rst:644 msgid "" "We also rename the module initialization function and module name in the " "initialization function, as we did before, and we add an extra definition to " "the :file:`setup.py` file." msgstr "" "También cambiamos el nombre de la función de inicialización del módulo y el " "nombre del módulo en la función de inicialización, como lo hicimos antes, y " "agregamos una definición adicional al archivo :file:`setup.py`." #: ../Doc/extending/newtypes_tutorial.rst:650 msgid "Supporting cyclic garbage collection" msgstr "Apoyo a la recolección de basura cíclica" #: ../Doc/extending/newtypes_tutorial.rst:652 msgid "" "Python has a :term:`cyclic garbage collector (GC) ` that " "can identify unneeded objects even when their reference counts are not zero. " "This can happen when objects are involved in cycles. For example, consider:" msgstr "" "Python tiene un :term:`recolector de basura cíclico (GC) ` que puede identificar objetos innecesarios incluso cuando sus " "recuentos de referencia no son cero. Esto puede suceder cuando los objetos " "están involucrados en ciclos. Por ejemplo, considere:" #: ../Doc/extending/newtypes_tutorial.rst:656 msgid "" ">>> l = []\n" ">>> l.append(l)\n" ">>> del l" msgstr "" #: ../Doc/extending/newtypes_tutorial.rst:662 msgid "" "In this example, we create a list that contains itself. When we delete it, " "it still has a reference from itself. Its reference count doesn't drop to " "zero. Fortunately, Python's cyclic garbage collector will eventually figure " "out that the list is garbage and free it." msgstr "" "En este ejemplo, creamos una lista que se contiene a sí misma. Cuando lo " "eliminamos, todavía tiene una referencia de sí mismo. Su recuento de " "referencia no cae a cero. Afortunadamente, el recolector cíclico de basura " "de Python finalmente descubrirá que la lista es basura y la liberará." #: ../Doc/extending/newtypes_tutorial.rst:667 #, fuzzy msgid "" "In the second version of the :class:`!Custom` example, we allowed any kind " "of object to be stored in the :attr:`!first` or :attr:`!last` attributes " "[#]_. Besides, in the second and third versions, we allowed subclassing :" "class:`!Custom`, and subclasses may add arbitrary attributes. For any of " "those two reasons, :class:`!Custom` objects can participate in cycles:" msgstr "" "En la segunda versión del ejemplo :class:`Custom`, permitimos que cualquier " "tipo de objeto se almacene en :attr:`first` o :attr:`last` atributos [#]_. " "Además, en la segunda y tercera versión, permitimos subclases :class:" "`Custom`, y las subclases pueden agregar atributos arbitrarios. Por " "cualquiera de esos dos motivos, los objetos :class:`Custom` pueden " "participar en ciclos:" #: ../Doc/extending/newtypes_tutorial.rst:673 msgid "" ">>> import custom3\n" ">>> class Derived(custom3.Custom): pass\n" "...\n" ">>> n = Derived()\n" ">>> n.some_attribute = n" msgstr "" #: ../Doc/extending/newtypes_tutorial.rst:681 #, fuzzy msgid "" "To allow a :class:`!Custom` instance participating in a reference cycle to " "be properly detected and collected by the cyclic GC, our :class:`!Custom` " "type needs to fill two additional slots and to enable a flag that enables " "these slots:" msgstr "" "Para permitir que una instancia de :class:`Custom` que participa en un ciclo " "de referencia sea detectada y recolectada correctamente por el GC cíclico, " "nuestro tipo :class:`Custom` necesita llenar dos espacios adicionales y " "habilitar un indicador que permita estos espacios:" #: ../Doc/extending/newtypes_tutorial.rst:685 msgid "" "#define PY_SSIZE_T_CLEAN\n" "#include \n" "#include /* for offsetof() */\n" "\n" "typedef struct {\n" " PyObject_HEAD\n" " PyObject *first; /* first name */\n" " PyObject *last; /* last name */\n" " int number;\n" "} CustomObject;\n" "\n" "static int\n" "Custom_traverse(CustomObject *self, visitproc visit, void *arg)\n" "{\n" " Py_VISIT(self->first);\n" " Py_VISIT(self->last);\n" " return 0;\n" "}\n" "\n" "static int\n" "Custom_clear(CustomObject *self)\n" "{\n" " Py_CLEAR(self->first);\n" " Py_CLEAR(self->last);\n" " return 0;\n" "}\n" "\n" "static void\n" "Custom_dealloc(CustomObject *self)\n" "{\n" " PyObject_GC_UnTrack(self);\n" " Custom_clear(self);\n" " Py_TYPE(self)->tp_free((PyObject *) self);\n" "}\n" "\n" "static PyObject *\n" "Custom_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\n" "{\n" " CustomObject *self;\n" " self = (CustomObject *) type->tp_alloc(type, 0);\n" " if (self != NULL) {\n" " self->first = PyUnicode_FromString(\"\");\n" " if (self->first == NULL) {\n" " Py_DECREF(self);\n" " return NULL;\n" " }\n" " self->last = PyUnicode_FromString(\"\");\n" " if (self->last == NULL) {\n" " Py_DECREF(self);\n" " return NULL;\n" " }\n" " self->number = 0;\n" " }\n" " return (PyObject *) self;\n" "}\n" "\n" "static int\n" "Custom_init(CustomObject *self, PyObject *args, PyObject *kwds)\n" "{\n" " static char *kwlist[] = {\"first\", \"last\", \"number\", NULL};\n" " PyObject *first = NULL, *last = NULL;\n" "\n" " if (!PyArg_ParseTupleAndKeywords(args, kwds, \"|UUi\", kwlist,\n" " &first, &last,\n" " &self->number))\n" " return -1;\n" "\n" " if (first) {\n" " Py_SETREF(self->first, Py_NewRef(first));\n" " }\n" " if (last) {\n" " Py_SETREF(self->last, Py_NewRef(last));\n" " }\n" " return 0;\n" "}\n" "\n" "static PyMemberDef Custom_members[] = {\n" " {\"number\", Py_T_INT, offsetof(CustomObject, number), 0,\n" " \"custom number\"},\n" " {NULL} /* Sentinel */\n" "};\n" "\n" "static PyObject *\n" "Custom_getfirst(CustomObject *self, void *closure)\n" "{\n" " return Py_NewRef(self->first);\n" "}\n" "\n" "static int\n" "Custom_setfirst(CustomObject *self, PyObject *value, void *closure)\n" "{\n" " if (value == NULL) {\n" " PyErr_SetString(PyExc_TypeError, \"Cannot delete the first " "attribute\");\n" " return -1;\n" " }\n" " if (!PyUnicode_Check(value)) {\n" " PyErr_SetString(PyExc_TypeError,\n" " \"The first attribute value must be a string\");\n" " return -1;\n" " }\n" " Py_XSETREF(self->first, Py_NewRef(value));\n" " return 0;\n" "}\n" "\n" "static PyObject *\n" "Custom_getlast(CustomObject *self, void *closure)\n" "{\n" " return Py_NewRef(self->last);\n" "}\n" "\n" "static int\n" "Custom_setlast(CustomObject *self, PyObject *value, void *closure)\n" "{\n" " if (value == NULL) {\n" " PyErr_SetString(PyExc_TypeError, \"Cannot delete the last " "attribute\");\n" " return -1;\n" " }\n" " if (!PyUnicode_Check(value)) {\n" " PyErr_SetString(PyExc_TypeError,\n" " \"The last attribute value must be a string\");\n" " return -1;\n" " }\n" " Py_XSETREF(self->last, Py_NewRef(value));\n" " return 0;\n" "}\n" "\n" "static PyGetSetDef Custom_getsetters[] = {\n" " {\"first\", (getter) Custom_getfirst, (setter) Custom_setfirst,\n" " \"first name\", NULL},\n" " {\"last\", (getter) Custom_getlast, (setter) Custom_setlast,\n" " \"last name\", NULL},\n" " {NULL} /* Sentinel */\n" "};\n" "\n" "static PyObject *\n" "Custom_name(CustomObject *self, PyObject *Py_UNUSED(ignored))\n" "{\n" " return PyUnicode_FromFormat(\"%S %S\", self->first, self->last);\n" "}\n" "\n" "static PyMethodDef Custom_methods[] = {\n" " {\"name\", (PyCFunction) Custom_name, METH_NOARGS,\n" " \"Return the name, combining the first and last name\"\n" " },\n" " {NULL} /* Sentinel */\n" "};\n" "\n" "static PyTypeObject CustomType = {\n" " .ob_base = PyVarObject_HEAD_INIT(NULL, 0)\n" " .tp_name = \"custom4.Custom\",\n" " .tp_doc = PyDoc_STR(\"Custom objects\"),\n" " .tp_basicsize = sizeof(CustomObject),\n" " .tp_itemsize = 0,\n" " .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | " "Py_TPFLAGS_HAVE_GC,\n" " .tp_new = Custom_new,\n" " .tp_init = (initproc) Custom_init,\n" " .tp_dealloc = (destructor) Custom_dealloc,\n" " .tp_traverse = (traverseproc) Custom_traverse,\n" " .tp_clear = (inquiry) Custom_clear,\n" " .tp_members = Custom_members,\n" " .tp_methods = Custom_methods,\n" " .tp_getset = Custom_getsetters,\n" "};\n" "\n" "static PyModuleDef custommodule = {\n" " .m_base = PyModuleDef_HEAD_INIT,\n" " .m_name = \"custom4\",\n" " .m_doc = \"Example module that creates an extension type.\",\n" " .m_size = -1,\n" "};\n" "\n" "PyMODINIT_FUNC\n" "PyInit_custom4(void)\n" "{\n" " PyObject *m;\n" " if (PyType_Ready(&CustomType) < 0)\n" " return NULL;\n" "\n" " m = PyModule_Create(&custommodule);\n" " if (m == NULL)\n" " return NULL;\n" "\n" " if (PyModule_AddObjectRef(m, \"Custom\", (PyObject *) &CustomType) < 0) " "{\n" " Py_DECREF(m);\n" " return NULL;\n" " }\n" "\n" " return m;\n" "}\n" msgstr "" #: ../Doc/extending/newtypes_tutorial.rst:688 msgid "" "First, the traversal method lets the cyclic GC know about subobjects that " "could participate in cycles::" msgstr "" "Primero, el método transversal permite que el GC cíclico conozca los " "subobjetos que podrían participar en los ciclos::" #: ../Doc/extending/newtypes_tutorial.rst:691 msgid "" "static int\n" "Custom_traverse(CustomObject *self, visitproc visit, void *arg)\n" "{\n" " int vret;\n" " if (self->first) {\n" " vret = visit(self->first, arg);\n" " if (vret != 0)\n" " return vret;\n" " }\n" " if (self->last) {\n" " vret = visit(self->last, arg);\n" " if (vret != 0)\n" " return vret;\n" " }\n" " return 0;\n" "}" msgstr "" #: ../Doc/extending/newtypes_tutorial.rst:708 #, fuzzy msgid "" "For each subobject that can participate in cycles, we need to call the :c:" "func:`!visit` function, which is passed to the traversal method. The :c:func:" "`!visit` function takes as arguments the subobject and the extra argument " "*arg* passed to the traversal method. It returns an integer value that must " "be returned if it is non-zero." msgstr "" "Para cada subobjeto que puede participar en ciclos, necesitamos llamar a la " "función :c:func:`visit`, que se pasa al método transversal. La función :c:" "func:`visit` toma como argumentos el subobjeto y el argumento extra *arg* " "pasados al método transversal. Retorna un valor entero que debe retornarse " "si no es cero." #: ../Doc/extending/newtypes_tutorial.rst:714 msgid "" "Python provides a :c:func:`Py_VISIT` macro that automates calling visit " "functions. With :c:func:`Py_VISIT`, we can minimize the amount of " "boilerplate in ``Custom_traverse``::" msgstr "" "Python proporciona una macro :c:func:`Py_VISIT` que automatiza las funciones " "de visita de llamada. Con :c:func:`Py_VISIT`, podemos minimizar la cantidad " "de repeticiones en ``Custom_traverse``::" #: ../Doc/extending/newtypes_tutorial.rst:718 msgid "" "static int\n" "Custom_traverse(CustomObject *self, visitproc visit, void *arg)\n" "{\n" " Py_VISIT(self->first);\n" " Py_VISIT(self->last);\n" " return 0;\n" "}" msgstr "" #: ../Doc/extending/newtypes_tutorial.rst:727 msgid "" "The :c:member:`~PyTypeObject.tp_traverse` implementation must name its " "arguments exactly *visit* and *arg* in order to use :c:func:`Py_VISIT`." msgstr "" "La implementación :c:member:`~PyTypeObject.tp_traverse` debe nombrar sus " "argumentos exactamente *visit* y *arg* para usar :c:func:`Py_VISIT`." #: ../Doc/extending/newtypes_tutorial.rst:730 msgid "" "Second, we need to provide a method for clearing any subobjects that can " "participate in cycles::" msgstr "" "En segundo lugar, debemos proporcionar un método para borrar cualquier " "subobjeto que pueda participar en los ciclos::" #: ../Doc/extending/newtypes_tutorial.rst:733 msgid "" "static int\n" "Custom_clear(CustomObject *self)\n" "{\n" " Py_CLEAR(self->first);\n" " Py_CLEAR(self->last);\n" " return 0;\n" "}" msgstr "" #: ../Doc/extending/newtypes_tutorial.rst:741 msgid "" "Notice the use of the :c:func:`Py_CLEAR` macro. It is the recommended and " "safe way to clear data attributes of arbitrary types while decrementing " "their reference counts. If you were to call :c:func:`Py_XDECREF` instead on " "the attribute before setting it to ``NULL``, there is a possibility that the " "attribute's destructor would call back into code that reads the attribute " "again (*especially* if there is a reference cycle)." msgstr "" "Observe el uso de la macro :c:func:`Py_CLEAR`. Es la forma recomendada y " "segura de borrar los atributos de datos de tipos arbitrarios al tiempo que " "disminuye sus recuentos de referencia. Si tuviera que llamar a :c:func:" "`Py_XDECREF` en lugar del atributo antes de establecerlo en ``NULL``, existe " "la posibilidad de que el destructor del atributo vuelva a llamar al código " "que lee el atributo nuevamente (*especialmente* si hay un ciclo de " "referencia)." #: ../Doc/extending/newtypes_tutorial.rst:749 msgid "You could emulate :c:func:`Py_CLEAR` by writing::" msgstr "Puede emular :c:func:`Py_CLEAR` escribiendo::" #: ../Doc/extending/newtypes_tutorial.rst:751 msgid "" "PyObject *tmp;\n" "tmp = self->first;\n" "self->first = NULL;\n" "Py_XDECREF(tmp);" msgstr "" #: ../Doc/extending/newtypes_tutorial.rst:756 msgid "" "Nevertheless, it is much easier and less error-prone to always use :c:func:" "`Py_CLEAR` when deleting an attribute. Don't try to micro-optimize at the " "expense of robustness!" msgstr "" "Sin embargo, es mucho más fácil y menos propenso a errores usar siempre :c:" "func:`Py_CLEAR` al eliminar un atributo. ¡No intentes micro-optimizar a " "expensas de la robustez!" #: ../Doc/extending/newtypes_tutorial.rst:760 msgid "" "The deallocator ``Custom_dealloc`` may call arbitrary code when clearing " "attributes. It means the circular GC can be triggered inside the function. " "Since the GC assumes reference count is not zero, we need to untrack the " "object from the GC by calling :c:func:`PyObject_GC_UnTrack` before clearing " "members. Here is our reimplemented deallocator using :c:func:" "`PyObject_GC_UnTrack` and ``Custom_clear``::" msgstr "" "El desasignador ``Custom_dealloc`` puede llamar a un código arbitrario al " "borrar los atributos. Significa que el GC circular se puede activar dentro " "de la función. Dado que el GC asume que el recuento de referencias no es " "cero, debemos destrabar el objeto del GC llamando a :c:func:" "`PyObject_GC_UnTrack` antes de borrar los miembros. Aquí está nuestro " "reubicador reimplementado usando :c:func:`PyObject_GC_UnTrack` y " "``Custom_clear``::" #: ../Doc/extending/newtypes_tutorial.rst:767 msgid "" "static void\n" "Custom_dealloc(CustomObject *self)\n" "{\n" " PyObject_GC_UnTrack(self);\n" " Custom_clear(self);\n" " Py_TYPE(self)->tp_free((PyObject *) self);\n" "}" msgstr "" #: ../Doc/extending/newtypes_tutorial.rst:775 #, fuzzy msgid "" "Finally, we add the :c:macro:`Py_TPFLAGS_HAVE_GC` flag to the class flags::" msgstr "" "Finalmente, agregamos el indicador :const:`Py_TPFLAGS_HAVE_GC` a los " "indicadores de clase::" #: ../Doc/extending/newtypes_tutorial.rst:777 msgid "" ".tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC," msgstr "" #: ../Doc/extending/newtypes_tutorial.rst:779 msgid "" "That's pretty much it. If we had written custom :c:member:`~PyTypeObject." "tp_alloc` or :c:member:`~PyTypeObject.tp_free` handlers, we'd need to modify " "them for cyclic garbage collection. Most extensions will use the versions " "automatically provided." msgstr "" "Eso es prácticamente todo. Si hubiéramos escrito controladores " "personalizados :c:member:`~PyTypeObject.tp_alloc` o :c:member:`~PyTypeObject." "tp_free`, tendríamos que modificarlos para la recolección de basura cíclica. " "La mayoría de las extensiones usarán las versiones proporcionadas " "automáticamente." #: ../Doc/extending/newtypes_tutorial.rst:785 msgid "Subclassing other types" msgstr "Subclases de otros tipos" #: ../Doc/extending/newtypes_tutorial.rst:787 msgid "" "It is possible to create new extension types that are derived from existing " "types. It is easiest to inherit from the built in types, since an extension " "can easily use the :c:type:`PyTypeObject` it needs. It can be difficult to " "share these :c:type:`PyTypeObject` structures between extension modules." msgstr "" "Es posible crear nuevos tipos de extensión que se derivan de los tipos " "existentes. Es más fácil heredar de los tipos incorporados, ya que una " "extensión puede usar fácilmente :c:type:`PyTypeObject` que necesita. Puede " "ser difícil compartir estas estructuras :c:type:`PyTypeObject` entre módulos " "de extensión." #: ../Doc/extending/newtypes_tutorial.rst:792 #, fuzzy msgid "" "In this example we will create a :class:`!SubList` type that inherits from " "the built-in :class:`list` type. The new type will be completely compatible " "with regular lists, but will have an additional :meth:`!increment` method " "that increases an internal counter:" msgstr "" "En este ejemplo crearemos un tipo :class:`SubList` que hereda del tipo " "incorporado :class:`list`. El nuevo tipo será completamente compatible con " "las listas regulares, pero tendrá un método adicional :meth:`increment` que " "aumenta un contador interno:" #: ../Doc/extending/newtypes_tutorial.rst:797 msgid "" ">>> import sublist\n" ">>> s = sublist.SubList(range(3))\n" ">>> s.extend(s)\n" ">>> print(len(s))\n" "6\n" ">>> print(s.increment())\n" "1\n" ">>> print(s.increment())\n" "2" msgstr "" #: ../Doc/extending/newtypes_tutorial.rst:809 msgid "" "#define PY_SSIZE_T_CLEAN\n" "#include \n" "\n" "typedef struct {\n" " PyListObject list;\n" " int state;\n" "} SubListObject;\n" "\n" "static PyObject *\n" "SubList_increment(SubListObject *self, PyObject *unused)\n" "{\n" " self->state++;\n" " return PyLong_FromLong(self->state);\n" "}\n" "\n" "static PyMethodDef SubList_methods[] = {\n" " {\"increment\", (PyCFunction) SubList_increment, METH_NOARGS,\n" " PyDoc_STR(\"increment state counter\")},\n" " {NULL},\n" "};\n" "\n" "static int\n" "SubList_init(SubListObject *self, PyObject *args, PyObject *kwds)\n" "{\n" " if (PyList_Type.tp_init((PyObject *) self, args, kwds) < 0)\n" " return -1;\n" " self->state = 0;\n" " return 0;\n" "}\n" "\n" "static PyTypeObject SubListType = {\n" " PyVarObject_HEAD_INIT(NULL, 0)\n" " .tp_name = \"sublist.SubList\",\n" " .tp_doc = PyDoc_STR(\"SubList objects\"),\n" " .tp_basicsize = sizeof(SubListObject),\n" " .tp_itemsize = 0,\n" " .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,\n" " .tp_init = (initproc) SubList_init,\n" " .tp_methods = SubList_methods,\n" "};\n" "\n" "static PyModuleDef sublistmodule = {\n" " PyModuleDef_HEAD_INIT,\n" " .m_name = \"sublist\",\n" " .m_doc = \"Example module that creates an extension type.\",\n" " .m_size = -1,\n" "};\n" "\n" "PyMODINIT_FUNC\n" "PyInit_sublist(void)\n" "{\n" " PyObject *m;\n" " SubListType.tp_base = &PyList_Type;\n" " if (PyType_Ready(&SubListType) < 0)\n" " return NULL;\n" "\n" " m = PyModule_Create(&sublistmodule);\n" " if (m == NULL)\n" " return NULL;\n" "\n" " if (PyModule_AddObjectRef(m, \"SubList\", (PyObject *) &SubListType) < " "0) {\n" " Py_DECREF(m);\n" " return NULL;\n" " }\n" "\n" " return m;\n" "}\n" msgstr "" #: ../Doc/extending/newtypes_tutorial.rst:812 #, fuzzy msgid "" "As you can see, the source code closely resembles the :class:`!Custom` " "examples in previous sections. We will break down the main differences " "between them. ::" msgstr "" "Como puede ver, el código fuente se parece mucho a los ejemplos :class:" "`Custom` en secciones anteriores. Desglosaremos las principales diferencias " "entre ellos. ::" #: ../Doc/extending/newtypes_tutorial.rst:815 msgid "" "typedef struct {\n" " PyListObject list;\n" " int state;\n" "} SubListObject;" msgstr "" #: ../Doc/extending/newtypes_tutorial.rst:820 msgid "" "The primary difference for derived type objects is that the base type's " "object structure must be the first value. The base type will already " "include the :c:func:`PyObject_HEAD` at the beginning of its structure." msgstr "" "La diferencia principal para los objetos de tipo derivado es que la " "estructura de objeto del tipo base debe ser el primer valor. El tipo base ya " "incluirá :c:func:`PyObject_HEAD` al comienzo de su estructura." #: ../Doc/extending/newtypes_tutorial.rst:824 #, fuzzy msgid "" "When a Python object is a :class:`!SubList` instance, its ``PyObject *`` " "pointer can be safely cast to both ``PyListObject *`` and ``SubListObject " "*``::" msgstr "" "Cuando un objeto Python es una instancia de :class:`SubList`, su puntero " "``PyObject *`` se puede convertir de forma segura tanto en ``PyListObject " "*`` como en ``SubListObject *``::" #: ../Doc/extending/newtypes_tutorial.rst:827 msgid "" "static int\n" "SubList_init(SubListObject *self, PyObject *args, PyObject *kwds)\n" "{\n" " if (PyList_Type.tp_init((PyObject *) self, args, kwds) < 0)\n" " return -1;\n" " self->state = 0;\n" " return 0;\n" "}" msgstr "" #: ../Doc/extending/newtypes_tutorial.rst:836 #, fuzzy msgid "" "We see above how to call through to the :meth:`~object.__init__` method of " "the base type." msgstr "Vemos arriba cómo llamar al método :attr:`__init__` del tipo base." #: ../Doc/extending/newtypes_tutorial.rst:839 msgid "" "This pattern is important when writing a type with custom :c:member:" "`~PyTypeObject.tp_new` and :c:member:`~PyTypeObject.tp_dealloc` members. " "The :c:member:`~PyTypeObject.tp_new` handler should not actually create the " "memory for the object with its :c:member:`~PyTypeObject.tp_alloc`, but let " "the base class handle it by calling its own :c:member:`~PyTypeObject.tp_new`." msgstr "" "Este patrón es importante cuando se escribe un tipo con miembros " "personalizados :c:member:`~PyTypeObject.tp_new` y :c:member:`~PyTypeObject." "tp_dealloc`. El manejador :c:member:`~PyTypeObject.tp_new` no debería crear " "realmente la memoria para el objeto con su :c:member:`~PyTypeObject." "tp_alloc`, pero deja que la clase base lo maneje llamando a su propio :c:" "member:`~PyTypeObject.tp_new`." #: ../Doc/extending/newtypes_tutorial.rst:845 msgid "" "The :c:type:`PyTypeObject` struct supports a :c:member:`~PyTypeObject." "tp_base` specifying the type's concrete base class. Due to cross-platform " "compiler issues, you can't fill that field directly with a reference to :c:" "type:`PyList_Type`; it should be done later in the module initialization " "function::" msgstr "" "La estructura :c:type:`PyTypeObject` admite a :c:member:`~PyTypeObject." "tp_base` especificando la clase base concreta del tipo. Debido a problemas " "de compilación multiplataforma, no puede llenar ese campo directamente con " "una referencia a :c:type:`PyList_Type`; debe hacerse más tarde en la función " "de inicialización del módulo::" #: ../Doc/extending/newtypes_tutorial.rst:851 msgid "" "PyMODINIT_FUNC\n" "PyInit_sublist(void)\n" "{\n" " PyObject* m;\n" " SubListType.tp_base = &PyList_Type;\n" " if (PyType_Ready(&SubListType) < 0)\n" " return NULL;\n" "\n" " m = PyModule_Create(&sublistmodule);\n" " if (m == NULL)\n" " return NULL;\n" "\n" " if (PyModule_AddObjectRef(m, \"SubList\", (PyObject *) &SubListType) < " "0) {\n" " Py_DECREF(m);\n" " return NULL;\n" " }\n" "\n" " return m;\n" "}" msgstr "" #: ../Doc/extending/newtypes_tutorial.rst:871 msgid "" "Before calling :c:func:`PyType_Ready`, the type structure must have the :c:" "member:`~PyTypeObject.tp_base` slot filled in. When we are deriving an " "existing type, it is not necessary to fill out the :c:member:`~PyTypeObject." "tp_alloc` slot with :c:func:`PyType_GenericNew` -- the allocation function " "from the base type will be inherited." msgstr "" "Antes de llamar a :c:func:`PyType_Ready`, la estructura de tipo debe tener " "el espacio :c:member:`~PyTypeObject.tp_base` rellenado. Cuando derivamos un " "tipo existente, no es necesario completar el :c:member:`~PyTypeObject." "tp_alloc` ranura con :c:func:`PyType_GenericNew` -- la función de asignación " "del tipo base será heredada." #: ../Doc/extending/newtypes_tutorial.rst:877 #, fuzzy msgid "" "After that, calling :c:func:`PyType_Ready` and adding the type object to the " "module is the same as with the basic :class:`!Custom` examples." msgstr "" "Después de eso, llamar a :c:func:`PyType_Ready` y agregar el objeto tipo al " "módulo es lo mismo que con los ejemplos básicos :class:`Custom`." #: ../Doc/extending/newtypes_tutorial.rst:882 msgid "Footnotes" msgstr "Notas al pie" #: ../Doc/extending/newtypes_tutorial.rst:883 msgid "" "This is true when we know that the object is a basic type, like a string or " "a float." msgstr "" "Esto es cierto cuando sabemos que el objeto es un tipo básico, como una " "cadena o un flotador." #: ../Doc/extending/newtypes_tutorial.rst:886 msgid "" "We relied on this in the :c:member:`~PyTypeObject.tp_dealloc` handler in " "this example, because our type doesn't support garbage collection." msgstr "" "Nos basamos en esto en el manejador :c:member:`~PyTypeObject.tp_dealloc` en " "este ejemplo, porque nuestro tipo no admite la recolección de basura." #: ../Doc/extending/newtypes_tutorial.rst:889 msgid "" "We now know that the first and last members are strings, so perhaps we could " "be less careful about decrementing their reference counts, however, we " "accept instances of string subclasses. Even though deallocating normal " "strings won't call back into our objects, we can't guarantee that " "deallocating an instance of a string subclass won't call back into our " "objects." msgstr "" "Ahora sabemos que el primer y el último miembro son cadenas de caracteres, " "por lo que quizás podríamos ser menos cuidadosos al disminuir sus recuentos " "de referencia, sin embargo, aceptamos instancias de subclases de cadenas. A " "pesar de que la desasignación de cadenas normales no volverá a llamar a " "nuestros objetos, no podemos garantizar que la desasignación de una " "instancia de una subclase de cadena de caracteres no vuelva a llamar a " "nuestros objetos." #: ../Doc/extending/newtypes_tutorial.rst:895 msgid "" "Also, even with our attributes restricted to strings instances, the user " "could pass arbitrary :class:`str` subclasses and therefore still create " "reference cycles." msgstr "" "Además, incluso con nuestros atributos restringidos a instancias de cadenas, " "el usuario podría pasar subclases arbitrarias :class:`str` y, por lo tanto, " "seguir creando ciclos de referencia."