是否可以使“type”的输出返回不同的类?

2024-02-12

所以免责声明:这个问题 https://stackoverflow.com/questions/56879033/how-do-i-override-type-method-in-python-object?noredirect=1#comment100306740_56879033激起了我的好奇心,我问这个纯粹是出于教育目的。我想这对于 Python 专家来说是一个更大的挑战!

是否有可能使输出type(foo)返回与实际实例类不同的值?即它能否冒充冒名顶替者并通过诸如type(Foo()) is Bar?

@juanpa.arrivilillaga https://stackoverflow.com/users/5014455/juanpa-arrivillaga提出了手动重新分配的建议__class__在实例上,但这会改变所有其他方法的调用方式。例如

class Foo:
    def test(self):
        return 1

class Bar:
    def test(self):
        return 2


foo = Foo()
foo.__class__ = Bar
print(type(foo) is Bar)
print(foo.test())

>>> True
>>> 2

期望的输出是True, 1。即返回的类type与实例不同,并且仍然会调用真实类中定义的实例方法。


不 - 的__class__属性是在 C API 级别本身“看到”的所有 Python 对象布局的基本信息。这就是通过调用来检查的type.

这意味着:每个 Python 对象在其内存布局中都有一个槽,其中包含用于指向 Python 对象(即该对象的类)的单个指针的空间。

即使您使用 ctypes 或其他方法来覆盖对该插槽的保护并从 Python 代码中更改它(因为修改obj.__class__ with =在 C 级别受到保护),更改它会有效地更改对象类型:__class__slot 是对象的类,并且test方法将从示例中的类(Bar)中选取。

但是这里有更多信息:在所有文档中,type(obj)被视为等价于obj.__class__- 但是,如果对象的类定义了一个具有名称的描述符__class__,当使用以下形式时使用obj.__class__. type(obj)但是会检查实例的__class__直接插入并返回真实的类。

所以,这可以“欺骗”代码使用obj.__class__, 但不是type(obj):

class Bar:
    def test(self):
        return 2

class Foo:
    def test(self):
        return 1
    @property
    def __class__(self):
        return Bar

元类的属性

试图搞乱创建一个__class__元类上的描述符Foo本身就会很混乱——两者type(Foo()) and repr(Foo())将报告一个instance of Bar,但“真正的”对象类将是 Foo。从某种意义上说,是的,它使得type(Foo())谎言,但不是你想象的那样 - type(Foo()) 将输出以下的 reprBar(), 但它是Foo由于内部的实现细节, 的 repr 被搞乱了type.__call__:

In [73]: class M(type): 
    ...:     @property 
    ...:     def __class__(cls): 
    ...:         return Bar 
    ...:                                                                                                                                               

In [74]: class Foo(metaclass=M): 
    ...:     def test(self): 
    ...:         return 1 
    ...:                                                                                                                                               

In [75]: type(Foo())                                                                                                                                   
Out[75]: <__main__.Bar at 0x55665b000578>

In [76]: type(Foo()) is Bar                                                                                                                            
Out[76]: False

In [77]: type(Foo()) is Foo                                                                                                                            
Out[77]: True

In [78]: Foo                                                                                                                                           
Out[78]: <__main__.Bar at 0x55665b000578>

In [79]: Foo().test()                                                                                                                                  
Out[79]: 1

In [80]: Bar().test()                                                                                                                                  
Out[80]: 2

In [81]: type(Foo())().test()                                                                                                                          
Out[81]: 1

修改type itself

既然没有人“进口”type从任何地方,只需使用 内置类型本身,可以对内置类型进行猴子修补type可调用来报告错误的类 - 它适用于所有人 Python代码在同一进程中依赖调用type:

original_type = __builtins__["type"] if isinstance("__builtins__", dict) else __builtins__.type

def type(obj_or_name, bases=None, attrs=None, **kwargs): 
    if bases is not None: 
        return original_type(obj_or_name, bases, attrs, **kwargs) 
    if hasattr(obj_or_name, "__fakeclass__"): 
        return getattr(obj_or_name, "__fakeclass__") 
    return original_type(obj_or_name) 

if isinstance(__builtins__, dict):
    __builtins__["type"] = type
else:
    __builtins__.type = type

del type

