构建自引用元组

2024-01-07

在看到多年前的论坛上的一次从未解决的对话后,我想知道如何正确创建一个引用自身的元组。从技术上讲,这是一个非常糟糕的主意,因为元组应该是不可变的。一个不可变的对象怎么可能包含它自己呢?然而,这个问题不是关于最佳实践,而是关于 Python 中可能的问题。

import ctypes

def self_reference(array, index):
    if not isinstance(array, tuple):
        raise TypeError('array must be a tuple')
    if not isinstance(index, int):
        raise TypeError('index must be an int')
    if not 0 <= index < len(array):
        raise ValueError('index is out of range')
    address = id(array)
    obj_refcnt = ctypes.cast(address, ctypes.POINTER(ctypes.c_ssize_t))
    obj_refcnt.contents.value += 1
    if ctypes.cdll.python32.PyTuple_SetItem(ctypes.py_object(array),
                                            ctypes.c_ssize_t(index),
                                            ctypes.py_object(array)):
        raise RuntimeError('PyTuple_SetItem signaled an error')

前面的函数旨在访问 Python 的 C API,同时牢记内部结构和数据类型。但是,在运行该函数时,通常会产生以下错误。通过未知的过程,以前已经可以通过类似的技术创建自引用元组。

问题:功能应该如何self_reference是否可以修改为始终持续工作?

>>> import string
>>> a = tuple(string.ascii_lowercase)
>>> self_reference(a, 2)
Traceback (most recent call last):
  File "<pyshell#56>", line 1, in <module>
    self_reference(a, 2)
  File "C:/Users/schappell/Downloads/srt.py", line 15, in self_reference
    ctypes.py_object(array)):
WindowsError: exception: access violation reading 0x0000003C
>>> 

Edit:以下是与口译员的两次不同对话,有些令人困惑。如果我正确理解文档,上面的代码似乎是正确的。然而,下面的对话似乎相互冲突,而且self_reference上面的功能。

对话1:

