# SOME DESCRIPTIVE TITLE. # Copyright (C) 2001-2025, Python Software Foundation # This file is distributed under the same license as the Python package. # FIRST AUTHOR , YEAR. # # Translators: # python-doc bot, 2025 # #, fuzzy msgid "" msgstr "" "Project-Id-Version: Python 3.9\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2025-01-03 16:35+0000\n" "PO-Revision-Date: 2025-09-22 17:54+0000\n" "Last-Translator: python-doc bot, 2025\n" "Language-Team: Chinese (China) (https://app.transifex.com/python-doc/teams/5390/zh_CN/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: zh_CN\n" "Plural-Forms: nplurals=1; plural=0;\n" #: ../../extending/newtypes_tutorial.rst:7 msgid "Defining Extension Types: Tutorial" msgstr "自定义扩展类型:教程" #: ../../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 允许编写 C 扩展模块定义可以从 Python 代码中操纵的新类型,这很像内置的 :class:`str` 和 :class:`list`" " 类型。所有扩展类型的代码都遵循一个模式,但是在您开始之前,您需要了解一些细节。这份文件是对这个主题介绍。" #: ../../extending/newtypes_tutorial.rst:24 msgid "The Basics" msgstr "基础" #: ../../extending/newtypes_tutorial.rst:26 msgid "" "The :term:`CPython` runtime sees all Python objects as variables of type " ":c:type:`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 "" ":term:`CPython` 运行时将所有 Python 对象都视为类型 :c:type:`PyObject\\*` 的变量,即所有 Python " "对象的\"基础类型\"。 :c:type:`PyObject` 结构体本身包含了对象的 :term:`reference count` " "和对象的\"类型对象\"。 类型对象确定解释器需要调用哪些 (C) 函数,例如一个属性查询一个对象,一个方法调用,或者与另一个对象相乘。 这些 C " "函数被称为“类型方法”。" #: ../../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 "所以,如果你想要定义新的扩展类型,需要创建新的类型对象。" #: ../../extending/newtypes_tutorial.rst:38 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 "" "这类事情只能用例子解释,这里用一个最小化但完整的的模块,定义了新的类型叫做 :class:`Custom` 在C扩展模块 :mod:`custom` " "里。" #: ../../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 "" "这里展示的方法是定义 *static* 扩展类型的传统方法。可以适合大部分用途。C API也可以定义在堆上分配的扩展类型,使用 " ":c:func:`PyType_FromSpec` 函数,但不在本入门里讨论。" #: ../../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 "这部分很容易理解,这是为了跟上一章能对接上。这个文件定义了三件事:" #: ../../extending/newtypes_tutorial.rst:53 msgid "" "What a :class:`Custom` **object** contains: this is the ``CustomObject`` " "struct, which is allocated once for each :class:`Custom` instance." msgstr "" ":class:`Custom` 类的对象 **object** 包含了: ``CustomObject`` 结构,这会为每个 " ":class:`Custom` 实例分配一次。" #: ../../extending/newtypes_tutorial.rst:55 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 "" ":class:`Custom` **type** 的行为:这是 ``CustomType`` " "结构体,其定义了一堆标识和函数指针,会指向解释器里请求的操作。" #: ../../extending/newtypes_tutorial.rst:58 msgid "" "How to initialize the :mod:`custom` module: this is the ``PyInit_custom`` " "function and the associated ``custommodule`` struct." msgstr "初始化 :mod:`custom` 模块: ``PyInit_custom`` 函数和对应的 ``custommodule`` 结构体。" #: ../../extending/newtypes_tutorial.rst:61 msgid "The first bit is::" msgstr "结构的第一块是 ::" #: ../../extending/newtypes_tutorial.rst:67 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 debug builds." msgstr "" #: ../../extending/newtypes_tutorial.rst:75 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 "注意在宏 :c:macro:`PyObject_HEAD` 后没有分号。意外添加分号会导致编译器提示出错。" #: ../../extending/newtypes_tutorial.rst:78 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 "当然,对象除了在 ``PyObject_HEAD`` 存储数据外,还有额外数据;例如,如下定义了标准的Python浮点数::" #: ../../extending/newtypes_tutorial.rst:87 msgid "The second bit is the definition of the type object. ::" msgstr "第二个位是类型对象的定义::" #: ../../extending/newtypes_tutorial.rst:100 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 "" "推荐使用如上C99风格的初始化,以避免列出所有的 :c:type:`PyTypeObject` " "字段,其中很多是你不需要关心的,这样也可以避免关注字段的定义顺序。" #: ../../extending/newtypes_tutorial.rst:104 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 "" "在 :file:`object.h` 中实际定义的 :c:type:`PyTypeObject` 具有比如上定义更多的 :ref:`字段 `。 剩余的字段会由 C 编译器用零来填充,通常的做法是不显式地指定它们,除非你确实需要它们。" #: ../../extending/newtypes_tutorial.rst:109 msgid "We're going to pick it apart, one field at a time::" msgstr "我们先挑选一部分,每次一个字段::" #: ../../extending/newtypes_tutorial.rst:113 msgid "" "This line is mandatory boilerplate to initialize the ``ob_base`` field " "mentioned above. ::" msgstr "这一行是强制的样板,用以初始化如上提到的 ``ob_base`` 字段::" #: ../../extending/newtypes_tutorial.rst:118 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 "我们的类型的名称。 这将出现在我们的对象的默认文本表示形式和某些错误消息中,例如:" #: ../../extending/newtypes_tutorial.rst:128 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 "" "注意,名字是一个带点的名字,包括模块名称和模块中的类型名称。本例中的模块是 :mod:`custom`,类型是 " ":class:`Custom`,所以我们将类型名设为 :class:`custom.Custom`。使用真正的点状导入路径很重要,可以使你的类型与 " ":mod:`pydoc` 和 :mod:`pickle` 模块兼容。" #: ../../extending/newtypes_tutorial.rst:137 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 "" "这样能让 Python 知道当创建新的 :class:`Custom` 实例时需要分配多少内存。 " ":c:member:`~PyTypeObject.tp_itemsize` 仅用于可变大小的对象而在其他情况下都应为零。" #: ../../extending/newtypes_tutorial.rst:143 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:`~class.__bases__`, or else it " "will not be able to call your type's :meth:`__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 "" "如果你希望你的类型可在 Python 中被子类化,并且你的类型具有与其基础类型相同的 " ":c:member:`~PyTypeObject.tp_basicsize`,那么你可能会遇到多重继承问题。 你的类型在 Python " "中的子类将必须在其 :attr:`~class.__bases__` 中将你的类型列在最前面,否则它在调用你的类型的 :meth:`__new__` " "方法时就会遇到错误。 你可以通过确保你的类型具有比其基础类型更大的 :c:member:`~PyTypeObject.tp_basicsize` " "值来避免此问题。 在大多数时候,这都是可以的,因为或者你的基础类型为 " ":class:`object`,或者你会向你的基础类型增加数据成员,并因而增加其大小。" #: ../../extending/newtypes_tutorial.rst:153 msgid "We set the class flags to :const:`Py_TPFLAGS_DEFAULT`. ::" msgstr "我们将类旗标设为 :const:`Py_TPFLAGS_DEFAULT`。 ::" #: ../../extending/newtypes_tutorial.rst:157 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 "" "所有类型都应当在它们的旗标中包括此常量。 该常量将启用至少在 Python 3.3 之前定义的全部成员。 如果你需要更多的成员,你将需要对相应的旗标进行" " OR 运算。" #: ../../extending/newtypes_tutorial.rst:161 msgid "" "We provide a doc string for the type in :c:member:`~PyTypeObject.tp_doc`. ::" msgstr "我们为 :c:member:`~PyTypeObject.tp_doc` 类型提供一个文档字符串. ::" #: ../../extending/newtypes_tutorial.rst:165 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:`__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 "" "要启用对象创建,我们需要提供一个 :c:member:`~PyTypeObject.tp_new` 处理器。 这等价于 Python 方法 " ":meth:`__new__`,但是必须显式地指定。 在这个场景中,我们可以直接使用 API 函数 " ":c:func:`PyType_GenericNew` 所提供的默认实现。 ::" #: ../../extending/newtypes_tutorial.rst:172 msgid "" "Everything else in the file should be familiar, except for some code in " ":c:func:`PyInit_custom`::" msgstr "该文件的其他部分应该都很容易理解,除了 :c:func:`PyInit_custom` 中的某些代码::" #: ../../extending/newtypes_tutorial.rst:178 msgid "" "This initializes the :class:`Custom` type, filling in a number of members to" " the appropriate default values, including :attr:`ob_type` that we initially" " set to ``NULL``. ::" msgstr "" "这将初始化 :class:`Custom` 类型,为一部分成员填充适当的默认值,包括我们在初始时设为 ``NULL`` 的 " ":attr:`ob_type`。 ::" #: ../../extending/newtypes_tutorial.rst:189 msgid "" "This adds the type to the module dictionary. This allows us to create " ":class:`Custom` instances by calling the :class:`Custom` class:" msgstr "这将把类型添加到模块字典。 这使我们能通过调用 :class:`Custom` 类来创建 :class:`Custom` 实例:" #: ../../extending/newtypes_tutorial.rst:197 msgid "" "That's it! All that remains is to build it; put the above code in a file " "called :file:`custom.c` and:" msgstr "好了! 接下来要做的就是编译它;将上述代码放到名为 :file:`custom.c` 的文件中然后:" #: ../../extending/newtypes_tutorial.rst:206 msgid "in a file called :file:`setup.py`; then typing" msgstr "在名为 :file:`setup.py` 的文件中;然后输入" #: ../../extending/newtypes_tutorial.rst:212 msgid "" "at a shell should produce a file :file:`custom.so` in a subdirectory; move " "to that directory and fire up Python --- you should be able to ``import " "custom`` and play around with Custom objects." msgstr "" "到 shell 中应当会在一个子目录中产生文件 :file:`custom.so`;进入该目录并运行 Python --- 你应当能够执行 " "``import custom`` 并尝试使用 Custom 对象。" #: ../../extending/newtypes_tutorial.rst:216 msgid "That wasn't so hard, was it?" msgstr "这并不难,对吗?" #: ../../extending/newtypes_tutorial.rst:218 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 "当然,当前的自定义类型非常无趣。它没有数据,也不做任何事情。它甚至不能被子类化。" #: ../../extending/newtypes_tutorial.rst:222 msgid "" "While this documentation showcases the standard :mod:`distutils` module for " "building C extensions, it is recommended in real-world use cases to use the " "newer and better-maintained ``setuptools`` library. Documentation on how to" " do this is out of scope for this document and can be found in the `Python " "Packaging User's Guide `_." msgstr "" "虽然本文档演示了用于构建 C 扩展的标准 :mod:`distutils` 模块,但在真实场景中还是推荐使用更新且维护得更好的 " "``setuptools`` 库。 有关其用法的文档超出了本文档的范围,可以访问 `Python 打包用户指南 " "`_ 来获取。" #: ../../extending/newtypes_tutorial.rst:230 msgid "Adding data and methods to the Basic example" msgstr "向基本示例添加数据和方法" #: ../../extending/newtypes_tutorial.rst:232 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 "" "让我们通过添加一些数据和方法来扩展这个基本示例。 让我们再使原类型可以作为基类使用。 我们将创建一个新模块 :mod:`custom2` " "来添加这些功能:" #: ../../extending/newtypes_tutorial.rst:239 msgid "This version of the module has a number of changes." msgstr "该模块的新版本包含多处修改。" #: ../../extending/newtypes_tutorial.rst:241 msgid "We've added an extra include::" msgstr "我们已经添加呢一个外部导入::" #: ../../extending/newtypes_tutorial.rst:245 msgid "" "This include provides declarations that we use to handle attributes, as " "described a bit later." msgstr "这包括提供被我们用来处理属性的声明,正如我们稍后所描述的。" #: ../../extending/newtypes_tutorial.rst:248 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 "" "现在 :class:`Custom` 类型的 C 结构体中有三个数据属性,*first*, *last* 和 *number*。 其中 *first* " "和 *last* 变量是包含头一个和末一个名称的 Python 字符串。 *number* 属性是一个 C 整数。" #: ../../extending/newtypes_tutorial.rst:252 msgid "The object structure is updated accordingly::" msgstr "对象的结构将被相应地更新::" #: ../../extending/newtypes_tutorial.rst:261 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 "因为现在我们有数据需要管理,我们必须更加小心地处理对象的分配和释放。 至少,我们需要有一个释放方法::" #: ../../extending/newtypes_tutorial.rst:272 msgid "which is assigned to the :c:member:`~PyTypeObject.tp_dealloc` member::" msgstr "它会被赋值给 :c:member:`~PyTypeObject.tp_dealloc` 成员::" #: ../../extending/newtypes_tutorial.rst:276 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 "" "此方法会先清空两个 Python 属性的引用计数。 :c:func:`Py_XDECREF` 可正确地处理其参数为 ``NULL`` 的情况(这可能在 " "``tp_new`` 中途失败时发生)。 随后它将调用对象类型的 :c:member:`~PyTypeObject.tp_free` 成员(通过 " "``Py_TYPE(self)`` 获取对象类型)来释放对象的内存。 请注意对象类型可以不是 " ":class:`CustomType`,因为对象可能是一个子类的实例。" #: ../../extending/newtypes_tutorial.rst:285 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 "" "上面需要强制转换 ``destructor`` 是因为我们定义了 ``Custom_dealloc`` 接受一个 ``CustomObject *`` " "参数,但 ``tp_dealloc`` 函数指针预期接受一个 ``PyObject *`` 参数。 如果不这样做,编译器将发出警告。 这是 C " "语言中面向对象的多态性!" #: ../../extending/newtypes_tutorial.rst:291 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 "我们希望确保头一个和末一个名称被初始化为空字符串,因此我们提供了一个 ``tp_new`` 实现::" #: ../../extending/newtypes_tutorial.rst:315 msgid "and install it in the :c:member:`~PyTypeObject.tp_new` member::" msgstr "并在 :c:member:`~PyTypeObject.tp_new` 成员中安装它::" #: ../../extending/newtypes_tutorial.rst:319 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:`__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 ``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 "" "``tp_new`` 处理器负责创建(而不是初始化)该类型的对象。 它在 Python 中被暴露为 :meth:`__new__` 方法。 它不需要定义" " ``tp_new`` 成员,实际上许多扩展类型会简单地重用 :c:func:`PyType_GenericNew`,就像上面第一版 " "``Custom`` 类型所作的那样。 在此情况下,我们使用 ``tp_new`` 处理器来将 ``first`` 和 ``last`` 属性初始化为非" " ``NULL`` 的默认值。" #: ../../extending/newtypes_tutorial.rst:327 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`` 将接受被实例化的类型(不要求为 " "``CustomType``,如果被实例化的是一个子类)以及在该类型被调用时传入的任何参数,并预期返回所创建的实例。 ``tp_new`` " "处理器总是接受位置和关键字参数,但它们总是会忽略这些参数,而将参数处理留给初始化(即 C 中的 ``tp_init`` 或 Python 中的 " "``__init__`` 函数)方法来执行。" #: ../../extending/newtypes_tutorial.rst:335 msgid "" "``tp_new`` shouldn't call ``tp_init`` explicitly, as the interpreter will do" " it itself." msgstr "``tp_new`` 不应显式地调用 ``tp_init``,因为解释器会自行调用它。" #: ../../extending/newtypes_tutorial.rst:338 msgid "" "The ``tp_new`` implementation calls the :c:member:`~PyTypeObject.tp_alloc` " "slot to allocate memory::" msgstr "``tp_new`` 实现会调用 :c:member:`~PyTypeObject.tp_alloc` 槽位来分配内存::" #: ../../extending/newtypes_tutorial.rst:343 msgid "" "Since memory allocation may fail, we must check the " ":c:member:`~PyTypeObject.tp_alloc` result against ``NULL`` before " "proceeding." msgstr "" "由于内存分配可能会失败,我们必须在继续执行之前检查 :c:member:`~PyTypeObject.tp_alloc` 结果确认其不为 " "``NULL``。" #: ../../extending/newtypes_tutorial.rst:347 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 "" "我们没有自行填充 :c:member:`~PyTypeObject.tp_alloc` 槽位。 而是由 :c:func:`PyType_Ready` " "通过从我们的基类继承来替我们填充它,其中默认为 :class:`object`。 大部分类型都是使用默认的分配策略。" #: ../../extending/newtypes_tutorial.rst:353 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:`__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 "" "如果你要创建一个协作 :c:member:`~PyTypeObject.tp_new` (它会调用基类型的 " ":c:member:`~PyTypeObject.tp_new` 或 :meth:`__new__`),那么你 *不能* " "在运行时尝试使用方法解析顺序来确定要调用的方法。 必须总是静态地确定你要调用的类型,并直接调用它的 " ":c:member:`~PyTypeObject.tp_new`,或是通过 ``type->tp_base->tp_new``。 " "如果你不这样做,你的类型的同样从其他 Python 定义的类继承的 Python 子类可能无法正确工作。 " "(特别地,你可能无法创建这样的子类的实例而是会引发 :exc:`TypeError`。)" #: ../../extending/newtypes_tutorial.rst:363 msgid "" "We also define an initialization function which accepts arguments to provide" " initial values for our instance::" msgstr "我们还定义了一个接受参数来为我们的实例提供初始值的初始化函数::" #: ../../extending/newtypes_tutorial.rst:392 msgid "by filling the :c:member:`~PyTypeObject.tp_init` slot. ::" msgstr "通过填充 :c:member:`~PyTypeObject.tp_init` 槽位。 ::" #: ../../extending/newtypes_tutorial.rst:396 msgid "" "The :c:member:`~PyTypeObject.tp_init` slot is exposed in Python as the " ":meth:`__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 "" ":c:member:`~PyTypeObject.tp_init` 槽位在 Python 中暴露为 :meth:`__init__` 方法。 " "它被用来在对象被创建后初始化它。 初始化器总是接受位置和关键字参数,它们应当在成功时返回 ``0`` 而在出错时返回 ``-1``。" #: ../../extending/newtypes_tutorial.rst:401 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:`__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 "" "不同于 ``tp_new`` 处理器,``tp_init`` 不保证一定会被调用 (例如,在默认情况下 :mod:`pickle` " "模块不会在被解封的实例上调用 :meth:`__init__`)。 它还可能被多次调用。 任何人都可以在我们的对象上调用 " ":meth:`__init__` 方法。 由于这个原因,我们在为属性赋新值时必须非常小心。 我们可能会被误导,例如像这样给 ``first`` " "成员赋值::" #: ../../extending/newtypes_tutorial.rst:415 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 "" "但是这可能会有危险。 我们的类型没有限制 ``first`` 成员的类型,因此它可以是任何种类的对象。 它可以带有一个会执行尝试访问 ``first``" " 成员的代码的析构器;或者该析构器可能会释放 :term:`全局解释器锁 ` 并让任意代码在其他线程中运行来访问和修改我们的对象。" #: ../../extending/newtypes_tutorial.rst:422 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 "为了保持谨慎并使我们避免这种可能性,我们几乎总是要在减少成员的引用计数之前给它们重新赋值。 什么时候我们可以不必再这样做?" #: ../../extending/newtypes_tutorial.rst:426 msgid "when we absolutely know that the reference count is greater than 1;" msgstr "当我们明确知道引用计数大于 1 的时候;" #: ../../extending/newtypes_tutorial.rst:428 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 "当我们知道对象的释放 [#]_ 既不会释放 :term:`GIL` 也不会导致任何对我们的类型的代码的回调的时候;" #: ../../extending/newtypes_tutorial.rst:431 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 "" "当减少一个 :c:member:`~PyTypeObject.tp_dealloc` 处理器内不支持循环垃圾回收的类型的引用计数的时候 [#]_." #: ../../extending/newtypes_tutorial.rst:434 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 "我们可能会想将我们的实例变量暴露为属性。 有几种方式可以做到这一点。 最简单的方式是定义成员的定义::" #: ../../extending/newtypes_tutorial.rst:447 msgid "" "and put the definitions in the :c:member:`~PyTypeObject.tp_members` slot::" msgstr "并将定义放置到 :c:member:`~PyTypeObject.tp_members` 槽位中::" #: ../../extending/newtypes_tutorial.rst:451 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 "" "每个成员的定义都有成员名称、类型、偏移量、访问旗标和文档字符串。 请参阅下面的 :ref:`Generic-Attribute-Management` " "小节来了解详情。section below for details." #: ../../extending/newtypes_tutorial.rst:455 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 "" "此方式的缺点之一是它没有提供限制可被赋值给 Python 属性的对象类型的办法。 我们预期 first 和 last " "的名称为字符串,但它们可以被赋值为任意 Python 对象。 此外,这些属性还可以被删除,并将 C 指针设为 ``NULL``。 " "即使我们可以保证这些成员被初始化为非 ``NULL`` 值,如果这些属性被删除这些成员仍可被设为 ``NULL``。" #: ../../extending/newtypes_tutorial.rst:462 msgid "" "We define a single method, :meth:`Custom.name()`, that outputs the objects " "name as the concatenation of the first and last names. ::" msgstr "我们定义了一个单独的方法,:meth:`Custom.name()`,它将对象名称输出为 first 和 last 名称的拼接。 ::" #: ../../extending/newtypes_tutorial.rst:479 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 "" "该方法的实现形式是一个接受 :class:`Custom` (或 :class:`Custom` 的子类) 实例作为第一个参数的 C 函数。 " "方法总是接受一个实例作为第一个参数。 方法也总是接受位置和关键字参数,但在本例中我们未接受任何参数也不需要接受位置参数元组或关键字参数字典。 " "该方法等价于以下 Python 方法:" #: ../../extending/newtypes_tutorial.rst:491 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 "" "请注意我们必须检查我们的 :attr:`first` 和 :attr:`last` 成员是否可能为 ``NULL``。 " "这是因为它们可以被删除,在此情况下它们会被设为 ``NULL``。 更好的做法是防止删除这些属性并将属性的值限制为字符串。 " "我们将在下一节了解如何做到这一点。" #: ../../extending/newtypes_tutorial.rst:497 msgid "" "Now that we've defined the method, we need to create an array of method " "definitions::" msgstr "现在我们已经定义好了方法,我们需要创建一个方法定义数组::" #: ../../extending/newtypes_tutorial.rst:507 msgid "" "(note that we used the :const:`METH_NOARGS` flag to indicate that the method" " is expecting no arguments other than *self*)" msgstr "(请注意我们使用 :const:`METH_NOARGS` 旗标来指明该方法不准备接受 *self* 以外的任何参数)" #: ../../extending/newtypes_tutorial.rst:510 msgid "and assign it to the :c:member:`~PyTypeObject.tp_methods` slot::" msgstr "并将其赋给 :c:member:`~PyTypeObject.tp_methods` 槽位::" #: ../../extending/newtypes_tutorial.rst:514 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 :const:`Py_TPFLAGS_BASETYPE` to our class flag definition::" msgstr "" "最后,我们将使我们的类型可被用作派生子类的基类。 我们精心地编写我们的方法以便它们不会随意假定被创建或使用的对象类型,所以我们需要做的就是将 " ":const:`Py_TPFLAGS_BASETYPE` 添加到我们的类旗标定义中::" #: ../../extending/newtypes_tutorial.rst:521 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 "" "我们将 :c:func:`PyInit_custom` 重命名为 :c:func:`PyInit_custom2`,更新 " ":c:type:`PyModuleDef` 结构体中的模块名,并更新 :c:type:`PyTypeObject` 结构体中的完整类名。" #: ../../extending/newtypes_tutorial.rst:525 msgid "Finally, we update our :file:`setup.py` file to build the new module:" msgstr "最后,我们更新我们的 :file:`setup.py` 文件来生成新的模块。" #: ../../extending/newtypes_tutorial.rst:538 msgid "Providing finer control over data attributes" msgstr "提供对于数据属性的更精细控制" #: ../../extending/newtypes_tutorial.rst:540 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 "" "在本小节中,我们将对 :class:`Custom` 示例中 :attr:`first` 和 :attr:`last` 属性的设置提供更细致的控制。 " "在我们上一版本的模块中,实例变量 :attr:`first` 和 :attr:`last` 可以被设为非字符串值甚至被删除。 " "我们希望这些属性总是包含字符串。" #: ../../extending/newtypes_tutorial.rst:549 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 "" "为了提供对于 :attr:`first` 和 :attr:`last` 属性更强的控制,我们将使用自定义的读取和设置函数。 下面就是用于读取和设置 " ":attr:`first` 属性的函数::" #: ../../extending/newtypes_tutorial.rst:580 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 "" "读取函数接受一个 :class:`Custom` 对象和一个“闭包”,它是一个空指针。 在本例中,该闭包会被忽略。 " "(该闭包支持将定义数据传给读取器和设置器的进阶用法。 例如,这可以被用来允许单组读取和设置函数根据闭包中的数据来决定要读取或设置的属性。)" #: ../../extending/newtypes_tutorial.rst:586 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 "" "设置器函数将接受 :class:`Custom` 对象、新值以及闭包。 新值可以为 ``NULL``,在此情况下属性将被删除。 " "在我们的设置器中,如果属性被删除或者如果它的新值不是字符串则我们将引发一个错误。" #: ../../extending/newtypes_tutorial.rst:591 msgid "We create an array of :c:type:`PyGetSetDef` structures::" msgstr "我们创建一个 :c:type:`PyGetSetDef` 结构体的数组::" #: ../../extending/newtypes_tutorial.rst:601 msgid "and register it in the :c:member:`~PyTypeObject.tp_getset` slot::" msgstr "并在 :c:member:`~PyTypeObject.tp_getset` 槽位中注册它::" #: ../../extending/newtypes_tutorial.rst:605 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 "" "在 :c:type:`PyGetSetDef` 结构体中的最后一项是上面提到的“闭包”。 在本例中,我们没有使用闭包,因此我们只传入 ``NULL``。" #: ../../extending/newtypes_tutorial.rst:608 msgid "We also remove the member definitions for these attributes::" msgstr "我们还移除了这些属性的成员定义::" #: ../../extending/newtypes_tutorial.rst:616 msgid "" "We also need to update the :c:member:`~PyTypeObject.tp_init` handler to only" " allow strings [#]_ to be passed::" msgstr "我们还需要将 :c:member:`~PyTypeObject.tp_init` 处理器更新为只允许传入字符串 [#]_::" #: ../../extending/newtypes_tutorial.rst:645 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 "" "通过这些更改,我们能够确保 ``first`` 和 ``last`` 成员一定不为 ``NULL`` 以便我们能在几乎所有情况下移除 ``NULL`` " "值检查。 这意味着大部分 :c:func:`Py_XDECREF` 调用都可以被转换为 :c:func:`Py_DECREF` 调用。 " "我们不能更改这些调用的唯一场合是在 ``tp_dealloc`` 实现中,那里这些成员的初始化有可能在 ``tp_new`` 中失败。" #: ../../extending/newtypes_tutorial.rst:652 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 "" "我们还重命名了模块初始化函数和初始化函数中的模块名称,就像我们之前所做的一样,我们还向 :file:`setup.py` 文件添加了一个额外的定义。" #: ../../extending/newtypes_tutorial.rst:658 msgid "Supporting cyclic garbage collection" msgstr "支持循环垃圾回收" #: ../../extending/newtypes_tutorial.rst:660 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 具有一个可以标识不再需要的对象的 :term:`循环垃圾回收器 (GC) ` " "即使它们的引用计数并不为零。 这种情况会在对象被循环引用时发生。 例如,设想:" #: ../../extending/newtypes_tutorial.rst:670 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 "" "在这个例子中,我们创建了一个包含其自身的列表。 当我们删除它的时候,它将仍然具有一个来自其本身的引用。 它的引用计数并未降为零。 幸运的是,Python" " 的循环垃圾回收器将最终发现该列表是无用的垃圾并释放它。" #: ../../extending/newtypes_tutorial.rst:675 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 "" "在 :class:`Custom` 示例的第二个版本中,我们允许任意各类的对象存储到 :attr:`first` 或 :attr:`last` 属性中 " "[#]_。 此外,在第二个和第三个版本中,我们还允许子类化 :class:`Custom`,并且子类可以添加任意属性。 " "出于这两个原因中的任何一个,:class:`Custom` 对象都可以加入循环:" #: ../../extending/newtypes_tutorial.rst:689 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 "" "要允许一个参加引用循环的 :class:`Custom` 实例被循环 GC 正确地删除并回收,我们的 :class:`Custom` " "类型需要填充两个额外槽位并增加启用这些槽位的旗标:" #: ../../extending/newtypes_tutorial.rst:696 msgid "" "First, the traversal method lets the cyclic GC know about subobjects that " "could participate in cycles::" msgstr "首先,遍历方法让循环 GC 知道能够参加循环的子对象::" #: ../../extending/newtypes_tutorial.rst:716 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 "" "对于每个能够参加循环的子对象,我们需要调用 :c:func:`visit` 函数,向它传入该遍历方法。 :c:func:`visit` " "函数接受该子对象作为参数并接受传给遍历方法的额外参数 *arg*。 它返回一个必须在非零时返回的整数值。" #: ../../extending/newtypes_tutorial.rst:722 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 提供了一个可自动调用 visit 函数的 :c:func:`Py_VISIT` 宏。 使用 " ":c:func:`Py_VISIT`,我们可以最小化 ``Custom_traverse`` 中的准备工作量::" #: ../../extending/newtypes_tutorial.rst:735 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 "" ":c:member:`~PyTypeObject.tp_traverse` 实现必须将其参数准确命名为 *visit* 和 *arg* 以便使用 " ":c:func:`Py_VISIT`。" #: ../../extending/newtypes_tutorial.rst:738 msgid "" "Second, we need to provide a method for clearing any subobjects that can " "participate in cycles::" msgstr "第二,我们需要提供一个方法用来清除任何可以参加循环的子对象::" #: ../../extending/newtypes_tutorial.rst:749 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 "" "请注意 :c:func:`Py_CLEAR` 宏的使用。 它是清除任意类型的数据属性并减少其引用计数的推荐的且安全的方式。 如果你要选择在将属性设为 " "``NULL`` 之间在属性上调用 :c:func:`Py_XDECREF`,则属性的析构器有可能会回调再次读取该属性的代码 (*特别是* " "如果存在引用循环的话)。" #: ../../extending/newtypes_tutorial.rst:757 msgid "You could emulate :c:func:`Py_CLEAR` by writing::" msgstr "你可以通过以下写法来模拟 :c:func:`Py_CLEAR`::" #: ../../extending/newtypes_tutorial.rst:764 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 "" "无论如何,在删除属性时始终使用Nevertheless, it is much easier and less error-prone to " "always use :c:func:`Py_CLEAR` 都是更简单且更不易出错的。 请不要尝试以健壮性为代价的微小优化!" #: ../../extending/newtypes_tutorial.rst:768 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 "" "释放器 ``Custom_dealloc`` 可能会在清除属性时调用任意代码。 这意味着循环 GC 可以在函数内部被触发。 由于 GC " "预期引用计数不为零,我们需要通过调用 :c:func:`PyObject_GC_UnTrack` 来让 GC 停止追踪相关的对象。 下面是我们使用 " ":c:func:`PyObject_GC_UnTrack` 和 ``Custom_clear`` 重新实现的释放器::" #: ../../extending/newtypes_tutorial.rst:783 msgid "" "Finally, we add the :const:`Py_TPFLAGS_HAVE_GC` flag to the class flags::" msgstr "最后,我们将 :const:`Py_TPFLAGS_HAVE_GC` 旗标添加到类旗标中::" #: ../../extending/newtypes_tutorial.rst:787 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 "" "这样就差不多了。 如果我们编写了自定义的 :c:member:`~PyTypeObject.tp_alloc` 或 " ":c:member:`~PyTypeObject.tp_free` 处理器,则我们需要针对循环垃圾回收来修改它。 大多数扩展都将使用自动提供的版本。" #: ../../extending/newtypes_tutorial.rst:793 msgid "Subclassing other types" msgstr "子类化其他类型" #: ../../extending/newtypes_tutorial.rst:795 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 "" "创建派生自现有类型的新类型是有可能的。 最容易的做法是从内置类型继承,因为扩展可以方便地使用它所需要的 :c:type:`PyTypeObject`。 " "在不同扩展模块之间共享这些 :c:type:`PyTypeObject` 结构体则是困难的。" #: ../../extending/newtypes_tutorial.rst:800 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 "" "在这个例子中我们将创建一个继承自内置 :class:`list` 类型的 :class:`SubList` 类型。 " "这个新类型将完全兼容常规列表,但将拥有一个额外的 :meth:`increment` 来增加内部计数器的值:" #: ../../extending/newtypes_tutorial.rst:820 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 "如你所见,此源代码与之前小节中的 :class:`Custom` 示例非常相似。 我们将逐一讲解它们之间的主要区别。 ::" #: ../../extending/newtypes_tutorial.rst:828 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 "" "派生类型对象的主要差异在于基类型的对象结构体必须是第一个值。 基类型将已经在其结构体的开头包括了 :c:func:`PyObject_HEAD`。" #: ../../extending/newtypes_tutorial.rst:832 msgid "" "When a Python object is a :class:`SubList` instance, its ``PyObject *`` " "pointer can be safely cast to both ``PyListObject *`` and ``SubListObject " "*``::" msgstr "" "当一个 Python 对象是 :class:`SubList` 的实例时,它的 ``PyObject *`` 指针可以被安全地强制转换为 " "``PyListObject *`` 和 ``SubListObject *``::" #: ../../extending/newtypes_tutorial.rst:844 msgid "" "We see above how to call through to the :attr:`__init__` method of the base " "type." msgstr "我们可以在上面看到如何调用至基类型的 :attr:`__init__` 方法。" #: ../../extending/newtypes_tutorial.rst:847 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 "" "这个模式在编写具有自定义 :c:member:`~PyTypeObject.tp_new` 和 " ":c:member:`~PyTypeObject.tp_dealloc` 成员的类型时很重要。 " ":c:member:`~PyTypeObject.tp_new` 处理器不应为具有 :c:member:`~PyTypeObject.tp_alloc`" " 的对象实际分配内存,而是让基类通过调用自己的 :c:member:`~PyTypeObject.tp_new` 来处理它。" #: ../../extending/newtypes_tutorial.rst:853 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 "" ":c:type:`PyTypeObject` 支持用 :c:member:`~PyTypeObject.tp_base` 指定类型的实体基类。 " "由于跨平台编译器问题,你无法使用对 :c:type:`PyList_Type` 的引用来直接填充该字段;它应当随后在模块初始化函数中完成::" #: ../../extending/newtypes_tutorial.rst:881 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 "" "在调用 :c:func:`PyType_Ready` 之前,类型结构体必须已经填充 :c:member:`~PyTypeObject.tp_base` " "槽位。 当我们从现有类型派生时,它不需要将 :c:member:`~PyTypeObject.tp_alloc` 槽位填充为 " ":c:func:`PyType_GenericNew` -- 来自基类型的分配函数将会被继承。" #: ../../extending/newtypes_tutorial.rst:887 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 "在那之后,调用 :c:func:`PyType_Ready` 并向模块添加类型对象是与基本的 :class:`Custom` 示例一样的。" #: ../../extending/newtypes_tutorial.rst:892 msgid "Footnotes" msgstr "备注" #: ../../extending/newtypes_tutorial.rst:893 msgid "" "This is true when we know that the object is a basic type, like a string or " "a float." msgstr "当我们知道该对象属于基本类型,如字符串或浮点数时情况就是如此。" #: ../../extending/newtypes_tutorial.rst:896 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 "" "在本示例中我们需要 :c:member:`~PyTypeObject.tp_dealloc` 处理器中的这一机制,因为我们的类型不支持垃圾回收。" #: ../../extending/newtypes_tutorial.rst:899 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 "" "现在我们知道 first 和 last 成员都是字符串,因此也许我们可以对减少它们的引用计数不必太过小心,但是,我们还接受字符串子类的实例。 " "即使释放普通字符串不会对我们的对象执行回调,我们也不能保证释放一个字符串子类的实例不会对我们的对象执行回调。" #: ../../extending/newtypes_tutorial.rst:905 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 "而且,即使是将我们的属性限制为字符串实例,用户还是可以传入任意 :class:`str` 子类因而仍能造成引用循环。"