gpt4 book ai didi

python - 对于私有(private)属性,setattr 和赋值并不等效

转载 作者:太空宇宙 更新时间:2023-11-03 15:59:21 26 4
gpt4 key购买 nike

使用CPython 3.4.3(GCC 5.3.1 20160406(Red Hat 5.3.1-6)),我在使用setattrgetattr时遇到非常奇怪的行为关于私有(private)属性:

class Short:
def __init__(self):
setattr(self, '__myatt', None)
self.__myatt = 42
assert getattr(self, '__myatt') is None
Short()

最后的代码永远不会引发任何 AssertionError,尽管在​​断言语句之前有一些矫揉造作。但是,使用 myattr 而不是 __myatt 的相同代码可以正确引发异常:

class Short:
def __init__(self):
setattr(self, 'myatt', None)
self.myatt = 42
assert getattr(self, 'myatt') is 42
Short()
<小时/>

以下是两种情况(私有(private)与公共(public))的比较,带有注释和断言,显示 3 种访问方式中的 2 种没有返回预期值:

class Private:

def __init__(self):
print('############### PRIVATE ###############')
print('Assign __fa with None using setattr.')
setattr(self, '__fa', None)


print("Set __fa to 42 using regular affectation.")
new_value = 42
self.__fa = new_value

print("\nPrint the new values. Expected to be all 42:")
print("new value:", new_value)
print("self.__fa:", self.__fa)
print("getattr(self, '__fa'):", getattr(self, '__fa'))
print("self.__dict__['__fa']:", self.__dict__['__fa'])

assert self.__dict__['__fa'] is None # this is unexpected
assert getattr(self, '__fa') is None # this is unexpected

print("\nNow modify __fa using setattr")
# Maintenant, on utilise la notation «équivalente» (d'après la doc)
setattr(self, '__fa', new_value)

print("\nPrint the new values. Expected to be all 42:")
# et tout va bien !
# WTF !
print("new value:", new_value)
print("self.__fa:", self.__fa)
print("getattr(self, '__fa'):", getattr(self, '__fa'))
print("self.__dict__['__fa']:", self.__dict__['__fa'])

assert self.__fa is not None


class Public:

def __init__(self):
print('\n############### PUBLIC ###############')
print('Assign fa with None using setattr.')
setattr(self, 'fa', None)


print("Set fa to 42 using regular affectation.")
new_value = 42
self.fa = new_value

print("\nPrint the new values. Expected to be all 42:")
print("new value:", new_value)
print("self.fa:", self.fa)
print("getattr(self, 'fa'):", getattr(self, 'fa'))
print("self.__dict__['fa']:", self.__dict__['fa'])

assert self.__dict__['fa'] is not None # this is expected
assert getattr(self, 'fa') is not None # this is expected


Private()
Public()

这种行为是预期的吗?为什么以及它的起源是什么?

最佳答案

这是预期的。在编译时执行的名称修饰不会影响字符串文字,因此您应该在 getattrsetattrhasattr 中显式提供修饰的名称:

class Short:
def __init__(self):
self.__myatt = 42
# print(getattr(self, '__myatt')) # Fails with a NameError
print(getattr(self, '_{0.__qualname__}__myatt'.format(type(self)))) # Succeeds

现在打印出42。同样,要设置 setattr 和检查 hasattr,您需要提供损坏的名称。

这是在相关的 bug report 中提出的对于 hasattr 来说,是的,它被明确声明为预期行为。

关于python - 对于私有(private)属性,setattr 和赋值并不等效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40495294/

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