gpt4 book ai didi

python - 如何创建一个 Python 类,该类是另一个类的子类,但未通过 issubclass 和/或 isinstance 测试?

转载 作者:行者123 更新时间:2023-11-28 21:32:23 24 4
gpt4 key购买 nike

我知道这可能是个糟糕的设计,但我遇到过这样一种情况,我需要即时创建类 Base 的子类 Derived ,并使 Derived 的实例无法通过 issubclass(Derived, Base)isinstance(derived_obj, Base) 检查(即返回 False )。

我尝试了很多方法,但都没有成功:

  • Derived ( https://stackoverflow.com/a/42958013/4909228 ) 中创建名为 __class__ 的属性。这只能用于使检查返回 True
  • 覆盖 Base__instancecheck____subclasscheck__ 方法。这是行不通的,因为 CPython 仅在常规检查返回 False 时调用这些方法。
  • __init__ 期间分配 __class__ 属性。这在 Python 3.6+ 中不再被允许。
  • 制作Derived 子类object 并将其所有属性和方法(包括特殊方法)分配给Base。这不起作用,因为某些方法(例如 __init__)不能在不是 Base 的子类的实例上调用。

这可以用 Python 完成吗?该方法可以是特定于解释器的(代码仅在 CPython 中运行),并且只需要针对 Python 版本 3.6+。


为了说明此要求的潜在用途,请考虑以下功能:

def map_structure(fn, obj):
if isinstance(obj, list):
return [map_structure(fn, x) for x in obj]
if isinstance(obj, dict):
return {k: map_structure(fn, v) for k, v in obj.items()}
# check whether `obj` is some other collection type
...
# `obj` must be a singleton object, apply `fn` on it
return fn(obj)

此方法将 map 概括为适用于任意嵌套结构。但是,有些情况下我们不想遍历某个嵌套结构,例如:

# `struct` is user-provided structure, we create a list for each element
struct_list = map_structure(lambda x: [x], struct)
# somehow add stuff into the lists
...
# now we want to know how many elements are in each list, so we want to
# prevent `map_structure` from traversing the inner-most lists
struct_len = map_structure(len, struct_list)

如果上述功能可以实现,那么上面可以改成:

pseudo_list = create_fake_subclass(list)
struct_list = map_structure(lambda x: pseudo_list([x]), struct)
# ... and the rest of code should work

最佳答案

Overriding the __instancecheck__ and __subclasscheck__ methods of Base. This doesn't work because CPython only calls these methods when conventional checks return False.

这种说法是一种误解。这些 Hook 将在 元类 上定义,而不是在基类 ( docs ) 上定义。

>>> class Meta(type): 
... def __instancecheck__(self, instance):
... print("instancecheck", self, instance)
... return False
... def __subclasscheck__(self, subclass):
... print("subclasscheck", self, subclass)
... return False
...
>>> class Base(metaclass=Meta):
... pass
...
>>> class Derived(Base):
... pass
...
>>> obj = Derived()
>>> isinstance(obj, Base)
instancecheck <class '__main__.Base'> <__main__.Derived object at 0xcafef00d>
False
>>> issubclass(Derived, Base)
subclasscheck <class '__main__.Base'> <class '__main__.Derived'>
False

注意 CPython 性能优化,它可以防止在某些特殊情况下调用自定义实例检查 Hook (有关详细信息,请参阅 here)。特别是,由于 CPython fast path,您可能不会对 isinstance(obj, Derived) 的返回值进行强武装。当有完全匹配时。

最后一点,我同意评论者的意见,即这听起来不是一个很有前途的设计。在这种情况下,您似乎应该考虑使用组合而不是继承。

关于python - 如何创建一个 Python 类,该类是另一个类的子类,但未通过 issubclass 和/或 isinstance 测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56658569/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com