【问题标题】:How to change class representation when the class is a dictionary's key?当类是字典的键时如何更改类表示?
【发布时间】:2021-08-20 17:06:34
【问题描述】:

考虑以下代码:

class DummyClass:
    
    def __init__(self, name):
        self.name = name

obj_1 = DummyClass("name_1")
obj_2 = DummyClass("name_2")

my_dict = {
    obj_1: "value_1",
    obj_2: "value_2"
}

print(my_dict)

输出

{<__main__.DummyClass object at 0x7f8f6493a0b8>: 'value_1', <__main__.DummyClass object at 0x7f8f649869e8>: 'value_2'}

此代码创建了一个字典 my_dict,其中包含 DummyClass 的实例作为键。

我想知道是否有可以在DummyClass 中覆盖的魔术函数(例如__something__),以便上面的代码产生以下输出:

{'name_1': 'value_1', 'name_2': 'value_2'}

其中name_1name_2 都是字符串,即DummyClass 实例的name 属性。

我不想更改可视化或打印,我想实际更改内存中的键。

【问题讨论】:

  • 不知道为什么有人会反对。如果我不知道我正在寻找的函数的名称,我就找不到答案。
  • 我可能错过了这里的重点,但在我看来 my_dict = {obj_1.name: "value_1", obj_2.name: "value_2" } 会做你想做的事。
  • 在这种特殊情况下,是的。但是有没有一种通用的模型方法可以让我写my_dict = {obj_1: "value_1", obj_2: "value_2" } 并得到与my_dict = {obj_1.name: "value_1", obj_2.name: "value_2" } 相同的结果?看来我需要覆盖__repr__
  • 在我看来,您正在寻找 Delphi 所谓的 默认属性:它是裸类实例名称的 RH 值,您当然必须声明,否则是什么让self.name 优先于其他属性?但是 Python 没有我所知道的使一个属性比其他属性更重要的机制。我认为最好解释一下为什么您认为需要这种机制。
  • 那么不,没有办法做到这一点。对象本身就是键,对于“当它被用作字典键时要用作键的实际值”没有神奇的方法。如上所述,您应该提供上下文,这将解决的问题。

标签: python


【解决方案1】:

__repr__ 方法用于生成dict 用于显示键的字符串。在dict 创建或更新期间没有修改密钥的机制,也没有dict 特定的方式来修改密钥的显示方式。

默认情况下,DummyClassobject 继承其__repr__ 方法,这就是产生&lt;...&gt; 字符串的原因。覆盖 __repr__ 以返回从 name 属性构建的字符串。

class DummyClass:

    def __init__(self, name):
        self.name = name

    def __repr__(self):
        return f"'{self.name}'"

有人向create a key-transforming dictionary 提出过提案,但被拒绝了。它本来可以让你写类似的东西

d = TransformDict(lambda x: x.name)
d[obj_1] = ...
d[obj_2] = ...

由此产生的dict 的行为就像'name1''name2' 是密钥一样(同时仍允许访问原始密钥obj_1obj_2,如有必要)。

【讨论】:

  • 这将使打印的表示正确,但正如问题 cmets 所指出的,这不会使实际的字典键成为字符串;它只是让它看起来像print下的一个。
  • 我没说清楚。 dict 的实例要么是关键,要么不是。 dict 没有提供在创建 dict 期间修改密钥的方法(尽管请参阅被拒绝的 PEP-455,它提出了这种机制),并且没有提供 dict 特定的钩子来了解密钥的方式显示。
  • 是的,我根本没有批评你的回答。我只是不希望 OP 认为这是他们问题的完全解决方案,因为他们在 cmets 中澄清了手头的问题。如所写,这是对所提出问题的回答。我不希望 OP 错过 cmets 中的其他上下文。
  • 我试图以一种解决原始意图的方式来澄清答案。
  • 谢谢。所以,总而言之,如果__repr__ 函数返回一个字符串,那么使用__repr__ 会生成字符串吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多