在创建元组的子类时调用__new__ [英] Calling __new__ when making a subclass of tuple

查看:63
本文介绍了在创建元组的子类时调用__new__的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在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


  1. 为什么 tuple .__ new __ 方法没有 self cls 作为第一个参数。

  2. 我该如何进行研究元组类的源代码,亲自了解实际情况。

  1. Why the tuple.__new__ method does not have self or cls as first argument.
  2. 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 the Row 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 have self or cls 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