数据隐藏在Python类中

Aam*_*nan 9 python

我知道由双下划线__前缀声明的类的属性可能在类定义之外可见也可能不可见.因为我们仍然可以访问这些属性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)


Cep*_*o93 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
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扩展.