当前位置:  开发笔记 > 编程语言 > 正文

在创建元组的子类时调用__new__

如何解决《在创建元组的子类时调用__new__》经验,为你挑选了1个好方法。

在Python中,当子类化元组时,__new__使用self作为参数调用该函数.例如,这是PySpark Row类的一个释义版本:

class Row(tuple):
    def __new__(self, args):
        return tuple.__new__(self, args)

help(tuple)没有显示出self参数__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传递?__new__Row

是通过*args吗?

确实__new__有一些细微之处,其中它的签名可以与情境改变?

或者,文档是否有误?

是否有可能查看源代码,tuple.__new__以便我可以自己查看答案?

我的问题不是这个问题的重复,因为在那个问题中,所有的讨论都是指__new__明确拥有selfcls作为第一个参数的方法.我想了解一下

    为什么该tuple.__new__方法没有selfcls作为第一个参数.

    我如何去检查元组类的源代码,看看自己到底发生了什么.

Andrea Corbe.. 11

正确的签名 tuple.__new__

在C中实现的函数和类型通常无法检查,并且它们的签名总是看起来像那个.

正确的签名tuple.__new__是:

__new__(cls[, sequence])

例如:

>>> tuple.__new__(tuple)
()
>>> tuple.__new__(tuple, [1, 2, 3])
(1, 2, 3)

毫不奇怪,tuple()除了你必须重复tuple两次这一事实之外,这就像打电话一样.


第一个论点 __new__

请注意,第一个参数__new__始终是类,而不是实例.实际上,角色__new__是创建并返回新实例.

特殊方法__new__是静态方法.

我这样说是因为在你Row.__new__看来我可以看到self:虽然参数的名称并不重要(除非使用关键字参数),但要注意这self将是Row或者是子类Row,而不是实例.一般惯例是命名第一个参数cls而不是self.


回到你的问题

那么如何在类定义中self传递?__new__Row

当你打电话时Row(...),Python会自动调用Row.__new__(Row, ...).

是通过*args吗?

你可以写Row.__new__如下:

class Row(tuple):
    def __new__(*args, **kwargs):
        return tuple.__new__(*args, **kwargs)

这有效,并没有错.如果你不关心这些论点,那将非常有用.

确实__new__有一些细微之处,其中它的签名可以与情境改变?

不,唯一特别之处__new__在于它是一种静态方法.

或者,文档是否有误?

我会说它不完整或含糊不清.

为什么该tuple.__new__方法没有selfcls作为第一个参数.

它确实有,它只是没有出现help(tuple.__new__),因为通常该信息不会被C中实现的功能和方法暴露.

我如何去研究tuple班级的源代码,亲眼看看自己到底发生了什么.

您要查找的文件是Objects/tupleobject.c.具体来说,您对该tuple_new()功能感兴趣:

static char *kwlist[] = {"sequence", 0};
/* ... */
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:tuple", kwlist, &arg))

"|O:tuple"意味着:该函数被称为"tuple",它接受一个可选参数(|分隔可选参数,O代表Python对象).可以通过关键字参数设置可选参数sequence.


关于 help(type)

作为参考,您正在查看文档type.__new__,而您应该在前四行停止help(type):

__new__()正确签名的情况下签名是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__签名不同.


记住super()!

最后但并非最不重要的是,尝试使用super()而不是tuple.__new__()直接调用.



1> Andrea Corbe..:

正确的签名 tuple.__new__

在C中实现的函数和类型通常无法检查,并且它们的签名总是看起来像那个.

正确的签名tuple.__new__是:

__new__(cls[, sequence])

例如:

>>> tuple.__new__(tuple)
()
>>> tuple.__new__(tuple, [1, 2, 3])
(1, 2, 3)

毫不奇怪,tuple()除了你必须重复tuple两次这一事实之外,这就像打电话一样.


第一个论点 __new__

请注意,第一个参数__new__始终是类,而不是实例.实际上,角色__new__是创建并返回新实例.

特殊方法__new__是静态方法.

我这样说是因为在你Row.__new__看来我可以看到self:虽然参数的名称并不重要(除非使用关键字参数),但要注意这self将是Row或者是子类Row,而不是实例.一般惯例是命名第一个参数cls而不是self.


回到你的问题

那么如何在类定义中self传递?__new__Row

当你打电话时Row(...),Python会自动调用Row.__new__(Row, ...).

是通过*args吗?

你可以写Row.__new__如下:

class Row(tuple):
    def __new__(*args, **kwargs):
        return tuple.__new__(*args, **kwargs)

这有效,并没有错.如果你不关心这些论点,那将非常有用.

确实__new__有一些细微之处,其中它的签名可以与情境改变?

不,唯一特别之处__new__在于它是一种静态方法.

或者,文档是否有误?

我会说它不完整或含糊不清.

为什么该tuple.__new__方法没有selfcls作为第一个参数.

它确实有,它只是没有出现help(tuple.__new__),因为通常该信息不会被C中实现的功能和方法暴露.

我如何去研究tuple班级的源代码,亲眼看看自己到底发生了什么.

您要查找的文件是Objects/tupleobject.c.具体来说,您对该tuple_new()功能感兴趣:

static char *kwlist[] = {"sequence", 0};
/* ... */
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:tuple", kwlist, &arg))

"|O:tuple"意味着:该函数被称为"tuple",它接受一个可选参数(|分隔可选参数,O代表Python对象).可以通过关键字参数设置可选参数sequence.


关于 help(type)

作为参考,您正在查看文档type.__new__,而您应该在前四行停止help(type):

__new__()正确签名的情况下签名是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__签名不同.


记住super()!

最后但并非最不重要的是,尝试使用super()而不是tuple.__new__()直接调用.

推荐阅读
echo7111436
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有