为什么 python 的 getattr(obj,'method') 和 obj.method 给出不同的结果?括号如何影响?

Why python's getattr(obj,'method') and obj.method give different results? How do brackets affect?

我的程序只计算 sha256 文件哈希,我决定扩展可能的算法数量。所以我开始使用 getattr() 而不是直接调用。并且哈希值发生了变化。

我花了一段时间才弄清楚问题出在哪里,这里是一个简单的字符串示例(不同之处在于 ()):

>>> import hashlib
>>> text = 'this is nonsence'.encode()

# unique original
>>> hash1 = hashlib.sha256()
>>> hash1.update(text)
>>> print(hash1.hexdigest())
ea85e601f8e91dbdeeb46b507ff108152575c816089c2d0489313b42461aa502

# pathetic parody
>>> hash2 = getattr(hashlib,'sha256')
>>> hash2().update(text)
>>> print(hash2().hexdigest())
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855

# solution
>>> hash3 = getattr(hashlib,'sha256')()
>>> hash3.update(text)
>>> print(hash3.hexdigest())
ea85e601f8e91dbdeeb46b507ff108152575c816089c2d0489313b42461aa502

谁能解释一下为什么 hash1 不等于 hash2() 而等于 hash3? 我错过了什么吗?因为对我来说他们看起来一样:

>>> print(hash1)
<sha256 HASH object @ 0x0000027D76700F50>
>>> print(hash2())
<sha256 HASH object @ 0x0000027D76FD7470>
>>> print(hash3)
<sha256 HASH object @ 0x0000027D76D92BF0>

>>> print(type(hash1))
<class '_hashlib.HASH'>
>>>print(type(hash2()))
<class '_hashlib.HASH'>
>>>print(type(hash3))
<class '_hashlib.HASH'>

事实上,getattr(obj, 'method')obj.method 给出了相同的结果,但是在 #2 的情况下,你用错了。

当您调用函数 hashlib.sha256 时,它 returns 一个新的 HASH 对象,这就是您在案例 #1 和 #3 中处理的对象。然而,在 #2 的情况下,hash2 是函数 hashlib.sha256,而不是 HASH 对象,并且在您稍后调用它时不会改变,意思是:

  • 当您执行 hash2().update(text) 时,结果将被丢弃。
  • 当您执行 hash2().hexdigest() 时,结果与 hashlib.sha256().hexdigest() 相同,即空哈希。

为了比较,案例 #2 实际上与此相同:

>>> list().append(0)  # Create new list object and append 0
>>> list()  # Create new list object
[]