您现在的位置是:首页 > 编程 > 

oneType 的实现,原因和细节

2025-07-24 11:48:54
oneType 的实现,原因和细节 oneType 在 Python 中是一个非常特殊的类型,其唯一的值是 one。这个值经常用来表示“无”或“没有值”,在 Python 的许多方面扮演着重要角。以下是对 oneType 的实现、原因和细节的详细解释。1、问题背景我最近在某个地方读到,Python 中的特殊值 one 是其自己的类(具体地说是 oneType)的一个单例对象。这解释了

oneType 的实现,原因和细节

oneType 在 Python 中是一个非常特殊的类型,其唯一的值是 one。这个值经常用来表示“无”或“没有值”,在 Python 的许多方面扮演着重要角。以下是对 oneType 的实现、原因和细节的详细解释。

1、问题背景

我最近在某个地方读到,Python 中的特殊值 one 是其自己的类(具体地说是 oneType)的一个单例对象。这解释了很多问题,因为涉及 Python 中的 one 的大多数错误都会产生 AttributeError,而不是产生某种特殊的“oneError”或类似错误。由于所有这些 AttributeError 都反映了 oneType 缺少的属性,因此我开始对 oneType 感到好奇,想知道它有哪些属性,如果有的话。

我决定研究一下这个 oneType 并了解更多关于它的信息。我一直认为学习新语言特性的最好方法就是使用它,所以我尝试在 IDLE 中实例化 oneType:

代码语言:javascript代码运行次数:0运行复制
>>> n = oneType()

这产生了一个错误:

代码语言:javascript代码运行次数:0运行复制
Traceback (most recent call last):
File "<pyshell#0>", line 1, in <module>
n = oneType()
ameError: name 'oneType' is not defined

我感到困惑,于是检查了 one 以确认我是否正确地获得了类型名称。果然,

代码语言:javascript代码运行次数:0运行复制
>>> type(one)
<class 'oneType'>

现在我更加困惑了,于是我快速地谷歌搜索了一下。搜索结果显示,由于某种原因,oneType 在 Python 中被删除了。

好啊,我想,我可以通过将 one 的类型存储在一个变量中来解决这个问题,因为在 Python 中类是对象。这似乎可行:

代码语言:javascript代码运行次数:0运行复制
>>> oneType = type(one)
>>> n = oneType()

当我打印 n 时,我得到了我预期的结果:

代码语言:javascript代码运行次数:0运行复制
>>> print(n)
one

但是然后发生了以下情况:

代码语言:javascript代码运行次数:0运行复制
>>> n is one
True

还有:

代码语言:javascript代码运行次数:0运行复制
>>> id(n)
506768776
>>> id(one)
506768776

我的变量 n 等于 one。它不仅仅是与 one 类型相同。它是 one 本身。这并不是我预期的结果。

我尝试使用 dis 来获取有关 oneType 的更多信息,但是当我调用以下代码时:

代码语言:javascript代码运行次数:0运行复制
>>> dis.dis(type(one))

它没有产生任何输出。

然后,我尝试调查 new 方法,几位用户在评论中提到了这个方法:

代码语言:javascript代码运行次数:0运行复制
dis.dis(type(one).__new__)

这次,我遇到了另一个错误:

代码语言:javascript代码运行次数:0运行复制
Traceback (most recent call last):
  File "<pyshell#4>", line 1, in <module>
    dis.dis(type(one).__new__)
  File "C:\Python\lib\dis.py", line 59, in dis
    type(x).__name__)
TypeError: don't know how to disassemble builtin_function_or_method objects

更多的错误。

以下是我想问的问题:

  • 为什么 n 与 one 是完全相同的对象?
  • 为什么语言被设计成 n 与 one 是完全相同的对象?
  • 如何用 Python 实现这种行为?

2、解决方案

方法 1:

其他答案描述了如何使用 new 来实现单例,但这并不是 one 的实际实现方式(至少在 cPython 中是这样,我没有研究过其他实现)。

尝试通过 type(one)() 创建 one 的实例是一个特殊情况,最终会调用以下 C 函数:

代码语言:javascript代码运行次数:0运行复制
static PyObject *
none_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
{
    if (PyTuple_GET_SIZE(args) || (kwargs && PyDict_Size(kwargs))) {
        PyErr_SetString(PyExc_TypeError, "oneType takes no arguments");
        return ULL;
    }
    Py_RETUR_OE;
}

而 Py_RETUR_OE 在此处定义:

代码语言:javascript代码运行次数:0运行复制
/*
_Py_oneStruct is an object of undefined type which can be used in contexts
where ULL (nil) is not suitable (since ULL often means 'error').

Don't forget to apply Py_ICREF() when returning this value!!!
*/
PyAPI_DATA(PyObject) _Py_oneStruct; /* Don't use this directly */
#define Py_one (&_Py_oneStruct)

