python - 一个新的类方法的__self__ 仍然引用以前的类?
问题描述
我想做的事情看起来很奇怪,简而言之,我正在尝试构建一个新类并从另一个类复制实例/静态/类方法而不进行继承(即,我只想要一个只有几个方法的类)。当我在网上查找时,似乎人们在建议我在插图中所做的(新类),但当我尝试测试它时,新类中声明的类方法似乎仍然指向前一个类(旧班级)。
这就是我所做的:
class OldClass(object):
current_count = 1
def __init__(self):
pass
@classmethod
def method_class(cls):
cls.current_count += 1
def method_normal(self):
return 2
# new class
class NewClass(object):
method_class_copy = OldClass.method_class
method_normal_copy = OldClass.method_normal
检查 __self__ 给出以下结果:
class_self = getattr(NewClass.method_class_copy, '__self__', None)
print(class_self)
它返回:
<class '__main__.OldClass'>
但在实例化后检查实例方法:
instance_self = getattr(NewClass().method_normal_copy, '__self__', None)
print(instance_self)
如您所见,它仍然指的是 OldClass,如果我运行类方法NewClass.method_class_copy()
,OldClass.current_count
它将按照我定义的方式增加它的值。
它返回:
<__main__.NewClass object at 0x000001D8CC1AEA88>
- 如何使用类方法的 __self__ 构造一个(新)类实际上是指 NewClass 而不是 OldClass?
- 为什么实例方法是“自动调整”的?
谢谢
解决方案
这是描述符协议的效果以及如何classmethod
使用它: Aclassmethod
通过在其上查找来绑定到它的类。松散地说,查找some_cls.some_classmethod
返回参数预填充为的cls
some_class
方法。
由于“普通”方法通过在实例上查找来绑定到它们的实例,因此在类上查找它们并没有绑定它们。
>>> class Foo:
... def some_normalmethod(self): ...
... @classmethod
... def some_classmethod(cls): ...
...
>>> Foo.some_classmethod
<bound method Foo.some_classmethod of <class '__main__.Foo'>>
>>> Foo.some_normalmethod
<function __main__.Foo.some_normalmethod(self)>
因此,classmethod
通过从类中获取 a 来“复制”它并不能按预期工作(它已经绑定到类),而“复制”一个普通方法确实有效(它没有绑定到实例)。
为了“复制” a classmethod
,提取其底层函数并从中创建一个新函数classmethod
:
>>> bound_cm = Foo.some_classmethod # bound classmethod
>>> base_cm = bound_cm.__func__ # function underlying classmethod
>>> class Bar:
... some_classmethod = classmethod(base_cm) # new classmethod of same function
...
>>> Bar.some_classmethod
<bound method Foo.some_classmethod of <class '__main__.Bar'>>
请注意,这会创建类方法的“副本”,而不是底层函数。某些元数据,例如 name Foo.some_classmethod
,仍然指向它的来源。
如果需要原始classmethod
对象,绕过描述符协议可以直接访问而不绑定方法。
>>> Foo.__dict__['some_classmethod']
<classmethod at 0x10b6d9d00>
>>> class Qux:
... some_classmethod = Foo.__dict__['some_classmethod']
...
>>> Qux.some_classmethod
<bound method Foo.some_classmethod of <class '__main__.Qux'>>
推荐阅读
- python - 当原始变量更新时,如何设置依赖于另一个变量的变量来更新?
- python - CommandInvokeError:命令引发异常:RuntimeError:在另一个循环正在运行时无法运行事件循环嗅探数据包时
- javascript - 如何修复与获取的数据不同的 Postman 数据
- flask - 有什么方法可以将 Flask 会话存储在本地存储中而不是 cookie 中?
- windows - Apache Cassandra 进程在 Windows 上是如何命名的?
- r - 如何更改R中矩阵中列的顺序
- java - 尝试使用 Java (Android Studio) 从 String 创建 JSONObject
- javascript - 如何在while循环中串联promise
- sql-server - 使用 Docker 连接的 SQL Server 的物理文件夹
- swift - 如何在 Swift 中使用变量编写 SQL Select Query?