I know that the attributes of class which are declared by double underscore __
prefix may or may not visible outside the class definition. As we can still access those attributes by object._className__attrName
.
class A:
def __init__(self):
self.a = 1
self.b = 2
----
----
self.z = 26
self.catch = 100
Now to protect all attributes except the attribute catch
, I have to declare them with double underscore which is quite messy. Is there a way I can say in my class definition that only self.catch
can be accessed outside the class?
Apologies if this is answered somewhere else or discussed earlier.
Yes, it is possible to hide private data in a closure -- at least, if there is a way to access private
from outside make_A
, I haven't found it:
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
Notice that private
is not in dir(a)
print('private' in dir(a))
# False
Although this is possible, I do not think this is recommendable way to program in Python.
Above, private
is shared by all instances of A
. To use private data on a per-instance basis, add self
to the dict key:
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
While the accepted answer by unutbu
looks like a good idea to hide data, the private
dictionary still accessible using __closure__
(this attribute cannot be removed):
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
Or following the link provided by Sumukh Barve
in the comments:
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
I bevile the only way to create private
attributes is to write some kind of CPython
extension.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With