Python 3.2.3 (default, Apr 11 2012, 07:15:24) [MSC v.1500 32 bit (Intel)]
on win32
Type "copyright", "credits" or "license()" for more information.
>>> from ctypes import *
>>> array = tuple(range(10))
>>> cast(id(array), POINTER(c_ssize_t)).contents.value
1
>>> cast(id(array), POINTER(c_ssize_t)).contents.value += 1
>>> cast(id(array), POINTER(c_ssize_t)).contents.value
2
>>> array
(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
>>> cdll.python32.PyTuple_SetItem(c_void_p(id(array)), 0,
                                  c_void_p(id(array)))
Traceback (most recent call last):
  File "<pyshell#6>", line 1, in <module>
    cdll.python32.PyTuple_SetItem(c_void_p(id(array)), 0,
                                  c_void_p(id(array)))
WindowsError: exception: access violation reading 0x0000003C
>>> cdll.python32.PyTuple_SetItem(c_void_p(id(array)), 0,
                                  c_void_p(id(array)))
Traceback (most recent call last):
  File "<pyshell#7>", line 1, in <module>
    cdll.python32.PyTuple_SetItem(c_void_p(id(array)), 0,
                                  c_void_p(id(array)))
WindowsError: exception: access violation reading 0x0000003C
>>> array
(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
>>> cdll.python32.PyTuple_SetItem(c_void_p(id(array)), 0,
                                  c_void_p(id(array)))
0
>>> array
((<NULL>, <code object __init__ at 0x02E68C50, file "C:\Python32\lib
kinter\simpledialog.py", line 121>, <code object destroy at 0x02E68CF0,
file "C:\Python32\lib   kinter\simpledialog.py", line 171>, <code object
body at 0x02E68D90, file "C:\Python32\lib      kinter\simpledialog.py",
line 179>, <code object buttonbox at 0x02E68E30, file "C:\Python32\lib
kinter\simpledialog.py", line 188>, <code object ok at 0x02E68ED0, file
"C:\Python32\lib        kinter\simpledialog.py", line 209>, <code object
cancel at 0x02E68F70, file "C:\Python32\lib    kinter\simpledialog.py",
line 223>, <code object validate at 0x02E6F070, file "C:\Python32\lib
kinter\simpledialog.py", line 233>, <code object apply at 0x02E6F110, file
"C:\Python32\lib     kinter\simpledialog.py", line 242>, None), 1, 2, 3, 4,
5, 6, 7, 8, 9)
>>>

对话2:

Python 3.2.3 (default, Apr 11 2012, 07:15:24) [MSC v.1500 32 bit (Intel)]
on win32
Type "copyright", "credits" or "license()" for more information.
>>> from ctypes import *
>>> array = tuple(range(10))
>>> cdll.python32.PyTuple_SetItem(c_void_p(id(array)), c_ssize_t(1),
                                  c_void_p(id(array)))
0
>>> array
(0, (...), 2, 3, 4, 5, 6, 7, 8, 9)
>>> array[1] is array
True
>>>

感谢nneonneo的帮助,我决定执行以下self_reference method.

import ctypes

ob_refcnt_p = ctypes.POINTER(ctypes.c_ssize_t)

class GIL:
    acquire = staticmethod(ctypes.pythonapi.PyGILState_Ensure)
    release = staticmethod(ctypes.pythonapi.PyGILState_Release)

class Ref:
    dec = staticmethod(ctypes.pythonapi.Py_DecRef)
    inc = staticmethod(ctypes.pythonapi.Py_IncRef)

class Tuple:
    setitem = staticmethod(ctypes.pythonapi.PyTuple_SetItem)
    @classmethod
    def self_reference(cls, array, index):
        if not isinstance(array, tuple):
            raise TypeError('array must be a tuple')
        if not isinstance(index, int):
            raise TypeError('index must be an int')
        if not 0 <= index < len(array):
            raise ValueError('index is out of range')
        GIL.acquire()
        try:
            obj = ctypes.py_object(array)
            ob_refcnt = ctypes.cast(id(array), ob_refcnt_p).contents.value
            for _ in range(ob_refcnt - 1):
                Ref.dec(obj)
            if cls.setitem(obj, ctypes.c_ssize_t(index), obj):
                raise SystemError('PyTuple_SetItem was not successful')
            for _ in range(ob_refcnt):
                Ref.inc(obj)
        finally:
            GIL.release()

要使用该方法,请按照下面显示的示例创建您自己的自引用元组。

>>> array = tuple(range(5))
>>> Tuple.self_reference(array, 1)
>>> array
(0, (...), 2, 3, 4)
>>> Tuple.self_reference(array, 3)
>>> array
(0, (...), 2, (...), 4)
>>> 
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

构建自引用元组 的相关文章

随机推荐

  • Cordova,在 Ubuntu 14.04 上添加 Android 平台时出现错误

    我安装了 cordova 并且可以毫无问题地创建一个新项目 但是 当我尝试添加 Android 平台时 出现以下错误 sudo cordova platform add android Running platform task Addin
  • 将字符串写入 NSPasteBoard

    我无法让这个方法返回 YES BOOL writeToPasteBoard NSString stringToWrite return pasteBoard setString stringToWrite forType NSStringP
  • 在 OS X Yosemite 上构建 binutils 的交叉编译

    我正在尝试构建 binutils 以在 Mac OS X 上生成 MIPS 代码 我找到了这个网站 http www theairportwiki com index php Building a cross compile of GCC
  • 如何使用 Moment.js 从日期中删除时间?

    formatCalendarDate function dateTime return moment utc dateTime format LLL 它显示 2013 年 2 月 28 日 09 24 但我想删除最后的时间 我怎样才能做到这
  • 如何在asdict中获取@property方法?

    我有类似的东西 from attr import attrs attrib attrs class Foo max count attrib property def get max plus one self return self ma
  • 库未加载 @rpath/AFNetworking iOS

    使用自定义 我自己创建的 框架将我的应用程序安装到设备上时 我遇到了非常奇怪的问题 MyFramework 使用 AFNetworking Dropbox 和 Google Drive 我只是将 MyFramework 拖到我的应用程序中并
  • 按列和最大日期分组时如何选择单行?

    我有以下数据想要过滤 所以我只根据第一列的分组得到一行并选择最大日期 co2 包含独特的值 col1 col2 date 1 123 2013 1 124 2012 1 125 2014 2 213 2011 2 214 2015 2 21
  • 我需要多个 EVP_CIPHER_CTX 结构吗?

    我有一个单线程客户端 服务器应用程序 需要对其网络通信进行加密和解密 我计划使用 OpenSSL 的 EVP API 和 AES 256 CBC 我从几个例子中找到了一些示例伪代码 key is 256 bits 32 bytes when
  • Vbscript列出文件夹和子文件夹中的所有PDF文件

    好吧 这是我的代码 但我无法使用 objFile Extension 过滤列表 我确信这很愚蠢 Set objFSO CreateObject Scripting FileSystemObject objStartFolder C dev
  • 了解 Vulkan 统一布局的“集合”索引

    我一直在关注 非常棒的 nvpro 光线追踪教程 并且对使用 CameraProperties 统一缓冲区的绑定方式有疑问layout binding 0 set 1 我理解绑定 0 但为什么设置 1 教程中说 set 1来自以下事实 它是
  • 导入错误:没有名为 cv2.cv 的模块

    python 3 5 和 Windows 10 我使用以下命令安装了 open cv pip install opencv python 3 1 0 cp35 cp35m win amd64 whl 这个命令在 python 中工作正常 i
  • 是否有与 git archive 相反的命令用于导入 zip 文件

    在主要修订正式纳入 大 公司 SCM 系统之前 我们的本地工作流程倾向于使用一系列 zip 文件作为本地 源代码控制 我正在尝试引入 git 作为一种更好的本地 SCM 方法 当前的工作流程对于我们的小团队来说非常有效 特别是当测试机器离线
  • Visual Studio 2015 中缺少 Xamarin 空白应用程序(本机)模板

    我已经在 Visual Studio 2015 中安装了使用 Xamarin 进行开发的所有工具 但不知何故 当我创建新项目时 我没有看到空白应用程序 本机 模板 我只能使用空白应用程序 Xamarin Forms 模板 我已经尝试重新安装
  • 如何对 Symfony2 控制器进行单元测试?

    我想尽可能多地使用测试驱动开发 这是一种很好的工作方式 我对 Symfony2 控制器创建并返回一个新的事实感到困扰Response object 我希望能够对控制器进行单独的单元测试 你怎么做呢 答案是创建一个控制器作为普通旧 PHP 对
  • SQL Server 更改计算列

    有谁知道如何更改计算列而不删除 SQL Server 中的列 我想停止使用该列作为计算列并开始直接在列中存储数据 但希望保留当前值 这可能吗 据我所知 但这是你可以做的事情 添加另一列到表中 使用计算列的值更新该列 然后删除计算列
  • 使用 Python 将 BMP/PNG/JPEG 转换为 SVG 文件

    我目前正在尝试使用 Python 将 BMP 文件转换为 SVG 文件 我正在尝试找到一个 Python 库 使我能够将 BMP PNG JPEG 文件转换为 SVG 文件 我已经尝试过使用 Potrace 但质量很糟糕 我需要相当高质量的
  • 不同文件夹中的文件具有相同的命名空间

    我正在尝试构建一个项目 以便自动生成的一些代码位于子文件夹中generated 但它与父目录中的文件具有相同的命名空间 例如 我有这个结构 它给了我错误PHP Fatal error Uncaught Error Class MyProje
  • 将文本字符串中的任何 url 替换为可单击的 php 链接

    假设我有一串文本 例如 text Hello world be sure to visit http whatever com today 我如何 可能使用正则表达式 插入链接的锚标记 将链接本身显示为链接文本 您可以使用正则表达式来执行此
  • 检测颜色并从图像中删除该颜色

    我的图像背景为浅紫色图像 字符为深蓝色 我的目标是从图像中识别文本 所以我试图从背景中删除浅紫色 以便我的图像没有噪音 但我找不到该图像的确切颜色代码 因为它在各处都有些不同 所以我无法遮盖图像 这是我的代码 import numpy as
  • 构建自引用元组

    在看到多年前的论坛上的一次从未解决的对话后 我想知道如何正确创建一个引用自身的元组 从技术上讲 这是一个非常糟糕的主意 因为元组应该是不可变的 一个不可变的对象怎么可能包含它自己呢 然而 这个问题不是关于最佳实践 而是关于 Python 中