Can 1 + 1 be equal to 3 in python?
在继续之前,我知道人们永远不应该这样做。这个问题纯粹是为了教育目的;我进行这个练习是为了更好地理解Python的内部,即
我知道在python中更改整数的值相对容易。实际上,你可以通过处理内部的问题来做很多事情。从C API参考中,
The current implementation keeps an array of integer objects for all
integers between -5 and 256, when you create an int in that range you
actually just get back a reference to the existing object. So it
should be possible to change the value of 1. I suspect the behaviour
of Python in this case is undefined. :-)
号
考虑到1的值是由cpython缓存的,这样做应该相对容易(或者至少可能)。经过一番周密的挖掘,我发现埃多克斯1〔0〕才是我要去的地方。然而,我尝试的大多数方法都会导致segfault。我通过改变2的值接近了。
1 2 3 4 5 | import ctypes def deref(addr, typ): return ctypes.cast(addr, ctypes.POINTER(typ)) deref(id(2), ctypes.c_int)[6] = 1 |
1+1现在给出了不正确的结果(朝着正确的方向迈出了一步),但我不能让它评估为"3":
1 2 3 4 5 6 7 8 | >>> 1 + 1 1 >>> 1 + 2 1 >>> 1 + 3 [1] 61014 segmentation fault python3.6 |
号
我尝试过类似的方法,但最终失败的是Abarnet的
disclaimer回答:这两个refers CPython只读;也可能会错过了希腊的问题…
我能够(有点)写一本市实现Python的C扩展。
在
1 2 3 4 | // the function in the same file that nb_add points to static PyObject * int_add(PyIntObject *v, PyIntObject *w) ... |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | #include <dlfcn.h> ... // symbol look-up from the Python extension void* addr = dlsym(RTLD_DEFAULT,"PyInt_Type"); // pointer to PyInt_Type PyTypeObject *int_type = addr; // pointer to int_as_number (PyInt_Type.tp_as_number) PyNumberMethods *int_funcs = int_type->tp_as_number; // pointer to int_add (tp_as_number->nb_add) int_add_orig = int_funcs->nb_add; // override this with a custom function int_funcs->nb_add = (binaryfunc)int_add_new; ... // custom add function PyObject *int_add_new(PyIntObject *v, PyIntObject *w) { long a = PyInt_AS_LONG(v); long b = PyInt_AS_LONG(w); // 1 + 1 = 3 special case if (a == 1 && b == 1) { return PyInt_FromLong(3); } // for all other cases default to the // original add function which was retrieved earlier return int_add_orig((PyObject *)v, (PyObject *)w); } |
全保市的原代码和内部变量的代码,《纽约avoids此前segfaults治疗:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | >>> # load the extension >>> import [...] >>> 1 + 1 2 >>> # call the extension function which overloads the add operator >>> 1 + 1 3 >>> 1 + 0 1 >>> 1 + 2 3 >>> 1 + 3 4 |