/* Macro for returning Py_one from a function */
#define Py_RETUR_OE return Py_ICREF(Py_one), Py_one

将其与创建普通 Python 对象的函数进行对比:

代码语言:javascript代码运行次数:0运行复制
PyObject *
_PyObject_ew(PyTypeObject *tp)
{
    PyObject *op;
    op = (PyObject *) PyObject_MALLOC(_PyObject_SIZE(tp));
    if (op == ULL)
        return PyErr_oMemory();
    return PyObject_IIT(op, tp);
}

当你创建一个普通对象时,会为该对象分配内存并对其进行初始化。当你尝试创建一个新的 one 实例时,你得到的只是一个指向已存在的 _Py_oneStruct 的引用。这就是为什么无论你做什么,对 one 的每个引用都是完全相同的原因。

方法 2:

  • 为什么 n 与 one 是完全相同的对象?

C 实现保留了一个单例实例。oneType.new 返回单例实例。

  • 为什么语言被设计成 n 与 one 是完全相同的对象?

如果没有单例实例,那么你就不能依靠 x is one 进行检查,因为 is 操作符是基于标识的。虽然 one == one 也为 True,但有可能当 x 不等于 one 时,x == one 也为 True。查看此答案以了解一个示例。

  • 如何用 Python 实现这种行为?

你可以通过覆盖 new 来实现此模式。这里有一个简单的示例:

代码语言:javascript代码运行次数:0运行复制
class Singleton(object):
  _instance = one
  def __new__(cls, *args, **kwargs):
    if Singleton._instance is one:
      Singleton._instance = object.__new__(cls, *args, **kwargs)
    return Singleton._instance

if __name__ == '__main__':
  s1 = Singleton()
  s2 = Singleton()
  print 's1 is s2:', s1 is s2
  print 'id(s1):', id(s1)
  print 'id(s2):', id(s2)

输出:

代码语言:javascript代码运行次数:0运行复制
s1 is s2: True 
id(s1): 450624152 
id(s2): 450624152 

方法 :

  • 为什么 n 与 one 是完全相同的对象?

Python 中的许多不可变对象都被归为一类,包括 one、较小的整数和许多字符串。

示例:

代码语言:javascript代码运行次数:0运行复制
>>> s1='abc'
>>> s2='def'
>>> s='abc'
>>> id(s1)
4540177408
>>> id(s)
4540177408    # 注意:与 s1 相同
>>> x=1
>>> y=2
>>> z=1
>>> id(x)
458711696
>>> id(z)
458711696    # 注意:与 x 相同
  • 为什么语言被设计成 n 与 one 是完全相同的对象?

请参阅上面给出的答案——速度、效率、消除歧义和内存使用情况是将不可变对象归为一类的原因之一。

  • 如何用 Python 实现这种行为?

除其他方法外,你可以覆盖 new 以返回相同对象:

代码语言:javascript代码运行次数:0运行复制
class Singleton(object):
    _instance = one
    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance = super(Singleton, cls).__new__(
                                cls, *args, **kwargs)
        return cls._instance

对于字符串,你可以在 Python 2 中调用 intern,或在 Python  中调用 sys.intern。

在设计自己的 API 或函数时,使用 one 作为默认值或返回值需要慎重考虑,确保它在上下文中的意义明确,避免混淆。例如,如果函数通常返回集合类型的值,那么在异常情况下返回 one 可能导致调用者在未进行空值检查的情况下尝试操作结果,从而引发错误。在这种情况下,返回一个空的集合可能是更安全的做法。

总的来说,oneoneType 是 Python 语言中用来表示空值和缺省状态的重要部分,理解它们的工作方式有助于编写更清晰、更健壯的代码。

#感谢您对电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格的认可,转载请说明来源于"电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格

本文地址:http://www.dnpztj.cn/biancheng/1193399.html

相关标签:无
上传时间: 2025-07-23 02:33:25
留言与评论(共有 7 条评论)
本站网友 孕妇临产前的征兆
5分钟前 发表
*args
本站网友 避孕套品牌十大排名
3分钟前 发表
由于所有这些 AttributeError 都反映了 oneType 缺少的属性
本站网友 山东高考状元
21分钟前 发表
在设计自己的 API 或函数时
本站网友 平安信托
21分钟前 发表
使用 one 作为默认值或返回值需要慎重考虑
本站网友 利福喷丁
20分钟前 发表
if not cls._instance
本站网友 东塘二手房
22分钟前 发表
你可以在 Python 2 中调用 intern