我知道由双下划线__前缀声明的类的属性可能在类定义之外可见也可能不可见.因为我们仍然可以访问这些属性object._className__attrName.
class A:
def __init__(self):
self.a = 1
self.b = 2
----
----
self.z = 26
self.catch = 100
Run Code Online (Sandbox Code Playgroud)
现在为了保护除属性之外的所有属性catch,我必须用双下划线声明它们,这是非常混乱的.有没有办法可以在我的班级定义中说只能self.catch在课外访问?
如果在其他地方回答或之前讨论过,请道歉.
unu*_*tbu 18
是的,可以在闭包中隐藏私有数据 - 至少,如果有private从外部访问的方法make_A,我还没有找到它:
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
Run Code Online (Sandbox Code Playgroud)
注意private不在dir(a)
print('private' in dir(a))
# False
Run Code Online (Sandbox Code Playgroud)
虽然这是可能的,但我认为这不是推荐用Python编程的方法.
以上,private由所有实例共享A.要基于每个实例使用私有数据,请添加self到dict键:
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
Run Code Online (Sandbox Code Playgroud)
虽然接受的答案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
Run Code Online (Sandbox Code Playgroud)
或者按照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
Run Code Online (Sandbox Code Playgroud)
我bevile创建private属性的唯一方法是编写某种CPython扩展.