2012-01-26 16 views
8

में डेटा छिपाने के बारे में मुझे पता है कि कक्षा के गुण जो डबल अंडरस्कोर __ उपसर्ग द्वारा घोषित किए गए हैं, कक्षा परिभाषा के बाहर दिखाई दे सकते हैं या नहीं भी हो सकते हैं। चूंकि हम अभी भी उन गुणों को object._className__attrName तक एक्सेस कर सकते हैं।पायथन कक्षा

class A: 
    def __init__(self): 
     self.a = 1 
     self.b = 2 
     ---- 
     ---- 
     self.z = 26 
     self.catch = 100 

अब विशेषता catch को छोड़कर सभी विशेषताओं की रक्षा के लिए, मैं उन्हें डबल अंडरस्कोर जो काफी गंदा है साथ घोषित करने के लिए है। क्या मेरी कक्षा परिभाषा में कोई तरीका है कि कक्षा के बाहर केवल self.catch तक पहुंचा जा सकता है?

क्षमा करें अगर इसका उत्तर कहीं और या पहले चर्चा की गई है।

+1

नहीं। हालांकि, जब तक कि आप वास्तव में पागल नहीं हो जाते हैं, तथ्य यह है कि कोई व्यक्ति * object._className__attrName 'का उपयोग करके ऑब्जेक्ट तक पहुंच सकता है, यह एक बड़ा सौदा नहीं है। आप वास्तव में लोगों को उन चरों तक पहुंचने से रोकना चाहते हैं जिन्हें वे आपके कोड का उपयोग करते समय नहीं करना चाहिए। Obfuscation उस लक्ष्य को प्राप्त करता है। – Chris

+2

संभावित डुप्लिकेट [क्या पाइथन में कक्षाओं में 'निजी' चर है?] (Http://stackoverflow.com/questions/1641219/does-python-have-private-variables-in-classes) –

+0

@ BjörnPollex, यह isn ' वह क्या पूछ रहा है। वह एक स्पष्ट "सार्वजनिक" ऑपरेटर की आवश्यकता चाहता है, विपरीत नहीं। –

उत्तर

16

हाँ, यह एक बंद में निजी डेटा को छिपाने के लिए संभव है - कम से कम, अगर वहाँ बाहर make_A से 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 

हालांकि यह संभव है में, मुझे नहीं लगता कि इस सिफ़ारिश लायक रास्ता अजगर में कार्यक्रम है।


ऊपर, privateA के सभी उदाहरणों द्वारा साझा किया जाता। एक प्रति उदाहरण के आधार पर निजी डेटा का उपयोग करने के लिए, dict कुंजी को 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 
+2

+1। – 9000

+0

*** बंद करने के लिए अंगूठे ** **। यह ब्याज का हो सकता है: [गुप्त चर I i Python] (http://www.jotflow.com/jot/Secret-Variables-In-Python/5)। यह जावा में निजी चर के साथ पाइथन में छिपे हुए कार्यात्मक डेटा की तुलना करता है। –

1

नहीं, क्योंकि यह नाम का हिस्सा है, आप ऐसा नहीं कर सकते हैं।

ठीक है, वास्तव में आप गेटर्स/सेटर्स के साथ हैकिंग के माध्यम से कर सकते हैं, लेकिन आपको आम तौर पर नहीं करना चाहिए।

1

क्यों आप विशेषताओं की रक्षा के लिए चाहते हो सकता है?

यदि आप अनजान ओवरराइटिंग से विशेषताओं की रक्षा करना चाहते हैं, तो डबल अंडरस्कोर का उपयोग करें, और संभवतः, केवल उपयोग करने योग्य गुणों को आसान बनाने के लिए उपयोग करें। लेकिन अधिकांश समय, you aint't gonna need it। बस अपने आप को एक पक्ष बनाओ और गुणों को खोलें, इससे डिबगिंग बहुत आसान हो जाती है।

आप तीसरे पक्ष द्वारा छेड़छाड़ से अपने वस्तु की रक्षा के लिए चाहते हैं, आप, __getattr__ और __setattr__ साथ खेल सकते हैं, लेकिन शायद आप पारित नहीं किया जाना चाहिए करने के लिए किसी अविश्वसनीय ग्राहक बिल्कुल सुरक्षित डेटा के साथ वस्तुओं के बजाय facade pattern का उपयोग करें और अपने क़ीमती सामान को छिपाने अधिक अपर्याप्त। आप भी अपने वास्तुकला पर पुनर्विचार करना चाह सकते हैं।

+1

* आप गुणों की रक्षा क्यों कर सकते हैं? * मैं आपको encapsulation पर विकी प्रविष्टि के लिए इंगित कर सकता हूं, लेकिन मैं आपको एक व्यावहारिक उदाहरण दूंगा। मान लें कि आपके पास एक बड़ा और जटिल पायथन एप्लिकेशन है जिसमें आपके पास विशेषता 'नाम' के साथ कई कक्षाएं हैं। एक बग पाया जाता है जिसमें कक्षा प्रशासक का नाम गलत तरीके से ओवरराइड किया जा रहा है। यदि आपने सुझाव दिया है कि आपने नाम विशेषता खोला है, तो आपको कोड की अपमानजनक रेखा कैसे मिलेगी? यदि आपने विशेषता और उपयोग किए गए एक्सेसर्स को छुपाया है, तो आप गेटटर पर ब्रेकपॉइंट डाल सकते हैं और अपराधी को तेजी से ढूंढ सकते हैं। – dar512

+0

@ dar512: यदि आपकी कक्षा सार्वजनिक इंटरफ़ेस का हिस्सा है, और ग्राहक विशेषता के साथ छेड़छाड़ कर सकते हैं, हर तरह से उन्हें एक्सेसर्स द्वारा संरक्षित करें! हालांकि, सार्वजनिक कक्षाओं की संख्या एक सामान्य अनुप्रयोग में सीमित है। इसके अलावा, अपरिवर्तनीय डेटा का उपयोग करने के कई फायदे हैं; मैं बुलेट प्रूफ तरीके से डेटा का प्रतिनिधित्व करने के लिए अक्सर 'नामांकित' के उप-वर्गों का उपयोग करता हूं। – 9000

+0

एक प्रोग्रामर के रूप में, अगर मैंने शॉटगन के साथ अपने पैर को शूट करना चुना, तो हो। आप चीजों को छुपाकर अपने कोड को ठीक/बदलने की मेरी क्षमता को सीमित कर रहे हैं। 'संरक्षित' और 'निजी' कीवर्ड केवल विरोधी पैटर्न हैं। कृपया इस धारणा को त्याग दें कि आप किसी अन्य प्रोग्रामर से चीजों को छिपाने के पक्ष में किसी के पक्ष में हैं। यदि आप ऐसा कुछ करना चाहते हैं, तो '_variable'' का उपयोग करें और 'variable' getter property और कोई सेटटर प्रदान न करें। यदि मैं चाहूं तो मैं अभी भी '_variable' को मैन्युअल रूप से संशोधित कर सकता हूं। लेकिन अन्य प्रोग्रामर से अपने आंतरिक को खराब करने के लिए भाषा हैक का उपयोग न करें। – Rebs

3

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 विशेषताएं बना लिए एक ही रास्ता bevile है कुछ कश्मीर में लिखने के लिए CPython विस्तार का इंडस्ट्री।

+0

इसके लिए धन्यवाद –

संबंधित मुद्दे