deb*_*ish 9 python static-methods super python-3.x
我理解这__new__是一个静态方法,super()可以从它调用创建一个新对象,如下所示:
>>> class A:
... def __new__(cls):
... print('__new__ called')
... return super().__new__(cls)
...
>>> a = A()
__new__ called
Run Code Online (Sandbox Code Playgroud)
为什么super调用不能与其他静态方法一起使用?为什么以下失败?
>>> class B:
... @staticmethod
... def funcB():
... print('funcB called')
...
>>> class C(B):
... @staticmethod
... def funcC():
... print('funcC called')
... super().funcB()
...
>>> c = C()
>>> c.funcC()
funcC called
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 5, in funcC
RuntimeError: super(): no arguments
Run Code Online (Sandbox Code Playgroud)
super() 在Python 3中没有参数基本上是对其基于参数的版本的破解.
当super()没有参数时,它获取第一个参数,即使用名为的特殊单元变量的类__class__,对于第二个参数,它将从堆栈中获取第一个局部变量(这将是函数的第一个参数).
如果__new__它可以得到(__class__和cls)并且工作正常.
但在这种情况下,例如除了__class__它之外没有第二个变量,因此它失败了.
class A:
@staticmethod
def func():
super().func() # super(__class__, <missing>).func()
A().func() # RuntimeError: super(): no arguments
Run Code Online (Sandbox Code Playgroud)
现在,如果我们改变它以接受一个参数,那么事情会改变:
class A:
@staticmethod
def func(foo):
super().func()
# This fails because super(B, 1).func() doesn't make sense.
A().func(1) # TypeError: super(type, obj): obj must be an instance or subtype of type
# Works! But as there's no parent to this class with func() it fails as expected.
A().func(A()) # AttributeError: 'super' object has no attribute 'func'
Run Code Online (Sandbox Code Playgroud)
因此,唯一的解决方案是super()在您的情况下使事情明确:
super(C, C).funcC()
Run Code Online (Sandbox Code Playgroud)
一般来说,我不确定为什么静态方法的实现不能成为异常并且使用__class__两个参数来使其工作.
相关的CPython代码:
static int
super_init(PyObject *self, PyObject *args, PyObject *kwds)
{
superobject *su = (superobject *)self;
PyTypeObject *type = NULL;
PyObject *obj = NULL;
PyTypeObject *obj_type = NULL;
if (!_PyArg_NoKeywords("super", kwds))
return -1;
if (!PyArg_ParseTuple(args, "|O!O:super", &PyType_Type, &type, &obj))
return -1;
if (type == NULL) {
/* Call super(), without args -- fill in from __class__
and first local variable on the stack. */
PyFrameObject *f;
PyCodeObject *co;
Py_ssize_t i, n;
f = PyThreadState_GET()->frame;
if (f == NULL) {
PyErr_SetString(PyExc_RuntimeError,
"super(): no current frame");
return -1;
}
co = f->f_code;
if (co == NULL) {
PyErr_SetString(PyExc_RuntimeError,
"super(): no code object");
return -1;
}
if (co->co_argcount == 0) {
PyErr_SetString(PyExc_RuntimeError,
"super(): no arguments");
return -1;
}
...
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
901 次 |
| 最近记录: |