Python类中的数据隐藏
我知道,在类里面用双下划线 __
开头的属性,可能在类的外面看不到,也可能能看到。不过,我们还是可以通过 object._className__attrName
来访问这些属性。
class A:
def __init__(self):
self.a = 1
self.b = 2
----
----
self.z = 26
self.catch = 100
现在,为了保护所有属性,除了 catch
这个属性,我得把它们都用双下划线声明,这样做有点麻烦。有没有办法可以在我的类定义里说明,只有 self.catch
这个属性可以在类外被访问呢?
如果这个问题在别的地方已经回答过或者讨论过,我表示歉意。
4 个回答
1
不行,因为这是名字的一部分,你不能这样做。
其实你可以通过一些技巧,比如使用获取器和设置器来实现,但一般来说不建议这么做。
5
虽然unutbu
给出的答案看起来是个不错的隐藏数据的方法,但实际上,private
字典还是可以通过__closure__
这个属性访问到(这个属性是无法删除的):
def make_A():
private = {}
class A:
def __init__(self):
self.catch = 100
private[self,'a'] = 1 # you can modify the private data
private[self,'b'] = 2
private[self,'z'] = 26
def foo(self):
print(private[self,'a']) # you can access the private data
return A
A = make_A()
a = A()
a.foo() # 1
a.foo.__closure__[0].cell_contents[(a, 'a')] = 42
a.foo() # 42
或者可以查看Sumukh Barve
在评论中提供的链接:
def createBankAccount():
private = {'balance': 0.0}
def incr(delta):
private['balance'] += delta;
account = {
'deposit': lambda amount: incr(amount),
'withdraw': lambda amount: incr(-amount),
'transferTo': lambda otherAccount, amount: (
account['withdraw'](amount),
otherAccount['deposit'](amount)
),
'transferFrom': lambda otherAccount, amount: (
otherAccount['transferTo'](account, amount)
),
'getBalance': lambda : private['balance']
}
return account;
account = createBankAccount()
print(account['getBalance']())
account['getBalance'].__closure__[0].cell_contents['balance'] = 1000**1000
print(account['getBalance']()) # I can buy a couple of nations
我认为创建private
属性的唯一方法是写一些类型的CPython
扩展。
20
是的,可以在一个闭包中隐藏私有数据——至少,如果有办法从外部访问private
,我还没找到:
def make_A():
private = {
'a' : 1,
'b' : 2,
'z' : 26,
}
class A:
def __init__(self):
self.catch = 100
private['a'] = 2 # you can modify the private data
def foo(self):
print(private['a']) # you can access the private data
return A
A = make_A()
a=A()
a.foo()
# 2
注意,private
不在dir(a)
的列表中。
print('private' in dir(a))
# False
虽然这样做是可能的,但我认为这不是在Python中推荐的编程方式。
上面提到的private
是所有A
的实例共享的。如果想要让每个实例都有自己的私有数据,可以在字典的键中加上self
:
def make_A():
private = {}
class A:
def __init__(self):
self.catch = 100
private[self,'a'] = 1 # you can modify the private data
private[self,'b'] = 2
private[self,'z'] = 26
def foo(self):
print(private[self,'a']) # you can access the private data
return A