gpt4 book ai didi

python - 如何将特殊方法 'Mixin' 应用于 typing.NamedTuple

转载 作者:太空狗 更新时间:2023-10-30 01:05:09 25 4
gpt4 key购买 nike

我喜欢 Python 3.6 中的 typing.NamedTuple。但通常情况下,namedtuple 包含不可散列的属性,我想将其用作 dict 键或 set 成员。如果 namedtuple 类使用对象标识(id() for __eq____hash__)是有意义的,那么添加这些类的方法工作正常。

但是,我现在在我的代码中的几个地方都有这种模式,我想摆脱样板 __eq____hash__ 方法定义。我知道 namedtuple 不是常规类,我一直无法弄清楚如何让它工作。

这是我尝试过的:

from typing import NamedTuple

class ObjectIdentityMixin:
def __eq__(self, other):
return self is other

def __hash__(self):
return id(self)

class TestMixinFirst(ObjectIdentityMixin, NamedTuple):
a: int

print(TestMixinFirst(1) == TestMixinFirst(1)) # Prints True, so not using my __eq__

class TestMixinSecond(NamedTuple, ObjectIdentityMixin):
b: int

print(TestMixinSecond(2) == TestMixinSecond(2)) # Prints True as well

class ObjectIdentityNamedTuple(NamedTuple):
def __eq__(self, other):
return self is other

def __hash__(self):
return id(self)

class TestSuperclass(ObjectIdentityNamedTuple):
c: int

TestSuperclass(3)
"""
Traceback (most recent call last):
File "test.py", line 30, in <module>
TestSuperclass(3)
TypeError: __new__() takes 1 positional argument but 2 were given
"""

有没有一种方法我不必在每个需要“对象标识”的 NamedTuple 中重复这些方法?

最佳答案

NamedTuple 类语法的神奇来源是它的 metaclass NamedTupleMetabehind the scene , NamedTupleMeta.__new__ 为您创建一个新类,而不是典型的类,而是一个由 collections.namedtuple() 创建的类。

问题是,当NamedTupleMeta创建新的类对象时,它忽略了基类,你可以检查TestMixinFirst的MRO,没有ObjectIdentityMixin:

>>> print(TestMixinFirst.mro())
[<class '__main__.TestMixinFirst'>, <class 'tuple'>, <class 'object'>]

你必须扩展 NamedTupleMeta 来处理基类:

import typing


class NamedTupleMetaEx(typing.NamedTupleMeta):

def __new__(cls, typename, bases, ns):
cls_obj = super().__new__(cls, typename+'_nm_base', bases, ns)
bases = bases + (cls_obj,)
return type(typename, bases, {})


class TestMixin(ObjectIdentityMixin, metaclass=NamedTupleMetaEx):
a: int
b: int = 10


t1 = TestMixin(1, 2)
t2 = TestMixin(1, 2)
t3 = TestMixin(1)

assert hash(t1) != hash(t2)
assert not (t1 == t2)
assert t3.b == 10

关于python - 如何将特殊方法 'Mixin' 应用于 typing.NamedTuple,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47339137/

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