这里有一个技巧我在扩展坞中没有找到:访问时__builtins__在程序中,它充当字典。然而,在Python的Repl或Ipython等交互式环境中,它是一个 模块 - 检索原始数据type并写出修改后的 版本为__builtins__必须考虑到这一点 - 上面的代码 双向工作。

并对此进行测试(我从磁盘上的 .py 文件导入了上面的代码片段):

>>> class Bar:
...     def test(self):
...          return 2
... 
>>> class Foo:
...    def test(self):
...         return 1
...    __fakeclass__ = Bar
... 
>>> type(Foo())
<class '__main__.Bar'>
>>> 
>>> Foo().__class__
<class '__main__.Foo'>
>>> Foo().test()
1

尽管这适用于演示目的,但替换内置类型会导致“不和谐”,这在更复杂的环境(例如 IPython)中被证明是致命的:如果运行上面的代码片段,Ipython 将崩溃并立即终止。

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

是否可以使“type”的输出返回不同的类? 的相关文章

  • 为什么 pandas 在简单的数学运算上比 numpy 更快?

    最近 我观察到 pandas 的乘法速度更快 我在下面的例子中向您展示了这一点 如此简单的操作怎么可能做到这一点 这怎么可能呢 pandas 数据帧中的底层数据容器是 numpy 数组 测量 我使用形状为 10k 10k 的数组 数据框 i
  • Python设置1和True的解释

    在 IPython 3 交互式 shell 中 In 53 set2 1 2 True hello In 54 len set2 Out 54 3 In 55 set2 Out 55 hello True 2 是因为 1 和 True 得到
  • 如何在seaborn热图标签中使用科学计数法?

    我正在尝试在 python 中使用seaborn 获取热图 不幸的是 即使数字非常大 它也没有使用科学记数法 我想知道是否有任何简单的方法可以转换为科学记数法或任何其他合理的格式 这是显示问题的一段代码 import seaborn as
  • 如何使用 python、openCV 计算图像中的行数

    我想数纸张 所以我正在考虑使用线条检测 我尝试过一些方法 例如Canny HoughLines and FLD 但我只得到处理过的照片 我不知道如何计算 有一些小线段就是我们想要的线 我用过len lines or len contours
  • Python函数组成

    我尝试使用良好的语法来实现函数组合 这就是我所得到的 from functools import partial class compfunc partial def lshift self y f lambda args kwargs s
  • 如何在动态执行的代码字符串中使用inspect.getsource?

    如果我在文件中有这段代码 import inspect def sample p1 print p1 return 1 print inspect getsource sample 当我运行脚本时 它按预期工作 在最后一行 源代码sampl
  • 如何在 numpy 数组中查找并保存重复的行?

    我有一个数组 例如 Array 1 1 1 2 2 2 3 3 3 4 4 4 5 5 5 1 1 1 2 2 2 我想要输出以下内容的东西 Repeated 1 1 1 2 2 2 保留重复行的数量也可以 例如 Repeated 1 1
  • 烧瓶 - 404 未找到

    我是烧瓶开发的新手 这是我在烧瓶中的第一个程序 但它向我显示了这个错误 在服务器上找不到请求的 URL 如果您输入了网址 请手动检查拼写并重试 这是我的代码 from flask import Flask app Flask name ap
  • 样本()和r样本()有什么区别?

    当我从 PyTorch 中的发行版中采样时 两者sample and rsample似乎给出了类似的结果 import torch seaborn as sns x torch distributions Normal torch tens
  • Django Web 应用程序中的 SMTP 问题

    我被要求向使用 Django Python 框架实现的现有程序添加一个功能 此功能将允许用户单击一个按钮 该按钮将显示一个小对话框 表单以输入值 我确实编写了一些代码 显示电子邮件已发送的消息 但实际上 它没有发送 My code from
  • 如何将 Pyspark Dataframe 标题设置到另一行?

    我有一个如下所示的数据框 col1 col2 col3 id name val 1 a01 X 2 a02 Y 我需要从中创建一个新的数据框 使用 row 1 作为新的列标题并忽略或删除 col1 col2 等行 新表应如下所示 id na
  • Bokeh 中单独的节点和边缘悬停工具?

    我正在尝试为 Bokeh 中的节点和边缘获取单独的悬停工具提示 但未能使其正常工作 有人可以指出我做错了什么吗 我相信代码应该如下所示 from bokeh io import show output notebook from bokeh
  • django 中的身份验证方法返回 None

    你好 我在 django 中做了一个简单的注册和登录页面 当想要登录时 登录视图中的身份验证方法不返回任何内容 我的身份验证应用程序 模型 py from django db import models from django contri
  • 我可以在 if 语句中使用“as”机制吗

    是否可以使用as in if类似的声明with我们使用的 例如 with open tmp foo r as ofile do something with ofile 这是我的代码 def my list rtrn lst True if
  • Python 或 C 语言中的 Matlab / Octave bwdist()

    有谁知道 Matlab Octave bwdist 函数的 Python 替代品 此函数返回给定矩阵的每个单元格到最近的非零单元格的欧几里得距离 我看到了一个 Octave C 实现 一个纯 Matlab 实现 我想知道是否有人必须用 AN
  • 通过新数据更新绘图,而不是在 Jupyter 笔记本中制作新绘图

    我有一些问题 希望你能帮我解决 我需要使用下拉小部件创建交互式绘图 我可以在其中选择并绘制感兴趣的数据 我通过以下方式做到这一点 import plotly graph objects as go import ipywidgets as
  • 旧版本的 spaCy 在尝试安装模型时抛出“KeyError: 'package'”错误

    我在 Ubuntu 14 04 4 LTS x64 上使用 spaCy 1 6 0 和 python3 5 为了安装 spaCy 的英文版本 我尝试运行 这给了我错误消息 ubun ner 3 NeuroNER master src pyt
  • 如何在 Qt 中以编程方式制作一条水平线

    我想弄清楚如何在 Qt 中制作一条水平线 这很容易在设计器中创建 但我想以编程方式创建一个 我已经做了一些谷歌搜索并查看了 ui 文件中的 xml 但无法弄清楚任何内容 ui 文件中的 xml 如下所示
  • PYTHON:从 txt 文件中删除 POS 标签

    我有以下 txt 文件 其中包含 POS 词性 http en wikipedia org wiki Part of speech tagging 每个单词的标签 不用 jj到 说 vb 我 ppss是 bedz愤怒 jj在 在 dt无与伦
  • 当训练和测试的特征数量不同时,如何处理生产环境中的One-Hot Encoding?

    在做某些实验时 我们通常在 70 上进行训练 在 33 上进行测试 但是 当您的模型投入生产时会发生什么 可能会发生以下情况 训练集 Ser Type Of Car 1 Hatchback 2 Sedan 3 Coupe 4 SUV 经过

