python3.10_概述 — Python 3.10.0a2 文档

引用计数¶

The reference count is important because today's computers have a finite (and

often severely limited) memory size; it counts how many different places there

are that have a reference to an object. Such a place could be another object,

or a global (or static) C variable, or a local variable in some C function.

When an object's reference count becomes zero, the object is deallocated. If

it contains references to other objects, their reference count is decremented.

Those other objects may be deallocated in turn, if this decrement makes their

reference count become zero, and so on. (There's an obvious problem with

objects that reference each other here; for now, the solution is "don't do

that.")

Reference counts are always manipulated explicitly. The normal way is to use

the macro Py_INCREF() to increment an object's reference count by one,

and Py_DECREF() to decrement it by one. The Py_DECREF() macro

is considerably more complex than the incref one, since it must check whether

the reference count becomes zero and then cause the object's deallocator to be

called. The deallocator is a function pointer contained in the object's type

structure. The type-specific deallocator takes care of decrementing the

reference counts for other objects contained in the object if this is a compound

object type, such as a list, as well as performing any additional finalization

that's needed. There's no chance that the reference count can overflow; at

least as many bits are used to hold the reference count as there are distinct

memory locations in virtual memory (assuming sizeof(Py_ssize_t) >= sizeof(void*)).

Thus, the reference count increment is a simple operation.

It is not necessary to increment an object's reference count for every local

variable that contains a pointer to an object. In theory, the object's

reference count goes up by one when the variable is made to point to it and it

goes down by one when the variable goes out of scope. However, these two

cancel each other out, so at the end the reference count hasn't changed. The

only real reason to use the reference count is to prevent the object from being

deallocated as long as our variable is pointing to it. If we know that there

is at least one other reference to the object that lives at least as long as

our variable, there is no need to increment the reference count temporarily.

An important situation where this arises is in objects that are passed as

arguments to C functions in an extension module that are called from Python;

the call mechanism guarantees to hold a reference to every argument for the

duration of the call.

However, a common pitfall is to extract an object from a list and hold on to it

for a while without incrementing its reference count. Some other operation might

conceivably remove the object from the list, decrementing its reference count

and possibly deallocating it. The real danger is that innocent-looking

operations may invoke arbitrary Python code which could do this; there is a code

path which allows control to flow back to the user from a Py_DECREF(), so

almost any operation is potentially dangerous.

A safe approach is to always use the generic operations (functions whose name

begins with PyObject_, PyNumber_, PySequence_ or PyMapping_).

These operations always increment the reference count of the object they return.

This leaves the caller with the responsibility to call Py_DECREF() when

they are done with the result; this soon becomes second nature.

Reference Count Details¶

The reference count behavior of functions in the Python/C API is best explained

in terms of ownership of references. Ownership pertains to references, never

to objects (objects are not owned: they are always shared). "Owning a

reference" means being responsible for calling Py_DECREF on it when the

reference is no longer needed. Ownership can also be transferred, meaning that

the code that receives ownership of the reference then becomes responsible for

eventually decref'ing it by calling Py_DECREF() or Py_XDECREF()

when it's no longer needed---or passing on this responsibility (usually to its

caller). When a function passes ownership of a reference on to its caller, the

caller is said to receive a new reference. When no ownership is transferred,

the caller is said to borrow the reference. Nothing needs to be done for a

borrowed reference.

Conversely, when a calling function passes in a reference to an object, there

are two possibilities: the function steals a reference to the object, or it

does not. Stealing a reference means that when you pass a reference to a

function, that function assumes that it now owns that reference, and you are not

responsible for it any longer.

Few functions steal references; the two notable exceptions are

PyList_SetItem() and PyTuple_SetItem(), which steal a reference

to the item (but not to the tuple or list into which the item is put!). These

functions were designed to steal a reference because of a common idiom for

populating a tuple or list with newly created objects; for example, the code to

create the tuple (1, 2, "three") could look like this (forgetting about

error handling for the moment; a better way to code this is shown below):

PyObject *t;

t = PyTuple_New(3);

PyTuple_SetItem(t, 0, PyLong_FromLong(1L));

