混淆Python集两次添加相同的对象

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了混淆Python集两次添加相同的对象相关的知识,希望对你有一定的参考价值。

如果我将一个整数添加到Python集对象两次,Python只会添加一次。

a = set()
a.add(5)
a.add(5)
print(a)
>> {5}

但是,在我的应用程序中,我正在尝试将协同程序添加到集合中,因为我无法找到更好的方法来跟踪event_loop中已经存在哪些协同程序。我对以下行为感到惊讶:

async def foo(something):
    await asyncio.sleep(1)
    print(something)

a = set()
coro_obj = foo("hi") 
a.add(coro_obj)
coro_obj = foo("hi") 
a.add(coro_obj)
print(a)
{<coroutine object foo at 0x7f36f8c52888>, <coroutine object foo at 0x7f36f8c52360>}

我不太确定我在这里做了什么。我是否正确地认为协程对象是否不可清除,它是否会被添加到集合中?所以它是可以清洗的,对吧?

那么如果它是hashable,为什么我们用相同的方法/参数得到两个不同的哈希?

答案

集合使用哈希来比较对象,因此如果两个对象的__ hash __()方法将返回相同的值,则认为两个对象相等。在您的示例中,它将是这样的:

a = set()
coro_obj = foo("hi") 
a.add(coro_obj.__hash__())
coro_obj = foo("hi") 
a.add(coro_obj.__hash__())
print(a)
{-9223363267847141772, 8769007586508}

正如您可以看到两个对象的哈希值不同,这都取决于内部协程__ hash __方法实现

附加:obj1 .__ eq __(obj2)也应该是True

另一答案

您可以使用字典来存储函数和参数集。

# dict to store functions
foo_dict = {}

# function that adds functions and sets of args to dict
d_add = lambda d, f, args : d[foo].add(args) if f in d else d.update({f: {args}} )

# function that makes a list of coroutine objects from this dict 
d_bake = lambda d:[f(*args) for f, args_list in d.items() for args in args_list]

结果:

d_add(foo_dict, foo, ("hi",))
d_add(foo_dict, foo, ("hi", "bye"))
d_add(foo_dict, foo, ("hi",))
d_add(foo_dict, foo, ("hi",))

print(foo_dict)
#{<function foo at 0x7fefc0be1268>: {('hi',), ('hi', 'bye')}}

print(d_bake(foo_dict))
#[<coroutine object foo at 0x7fefc0f39f68>, <coroutine object foo at 0x7fefc0bec048>]

以上是关于混淆Python集两次添加相同的对象的主要内容,如果未能解决你的问题,请参考以下文章

对话框片段已添加异常未抛出

Python 默认参数混淆

Python:使用jsonpickle无法两次或多次打印同一个对象。

append() 在这个代码片段中是如何工作的?与特定变量混淆[重复]

使用导航控制器创建两次的片段

在导致意外行为的对话框上两次添加相同的 ActiveX 控件