Python 3.x 如何创建元组的循环引用?

Python 3.x 如何创建元组的循环引用?,python-3.x,tuples,cpython,circular-reference,Python 3.x,Tuples,Cpython,Circular Reference,出于历史原因(阅读:可怕的type(t)=tuple检查),我发现自己需要将一个圆形图冻结为tuple对象的集合。显然,这并不理想: >>> head = ("head", None) >>> a = ("a", ("b", ("c", head))) >>> head[1] = a Traceback (most recent call last): File "<pyshell#3>", line 1, in <mo

出于历史原因(阅读:可怕的
type(t)=tuple
检查),我发现自己需要将一个圆形图冻结为
tuple
对象的集合。显然,这并不理想:

>>> head = ("head", None)
>>> a = ("a", ("b", ("c", head)))
>>> head[1] = a
Traceback (most recent call last):
  File "<pyshell#3>", line 1, in <module>
    head[1] = a
TypeError: 'tuple' object does not support item assignment
头=(“头”,无) >>>a=(“a”,“b”,“c”,标题))) >>>头[1]=a 回溯(最近一次呼叫最后一次): 文件“”,第1行,在 头[1]=a TypeError:“tuple”对象不支持项分配 一、 然而,我并不十分相信
TypeError
s,并且怀疑通过特定于实现的黑客技术,这是可以做到的

  • 我如何才能在不冒越界或导致其他C未定义行为的风险的情况下生成这个怪物
  • 垃圾收集器的循环依赖释放部分可以处理这样的事情吗
一、 然而,我并不十分相信类型错误,并且怀疑,通过特定于实现的黑客技术,这是可以做到的

遗憾的是,你是对的:

从ctypes导入结构、c_ssize_t、c_void_p、py_对象、pythonapi
pythonapi.Py_DecRef.argtypes=Py_对象,
def可变(tup):
#我们正在动态生成此类,因为ob_项的大小
#根据给定元组的大小而变化
类PyTupleObject(结构):
_字段=[('ob_refcnt',c_ssize_t),
('ob_type',c_void_p),
('ob_size',c_ssize_t),
('ob_item',py_object*len(tup))]
@类方法
来自参数组(cls,参数组)的def:
实例=cls.from_地址(id(tup))
#在实例上保存对tup的引用,因为我们直接从内存中使用它
#也不希望它被垃圾收集
instance.original=tup
返回实例
定义设置项(self、idx、val):
#替换self.ob_项中的值不会减少旧值,但会减少新值
pythonapi.Py\u DecRef(self.ob\u项[idx])
self.ob_项目[idx]=val
def uu getitem uu(self,idx):
返回self.ob_项目[idx]
定义(自我):
返回iter(自身ob_项目)
定义(自我):
返回透镜(自身ob_项目)
def__;包含___;(self,val):
返回self.ob_项目中的val
返回PyTupleObject.from_tuple(tup)
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
tup=(无,)
mut_tup=mutable(tup)
mut_tup[0]=tup
打印(tup为tup[0])#输出“True”
我如何才能在不冒越界或导致其他C未定义行为的风险的情况下生成这个怪物

我们通过将成员
ob\u项
定义为
py\u object*len(tup)
来防止越界访问

垃圾收集器的循环依赖释放部分可以处理这样的事情吗


不!元组被认为是不可变的,因此不需要对其自身进行循环引用。这就是为什么他们没有实现
tp_clear
方法的原因,python垃圾收集器使用该方法来打破引用周期并收集相关垃圾。更多细节

显然有些人已经成功地使用了ctypes(请参阅),但对我来说,它总是有缺点。我不知道散列(a)对于假设的-freezed-circular-graph-stored-in-a-tuple应该如何工作,它可能会陷入无限循环。为什么不使用适当的图形库(如networkX)并在需要时定义图形/节点序列化程序?@wim为什么不使用
列表
?它实际上不是一个图,而是一个状态图。这是一段可怕的代码,应该烧掉,但现在还不能烧掉。我正在把它切碎,然后把它放进炉子里。(不过,您关于
散列(a)
的观点是有效的;这实际上可能不可能,这取决于代码使用
元组的目的。)。我求求你,再找一个可怕的黑客。那么sed's/type(t)=tuple/True/’呢?
?发挥创意吧。重写
type()
和特例
t
的返回值。来吧,我相信你。@JohnKugelmansupportsMonica上次我试着修改
\uuuu内置物时,结果非常糟糕。但我想这不可能比这更糟。事实上,动态地将
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
的类型修改为具有空
\uuuuuuuuuu插槽的
子类可能更安全,实现
\uuuu getitem\uuuuuu
并替换
type
的实现,只用于可怕的模块…我想我已经在某个地方找到了该模块的代码。警告:对结果元组调用
哈希
,或将其用于集合或作为字典键,将导致堆栈溢出。这不是每次运行
mutable(tup)
时都会创建一个新的
PyTupleObject
类吗?(是的,这肯定是这段代码的最大问题,而且根本不存在。)它确实存在,因为结构的大小随元组的长度而变化。我没有找到创建可变大小结构类的方法:)