PyTuple_SetItem(t, 1, PyLong_FromLong(2L));

PyTuple_SetItem(t, 2, PyUnicode_FromString("three"));

Here, PyLong_FromLong() returns a new reference which is immediately

stolen by PyTuple_SetItem(). When you want to keep using an object

although the reference to it will be stolen, use Py_INCREF() to grab

another reference before calling the reference-stealing function.

Incidentally, PyTuple_SetItem() is the only way to set tuple items;

PySequence_SetItem() and PyObject_SetItem() refuse to do this

since tuples are an immutable data type. You should only use

PyTuple_SetItem() for tuples that you are creating yourself.

Equivalent code for populating a list can be written using PyList_New()

and PyList_SetItem().

However, in practice, you will rarely use these ways of creating and populating

a tuple or list. There's a generic function, Py_BuildValue(), that can

create most common objects from C values, directed by a format string.

For example, the above two blocks of code could be replaced by the following

(which also takes care of the error checking):

PyObject *tuple, *list;

tuple = Py_BuildValue("(iis)", 1, 2, "three");

list = Py_BuildValue("[iis]", 1, 2, "three");

It is much more common to use PyObject_SetItem() and friends with items

whose references you are only borrowing, like arguments that were passed in to

the function you are writing. In that case, their behaviour regarding reference

counts is much saner, since you don't have to increment a reference count so you

can give a reference away ("have it be stolen"). For example, this function

sets all items of a list (actually, any mutable sequence) to a given item:

int

set_all(PyObject *target, PyObject *item)

{

Py_ssize_t i, n;

n = PyObject_Length(target);

if (n < 0)

return -1;

for (i = 0; i < n; i++) {

PyObject *index = PyLong_FromSsize_t(i);

if (!index)

return -1;

if (PyObject_SetItem(target, index, item) < 0) {

Py_DECREF(index);

return -1;

}

Py_DECREF(index);

}

return 0;

}

The situation is slightly different for function return values. While passing

a reference to most functions does not change your ownership responsibilities

for that reference, many functions that return a reference to an object give

you ownership of the reference. The reason is simple: in many cases, the

returned object is created on the fly, and the reference you get is the only

reference to the object. Therefore, the generic functions that return object

references, like PyObject_GetItem() and PySequence_GetItem(),

always return a new reference (the caller becomes the owner of the reference).

It is important to realize that whether you own a reference returned by a

function depends on which function you call only --- the plumage (the type of

the object passed as an argument to the function) doesn't enter into it!

Thus, if you extract an item from a list using PyList_GetItem(), you

don't own the reference --- but if you obtain the same item from the same list

using PySequence_GetItem() (which happens to take exactly the same

arguments), you do own a reference to the returned object.

Here is an example of how you could write a function that computes the sum of

the items in a list of integers; once using PyList_GetItem(), and once

using PySequence_GetItem().

long

sum_list(PyObject *list)

{

Py_ssize_t i, n;

long total = 0, value;

PyObject *item;

n = PyList_Size(list);

if (n < 0)

return -1; /* Not a list */

for (i = 0; i < n; i++) {

item = PyList_GetItem(list, i); /* Can't fail */

if (!PyLong_Check(item)) continue; /* Skip non-integers */

value = PyLong_AsLong(item);

if (value == -1 && PyErr_Occurred())

/* Integer too big to fit in a C long, bail out */

return -1;

total += value;

}

return total;

}

long

sum_sequence(PyObject *sequence)

{

Py_ssize_t i, n;

long total = 0, value;

PyObject *item;

n = PySequence_Length(sequence);

if (n < 0)

return -1; /* Has no length */

for (i = 0; i < n; i++) {

item = PySequence_GetItem(sequence, i);

if (item == NULL)

return -1; /* Not a sequence, or other failure */

if (PyLong_Check(item)) {

value = PyLong_AsLong(item);

Py_DECREF(item);

if (value == -1 && PyErr_Occurred())

/* Integer too big to fit in a C long, bail out */

return -1;

total += value;

}

else {

Py_DECREF(item); /* Discard reference ownership */

}

}

return total;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值