我有一个类C
,它表示一个未知的值的整数。 C
实现允许在算术表达式中使用的所有方法(包括__add__
,__sub__
等),通常返回类型为C
的新对象。
我想欺骗python解释器,使其相信C
类型的对象确实是一个整数,即使它不是。所以,例如,我希望能够写出类似的内容:
c = C()
for i in range(c):
print(i)
目前,这样做会产生错误:TypeError: 'C' object cannot be interpreted as an integer
。相反,我希望范围函数认为c
是一个整数,并尝试执行其代码将c
视为有效整数(可能会在以后c
时导致错误在C
类型的操作中使用,不支持或出于任何其他原因。)
一般来说,我不希望c
计算到一个特定的整数,我只想让它对任何要求它的类型的人说(就像范围函数显然那样)“嘿!我是一个整数相信我!“。
我不知道这是否可以通过聪明的方式完成子类化int
,但我最近的所有尝试都失败了。
我还尝试重载类__index__
的方法C
,该方法用于将C
类型的对象转换为整数,但我不允许返回{{1因为self
不是self
类型,所以在该方法中。
有没有办法实现这个目标?
使用案例
我正在尝试实现此功能,以实现Python代码的动态符号执行程序。给定一个输入整数的函数int
,使用我的库,可以在类型为f
的对象f
上调用函数s
上述类型SymbolicInt
)。函数代码使用对象C
。每当在s
+ 3之类的操作中使用它时,结果就是s
形式的符号表达式。理想情况下,涉及符号整数的所有操作都返回符号表达式而不是具体值。当请求已知计算为布尔类型(如SymbolicAdd(s, 3)
)的符号表达式的布尔值时,我的库会判断它是否存在变量SymbolicLessThan(SymbolicInt('x'), 10)
的任何值以使条件成立{ {1}}以及变量x
是否存在任何值以使条件保持True
。在x
的两个值都存在的情况下,当前的Python进程是分叉的,并且两个独立的进程继续执行代码,一个假设表达式是False
而另一个假设是x
}。
实际上,这意味着将探索输入符号输入的函数的所有可能执行路径,而不是仅在执行具体输入时通常发生的一个。
回到True
相关示例,范围输入一个整数(实际上最多3个整数,但让我们考虑一下这个简单的情况)并对这样的整数进行操作(将计数器设置为0,执行一个while循环直到这样的计数器与提供的整数不同,在每一步将计数器递增1(我知道它不完全是这样,但我们假设它是为了清晰起见))。现在,当输入范围中的符号整数用于布尔表达式时,我的库负责分支当前进程(如果需要)并返回它的具体布尔值,但在此之前它只是一个没有预定义值的符号整数当它被用于各种操作时,它可以将自身转换为符号表达式。
我现在遇到的问题是,范围拒绝接受一个False
对象作为“它不是一个int”的输入,但我希望它接受它并在操作中使用它分支条件就像它一样。
我希望这能澄清我的意图。
答案 0 :(得分:3)
我不确定你是否想过这个。 range()
不只是接受int
输入,它将整个行为基于该整数的数值。传入一个'未知'整数是没有意义的,因为没有该对象的具体数值,range()
如何在迭代时知道范围的边界?
换句话说,只要预期具体的整数值,就会使用__index__
。 想要使用__index__
的任何内容都不需要int
,它需要一个具体的数字。
如果您的类型无法提供具体值,则不应实现__index__
,并且不能在这些上下文中使用。
对于您的特定用例,听起来好像您必须 fork一个符号整数的每个可能的int值。如果您已经为该值设置了上限3
,则表示您需要将流程设置为4,具有int
的具体0
值,1
,{{ 1}}和2
。然后3
产生一个产生0到3个具体整数的序列。
我必须敦促您在没有运行代码的情况下查看static type inference并了解代码。像mypy这样的项目已经可以单独使用静态解析从代码中推断出大量信息,像Facebook Infer这样的工具可以更进一步,并为正在分析的代码选择可能的状态(尽管不是Python代码)