在 Python 中自定义不可变类型
Customizing immutable types in Python
假设我想要一个包含 2 个元素的自定义 frozenset
,它可以迭代、散列、比较,并具有其他各种不错的操作作为 frozenset,但打印方式不同。
>>> p = edge(5, 7)
>>> p == edge(7, 5)
True
>>> p
edge(5, 7)
我可以继承,也可以委派,但在这两种情况下我都得不到我想要的。
如果按字面继承,好像没办法写__init__
,因为我的parent是不可变的。我可以只写:
class edge:
def __new__(cls, a, b):
return frozenset({a, b})
但后来我得到了一个合适的 frozenset 并且无法自定义它的 __repr__
,这正是我想要做的。我无法让 super()
以任何好的方式在这里工作。
如果我委派,我可以覆盖 __getattr__
或 __getattribute__
,但是其中的 none 在例如 __iter__
被寻求时确实有效。我想这里的特殊方法太特殊了。我目前唯一的解决方案是手动委托我能想到的每一个特殊方法,但肯定有更好的方法。有什么想法吗?
愚蠢的我。现在可以了。如果有人想知道怎么做,这里是:
class pair(frozenset):
def __new__(cls, a, b):
return super().__new__(cls, {a, b})
def __repr__(self):
a, b = sorted(self)
return "{} & {}".format(a, b)
错误是我调用 super().__new__({a, b})
时认为它会以与 self
相同的方式幻化我的 cls
,当不带参数调用时。当然,__new__
是隐式类方法并没有帮助。 :-)
假设我想要一个包含 2 个元素的自定义 frozenset
,它可以迭代、散列、比较,并具有其他各种不错的操作作为 frozenset,但打印方式不同。
>>> p = edge(5, 7)
>>> p == edge(7, 5)
True
>>> p
edge(5, 7)
我可以继承,也可以委派,但在这两种情况下我都得不到我想要的。
如果按字面继承,好像没办法写__init__
,因为我的parent是不可变的。我可以只写:
class edge:
def __new__(cls, a, b):
return frozenset({a, b})
但后来我得到了一个合适的 frozenset 并且无法自定义它的 __repr__
,这正是我想要做的。我无法让 super()
以任何好的方式在这里工作。
如果我委派,我可以覆盖 __getattr__
或 __getattribute__
,但是其中的 none 在例如 __iter__
被寻求时确实有效。我想这里的特殊方法太特殊了。我目前唯一的解决方案是手动委托我能想到的每一个特殊方法,但肯定有更好的方法。有什么想法吗?
愚蠢的我。现在可以了。如果有人想知道怎么做,这里是:
class pair(frozenset):
def __new__(cls, a, b):
return super().__new__(cls, {a, b})
def __repr__(self):
a, b = sorted(self)
return "{} & {}".format(a, b)
错误是我调用 super().__new__({a, b})
时认为它会以与 self
相同的方式幻化我的 cls
,当不带参数调用时。当然,__new__
是隐式类方法并没有帮助。 :-)