我有以下代码
class AccountBannk:
def __init__(self,balance,holder):
self.__AccountHolder=holder
def Display_AccountHolder(self):
print "account holder is" , self.__AccountHolder
myaccount=AccountBannk(100000,"mehdiebagvand")
#print myaccount.__AccountHolder #is a error
myaccount.__AccountHolder="ali"
print myaccount.__AccountHolder #print ali
在此代码中AccountHolder是私有属性
在python中我们无法直接编辑或打印它
如果我们尝试下面的代码,python发布错误
print myaccount.__AccountHolder
但我的问题是 1 - 为什么python不会在下面的代码中发布错误
myaccount.__AccountHolder="ali"
2-I在end_line中打印myaccount .__ AccountHolder但是python没有释放错误
并将myaccount .__ AccountHolder的值更改为'ali'
答案 0 :(得分:3)
这不是错误。当你在你的类中定义你的第一个__AccountHolder
时,Python会破坏变量的名称(很难猜测,但不是真正的私有,请参阅PEP-8)。当你附加第二个__AccountHolder
时,你正在创建一个新的变量(带有一个新的变形名称)。试试看:
print myaccount.__AccountHolder
print myaccount.Display_AccountHolder()
或添加
print dir(myaccount)
在你做第二次任务之前和之后:
>>> myaccount=AccountBannk(100000,"mehdiebagvand")
>>> dir(myaccount)
['Display_AccountHolder', '_AccountBannk__AccountHolder', '__doc__', '__init__', '__module__']
>>> myaccount.__AccountHolder="ali"
>>> dir(myaccount)
['Display_AccountHolder', '_AccountBannk__AccountHolder', '__AccountHolder', '__doc__', '__init__', '__module__']
至于名称修改,这里来自文档:
__ double_leading_underscore:在命名一个class属性时,调用name mangling(在类FooBar中,__ boo变成 FooBar _boo;参见 下文)。
答案 1 :(得分:1)
这是我认为使用__names
作为“私有变量”比使用{em>方式更麻烦的众多原因之一。 __names
的预期用例更多是允许层次结构中的类使用nice(ish)名称,而不必担心层次结构中其他类正在使用哪些名称,而不是创建“私有”属性。
对于“私有”属性,只需使用单个前导下划线(如_name
)。这表明您的意图是某些名称是私有实现细节,而其他名称是该类的公共接口的一部分。它不会阻止任何使用“私有”名称的人,但__names
也不会,因为修改非常容易进行逆向工程。所有这些技巧都可以防止任何人意外使用你想要私密的名字;他们可以做狡猾的事情,但他们必须知道他们正在做这件事。这是Python中可以获得的全部内容;因为一切都是动态的,任何人都可以随时做任何事情。
因此,对于您的私人内部名称,__name
和_name
之间的主要区别在于,只要您开始想要使用__name
或{{getattr
,hasattr
就会成为主要的PITA 1}}(即使在正确的类中),动态附加方法,或者具有 想要共享“私有”名称的子类。具有单个下划线的_name
在任何这些区域都没有问题,在记录您的意图方面同样有效,并且在防止在类定义之外使用私有名称方面同样有效(即几乎完全无效)。