在创建元组的子类时调用__new__ [英] Calling __new__ when making a subclass of tuple
问题描述
在Python中,当对元组进行子类化时, __ new __
函数。例如,以下是PySpark的 Row
类的释义版本:
In Python, when subclassing tuple, the __new__
function is called with self as an argument. For example, here is a paraphrased version of PySpark's Row
class:
class Row(tuple):
def __new__(self, args):
return tuple.__new__(self, args)
但是 help(tuple)
没有显示<$ c $ self> 自变量c> __ new __ :
But help(tuple)
shows no self
argument to __new__
:
__new__(*args, **kwargs) from builtins.type
Create and return a new object. See help(type) for accurate signature.
和 help(type)
只是说相同的东西:
__new__(*args, **kwargs)
Create and return a new object. See help(type) for accurate signature.
那么 self
如何传递给< Row
类定义中的code> __ new __ ?
So how does self
get passed to __new__
in the Row
class definition?
- 是通过
* args
吗? -
__ new __
有一些微妙之处,其签名可以随上下文而改变吗? - 文档是否弄错了?
- Is it via
*args
? - Does
__new__
have some subtlety where its signature can change with context? - Or, is the documentation mistaken?
是否可以查看元组的来源。__new __
这样我就可以自己找到答案了。
Is it possible to view the source of tuple.__new__
so I can see the answer for myself?
我的问题不是这个,因为在该问题中,所有讨论都引用了 __ new __
方法,这些方法明确具有自身
或 cls
作为第一个参数。我试图理解
My question is not a duplicate of this one because in that question, all discussion refers to __new__
methods that explicitly have self
or cls
as first argument. I'm trying to understand
- 为什么
tuple .__ new __
方法没有self
或cls
作为第一个参数。 - 我该如何进行研究元组类的源代码,亲自了解实际情况。
- Why the
tuple.__new__
method does not haveself
orcls
as first argument. - How I might go about examining the source code of the tuple class, to see for myself what's really going on.
推荐答案
tuple .__ new __
在C中实现的函数和类型的正确签名通常无法检查,它们的
The correct signature of tuple.__new__
Functions and types implemented in C often can't be inspected, and their signature always look like that one.
tuple .__ new __
的正确签名是:
__new__(cls[, sequence])
例如:
>>> tuple.__new__(tuple)
()
>>> tuple.__new__(tuple, [1, 2, 3])
(1, 2, 3)
毫不奇怪,这与调用 tuple()
完全一样,除了必须重复 tuple
两次。
Not surprisingly, this is exactly as calling tuple()
, except for the fact that you have to repeat tuple
twice.
请注意, __ new __
的第一个参数始终是类,而不是实例。实际上, __ new __
的作用是创建并返回新实例。
Note that the first argument of __new__
is always the class, not the instance. In fact, the role of __new__
is to create and return the new instance.
特殊方法 __ new __
是静态方法。
我之所以这样说是因为在您的行中。__new __
我可以看到 self
:尽管参数的名称并不重要(使用关键字参数时除外),但请注意 self
将是 Row
或 Row
的子类,而不是实例。一般约定是将第一个参数命名为 cls
而不是 self
。
I'm saying this because in your Row.__new__
I can see self
: while the name of the argument is not important (except when using keyword arguments), beware that self
will be Row
or a subclass of Row
, not an instance. The general convention is to name the first argument cls
instead of self
.
那么
self
传递给Row
类定义中的__ new __
吗?
So how does
self
get passed to__new__
in theRow
class definition?
调用 Row(...)
时,Python自动调用 Row .__ new __(Row,...)
。
When you call Row(...)
, Python automatically calls Row.__new__(Row, ...)
.
- 通过
* args
?
- Is it via
*args
?
您可以写您的 Row .__ new __
如下:
class Row(tuple):
def __new__(*args, **kwargs):
return tuple.__new__(*args, **kwargs)
这有效,没有任何问题。如果您不关心参数,这将非常有用。
This works and there's nothing wrong about it. It's very useful if you don't care about the arguments.
- 是否
__ new__
有一些微妙之处,其签名可以随上下文而改变?
- Does
__new__
have some subtlety where its signature can change with context?
否,关于 __ new __
的唯一特别之处是它是静态方法。
No, the only special thing about __new__
is that it is a static method.
- 或者,文档是否弄错了?
我会说
- 为什么
tuple .__ new __
方法没有self
或cls
作为第一个参数。
- Why the
tuple.__new__
method does not haveself
orcls
as first argument.
它确实有,只是没有出现在 help(tuple .__ new __)
上,因为通常这些信息不会被用C语言实现的功能和方法所公开。
It does have, it's just not appearing on help(tuple.__new__)
, because often that information is not exposed by functions and methods implemented in C.
- 我该怎么去研究<$的源代码c $ c> tuple 类,以了解自己的实际情况。
- How I might go about examining the source code of the
tuple
class, to see for myself what's really going on.
您要查找的文件是 Objects / tupleobject.c
。具体来说,您对 tuple_new( )
函数:
The file you are looking for is Objects/tupleobject.c
. Specifically, you are interested in the tuple_new()
function:
static char *kwlist[] = {"sequence", 0};
/* ... */
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:tuple", kwlist, &arg))
此处 | O:tuple
的意思是:该函数称为 tuple,它接受一个可选参数( |
分隔可选参数, O
代表Python对象)。可以通过关键字参数 sequence
设置可选参数。
Here "|O:tuple"
means: the function is called "tuple" and it accepts one optional argument (|
delimits optional arguments, O
stands for a Python object). The optional argument may be set via the keyword argument sequence
.
作为参考,您正在查看 type .__ new __
,而您应该已经停止在 help(type)
的前四行:
For the reference, you were looking at the documentation of type.__new__
, while you should have stopped at the first four lines of help(type)
:
对于 __ new __()
,正确的签名是 type()
的签名:
In the case of __new__()
the correct signature is the signature of type()
:
class type(object)
| type(object_or_name, bases, dict)
| type(object) -> the object's type
| type(name, bases, dict) -> a new type
但这并不重要,因为 tuple .__ new __
具有不同的签名。
But this is not relevant, as tuple.__new__
has a different signature.
最后但并非最不重要的是,尝试使用 super()
而不是调用 tuple .__ new __()
直接。
Last but not least, try to use super()
instead of calling tuple.__new__()
directly.
这篇关于在创建元组的子类时调用__new__的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!