随机推荐

  • 如何访问 rowdatabound 上的 gridview 列?

    我想在值为 1 时将 gridview 列的值更改为活动状态 我有类似的 gridview 列
  • 为什么在类中实现的 C# 接口方法必须是公共的?

    我有一个继承接口的类 接口成员方法在我的类中实现 没有访问修饰符 因此 默认情况下它是 private 我收到错误 无法实现接口成员 因为它不是公共的 为什么不允许 我不能覆盖可访问性吗 这是一个例子why能够覆盖可见性是没有意义的 int
  • 在调整大小时保存 NSWindow 大小并为用户关闭

    我注意到 OS X 上的所有应用程序似乎都会保存您设置的大小 下次打开它时 它通常处于相同的位置和大小 我正在制作一个应用程序 我注意到调整大小后 如果我再次启动应用程序 它的大小只是我在 Xcode 4 的 IB 中设置的大小 而不是我在
  • 检查是否连接了打印机

    Windows 中有没有一种方法 在 Windows CE 中工作 来检查打印机是否已连接并与 C 中的 LPT1 进行通信 Edit 更多信息 我们目前正在使用通用 Windows CE 打印机驱动程序 pcl dll 通过将其传递到Cr
  • 将 Perfmon 分析解释为特定于应用程序的观察/数据的最佳方法是什么?

    我们很多人都使用过Perfmon工具来进行性能分析 特别是对于 Net 计数器 但 Perfmon 中存在太多变量 因此总是很难将 Perfmon 结果解释为有关我的应用程序的有价值的反馈 我想使用 perfmon 不是像蚂蚁分析器 htt
  • 如果我们是有效用户,我们可以克隆存储库吗?

    我是 Git 新手 所以如果这是一个愚蠢的问题 请原谅 在我们的组织中 我们使用 Git 作为存储库 我可以这样做git checkin checkout pull 从我的办公室机器 我们的 Git 存储库 URL 是这样的 但由于限制我无
  • 如何使 Flex Row 响应式 Bootstrap 4

    目前页面如下所示 现在 调整大小到移动屏幕时 弹性框会溢出容器 Html div class d flex flex row text white text center div class port item p 4 bg primary
  • 如何修改 C 程序以便 gprof 可以分析它?

    当我在我的 C 程序上运行 gprof 时 它说我的程序没有累积时间 并且所有函数调用都显示 0 时间 但是它确实对函数调用进行计数 如何修改我的程序 以便 gprof 能够计算某项运行所需的时间 编译的时候有没有指定 pg http so
  • 通过解析纯文本文件生成数据结构

    我为我正在编写的游戏编写了一个文件解析器 以便自己轻松更改游戏的各个方面 例如角色 舞台 碰撞数据 例如 我可能有一个像这样的字符类 class Character public int x y Character s location C
  • 使用 Golang 限制可执行文件的单个实例

    我一次只需要允许 Golang 可执行文件的一个实例 我不确定如何使用全局互斥体来确保没有其他实例正在运行 这将在 Windows 机器上运行 我知道这个主题有点老了 但我最近在 Windows 上需要它 我将在这里发布我是如何做到的 以防
  • 建立一个字典来按值查找键[重复]

    这个问题在这里已经有答案了 字典通常适合按键查找值 但按值查找键相当慢 for k v in dictionary items if v myValue return k 是否已经有一个数据结构可以同时实现 key gt value 和 k
  • d3 图缺少数组中的第一项

    我真的很挣扎 我正在使用 d3 库在 javascript 中创建点图 我想过滤实际绘制的点 以便稍后我可以将文本字段添加到数据集中名为 突出显示 的列中指定的其中一些字段 就像测试一样 我只绘制标记为 是 的圆圈 但最终会绘制所有圆圈 我
  • 为什么不能获取 nullptr 的地址?

    在C 11标准中 我不明白为什么要取地址nullptr是不允许的 而一个is允许使用自己的地址std nullptr t实例 除了这个事实之外nullptr是一个保留关键字 这个决定有什么指定的理由吗 只是因为它让我感到有趣 我尝试使用以下
  • 使用 PRAW 在 Python 中从 Reddit API 解码 JSON

    我在 Python GTK 应用程序中使用 PRAW for Reddit API 我已经成功地使用了 API 但我似乎无法解码 JSON 以供使用 应该知道 我是Python和GTK应用程序的初学者 Mode Python coding
  • 网格中最大的产品

    我被这个问题困扰了 我确实认为我已经找到了正确的解决方案 但是当将其提交到网站时 它不接受 我尝试通过打印所有可能的组合来调试它 它们都完成了 水平 垂直和对角线 数组也被正确填充 我后来打印出来检查了一下 你知道问题可能出在哪里吗 Que
  • 安装aws-sdk后出错

    我正在尝试让回形针与 S3 一起使用 但我的视图抛出错误 cannot load such file aws sdk You may need to install the aws sdk gem 我的 Rails 配置如下 Gemfile
  • (MVC 3 Razor) - 循环遍历 3 列 div 的更简单方法

    目前我在 CSHTML 中使用以下代码 int i 0 foreach var item in Model Traders if i 3 0 if i 1 div class row div class four column div cl
  • 获取 Firefox SDK main.js 中某个文件的内容

    所以我正在开发一个 Firefox 插件 它可以向任何网页的 DOM 添加一些 HTML 这里的想法是我使用一个名为template html作为模板 位于dataaddon 文件夹内的文件夹 接下来 我想使用该内容template htm
  • 如何像Notes App一样设置UITextView内容插入

    我正在开发一个应用程序 我需要在 iPhone 中提供类似 Notes App 的功能 如第一个屏幕截图所示 最初 笔记在内容开始之前留下一个选项卡 我也想做同样的事情 当我设置时左侧内容插图 UITextView 到 25 时 它显示如屏
  • 是否可以使“type”的输出返回不同的类?

    所以免责声明 这个问题 https stackoverflow com questions 56879033 how do i override type method in python object noredirect 1 comme