अजगर में निजी मॉड्यूल कार्यों को परिभाषित करना


238

Http://www.faqs.org/docs/diveintopython/fileinfo_pStreet.html के अनुसार :

अधिकांश भाषाओं की तरह, पायथन में निजी तत्वों की अवधारणा है:

  • निजी कार्य, जिन्हें उनके मॉड्यूल के बाहर से नहीं बुलाया जा सकता है

हालाँकि, अगर मैं दो फाइलों को परिभाषित करता हूं:

#a.py
__num=1

तथा:

#b.py
import a
print a.__num

जब मैं b.pyइसे चलाता हूं तो 1कोई अपवाद दिए बिना प्रिंट करता है। क्या डायविंटोपथियन गलत है, या मुझे कुछ गलत समझ में आया? और क्या मॉड्यूल के कार्य को निजी के रूप में परिभाषित करने का कोई तरीका है?


ऐसा नहीं है कि डाइविंटोपथियन गलत है, लेकिन उनके उदाहरण में: >>> import fileinfo >>> m = fileinfo.MP3FileInfo() >>> m.__parse("/music/_singles/kairo.mp3") 1 Traceback (innermost last): File "<interactive input>", line 1, in ? AttributeError: 'MP3FileInfo' instance has no attribute '__parse' fileinfo.MP3FileInfo () कक्षा का एक उदाहरण है। जब आप डबल अंडरस्कोर का उपयोग करते हैं तो यह अपवाद देता है। जबकि आपके मामले में, आपने एक वर्ग नहीं बनाया, आपने सिर्फ एक मॉड्यूल बनाया। इन्हें भी देखें: stackoverflow.com/questions/70528/…
होमेरो एस्मेराल्डो

जवाबों:


323

आप नहीं कर सकते हैं - अजगर में, "गोपनीयता" "सहमति दे वयस्कों '" समझौते के स्तर पर निर्भर करता है के लिए मजबूर यह (आप वास्तविक जीवन में कर सकते हैं की तुलना में किसी भी अधिक ;-)। एक एकल प्रमुख अंडरस्कोर साधन आप नहीं कर रहे हैं माना जाता है कि यह "बाहर से" पहुँच के लिए - दो प्रमुख अंडरस्कोर (w / ओ अनुगामी अंडरस्कोर) भी अधिक जबरदस्ती संदेश ले ... लेकिन, अंत में, यह अभी भी सामाजिक पर निर्भर करता है सम्मेलन और आम सहमति: पायथन का आत्मनिरीक्षण पर्याप्त है कि आप अपनी इच्छाओं का सम्मान करने के लिए दुनिया के हर दूसरे प्रोग्रामर को हथकड़ी नहीं लगा सकते ।

((Btw, हालांकि यह एक बारीकी से आयोजित रहस्य है, बहुत सी + + के लिए एक ही धारण करता है: सबसे संकलक के साथ, एक सरल #define private publicलाइन #includeआपकी .hफ़ाइल से पहले है) यह आपकी "गोपनीयता" के हैश बनाने के लिए विली कोडर्स के लिए लेता है ...! -) )


82
C ++ पर आपका नोट गलत है। #Define निजी सार्वजनिक का उपयोग करके आप संकलक को भेजे जाने वाले कोड को बदल रहे हैं, जो कि जहां पर नामकरण होता है।
स्फटिक का

14
इसके अलावा सी ++ मैन्गुलिंग अस्पष्ट है, लेकिन शायद ही गुप्त है। आप सी + + द्वारा निर्मित एक बाइनरी को "आत्मनिरीक्षण" भी कर सकते हैं। ओटी, सॉरी।
प्रो। फल्केन

47
@Rhinoinrepose पर अपडेट के रूप में, यह सिर्फ गलत नहीं है, यह एक पूर्वप्रक्रमक मैक्रो के साथ एक कीवर्ड को फिर से परिभाषित करने के लिए मानक के अनुसार अपरिभाषित व्यवहार है
कोरी क्रेमर

3
@AlexMartelli static void foo()निजी नहीं है क्योंकि यह हो जाता है। यह कम से कम लिंकर के लिए छिपा हुआ है, और फ़ंक्शन को पूरी तरह से इनलाइन करके हटाया जा सकता है।
user877329

3
अगर वे कानूनों को तोड़ते हैं, तो वास्तविक जीवन में लोगों पर मुकदमा चलाया जाता है
लेनो गोंजालेज़

288

क्लास प्राइवेट और मॉड्यूल प्राइवेट के बीच कन्फ्यूजन हो सकता है ।

एक मॉड्यूल निजी एक अंडरस्कोर के साथ शुरू होता है आयात आदेश
के from <module_name> import *रूप का उपयोग करते समय इस तरह के एक तत्व की नकल नहीं की जाती है ; हालाँकि यह import <moudule_name>सिंटैक्स का उपयोग करते समय आयात किया जाता है ( बेन विल्हेम का जवाब देखें )
बस प्रश्न के उदाहरण के .__ संख्या से एक अंडरस्कोर हटा दें और यह उन मॉड्यूल्स में नहीं दिखाया जाएगा जो from a import *सिंटैक्स का उपयोग करके थिंकपैड को आयात करते हैं।

एक वर्ग निजी के साथ शुरू होता है दो अंडरस्कोर (उर्फ दुंदर यानी डी-ouble अंडर स्कोर)
इस तरह के एक चर कि इसके नाम "घायल" classname आदि शामिल करने के लिए है
यह अभी भी घायल नाम के माध्यम से, वर्ग तर्क के बाहर पहुँचा जा सकता है।
यद्यपि नामकरण अनधिकृत पहुंच के खिलाफ हल्के रोकथाम उपकरण के रूप में काम कर सकता है, लेकिन इसका मुख्य उद्देश्य पूर्वजों वर्गों के वर्ग के सदस्यों के साथ संभावित नाम टकराव को रोकना है। एलेक्स मार्टेली के वयस्कों को सहमति देने के लिए मजाकिया लेकिन सटीक संदर्भ देखें क्योंकि वह इन चरों के संबंध में इस्तेमाल किए गए सम्मेलन का वर्णन करता है।

>>> class Foo(object):
...    __bar = 99
...    def PrintBar(self):
...        print(self.__bar)
...
>>> myFoo = Foo()
>>> myFoo.__bar  #direct attempt no go
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Foo' object has no attribute '__bar'
>>> myFoo.PrintBar()  # the class itself of course can access it
99
>>> dir(Foo)    # yet can see it
['PrintBar', '_Foo__bar', '__class__', '__delattr__', '__dict__', '__doc__', '__
format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__',
'__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__
', '__subclasshook__', '__weakref__']
>>> myFoo._Foo__bar  #and get to it by its mangled name !  (but I shouldn't!!!)
99
>>>

खैर, टी.आई.एल. किसी भी कारण से वे मॉड्यूल-स्तर को लागू नहीं करते हैं __private_function, हालांकि? मैं इसमें भाग गया और इसके कारण त्रुटियों में पड़ गया।
सांता

@Terrabits शब्दों के लिए धन्यवाद, लेकिन मैं ख़ुशी से एलेक्स (अच्छी तरह से पीछे!) सभी चीजों पर 'पायथन' के लिए खड़ा हूं। इसके अलावा उनके जवाब आम तौर पर अधिक संक्षिप्त और विनोदी होते हैं, जबकि उच्च स्तर की आधिकारिकता को बनाए रखते हुए एलेक्स को भाषा और समुदाय में व्यापक योगदान दिया जाता है।
mjv

1
@mjv यह एक ऐसी उपयोगी व्याख्या थी! धन्यवाद! मैं थोड़ी देर के लिए इस व्यवहार के बारे में हैरान था। मेरी इच्छा है कि यदि आप क्लास को सीधे निजी रूप से एक्सेस करने का प्रयास करते हैं, तो एक एट्रीब्यूटर के अलावा किसी प्रकार की त्रुटि को फेंकने के लिए पसंद किया गया था; शायद "PrivateAccessError" या कुछ और अधिक स्पष्ट / सहायक होता। (चूंकि यह त्रुटि है कि यह एक विशेषता नहीं है वास्तव में सच नहीं है) हो रही है।
HFBrowning

82

इस सवाल का पूरी तरह से जवाब नहीं दिया गया था, क्योंकि मॉड्यूल गोपनीयता विशुद्ध रूप से पारंपरिक नहीं है, और आयात का उपयोग करने के बाद से मॉड्यूल गोपनीयता को पहचान नहीं सकता है या नहीं करता है, यह इस बात पर निर्भर करता है कि इसका उपयोग कैसे किया जाता है।

यदि आप किसी मॉड्यूल में निजी नामों को परिभाषित करते हैं, तो उन नामों को किसी भी स्क्रिप्ट में आयात किया जाएगा जो वाक्य रचना का उपयोग करता है, 'import मॉड्यूल_name'। इस प्रकार, मान लें कि आपने अपने उदाहरण में सही ढंग से परिभाषित किया था मॉड्यूल प्राइवेट, _num, a Oracle में, जैसे ..

#a.py
_num=1

.. आप इसे मॉड्यूल नाम प्रतीक के साथ b.py में एक्सेस कर पाएंगे:

#b.py
import a
...
foo = a._num # 1

एरेन्डो से केवल गैर-निजीकृत आयात करने के लिए, आपको सिंटैक्स से उपयोग करना होगा :

#b.py
from a import *
...
foo = _num # throws NameError: name '_num' is not defined

स्पष्टता के लिए, हालांकि, मॉड्यूल से नाम आयात करते समय, सभी को '*' के साथ आयात करने के बजाय, स्पष्ट होना बेहतर है।

#b.py
from a import name1 
from a import name2
...

1
आप यह निर्दिष्ट करते हैं कि कौन से कार्य / पुस्तकालय आयात किए गए हैं? में init .py?
FistOfFury

नाम के टकराव का कोई जोखिम नहीं है जब _namesइसे लागू किया जाता है import a- वे a._namesइस शैली का उपयोग करते समय पहुंचते हैं।
जोशिया योडर

@FistOfFury हाँ, आप __init__.pyफ़ाइल में आयात किए गए कार्यों को निर्दिष्ट करते हैं । उस पर कुछ मदद के लिए यहां देखें ।
माइक विलियम्सन

29

पायथन निजी वर्ग के सदस्यों के लिए डबल अंडरस्कोर उपसर्ग के साथ अनुमति देता है । यह तकनीक मॉड्यूल स्तर पर काम नहीं करती है इसलिए मैं सोच रहा हूं कि यह डाइव इन पाइथन में एक गलती है।

यहाँ निजी वर्ग के कार्यों का एक उदाहरण दिया गया है:

class foo():
    def bar(self): pass
    def __bar(self): pass

f = foo()
f.bar()   # this call succeeds
f.__bar() # this call fails

2
मुझे लगता है कि ओपी की मंशा ऐसे कार्यों को लिखना है जो कि बाहर से सुलभ नहीं हैं, उदाहरण के लिए, एक वाणिज्यिक पैकेज। उस संबंध में, यह उत्तर पूर्ण नहीं है। __Bar () फ़ंक्शन अभी भी f._foo__bar () के माध्यम से बाहर से पहुंच योग्य है। इसलिए, डबल-अग्रणी अंडरस्कोर इसे निजी नहीं बनाते हैं।
सेवकप्रेम

24

आप एक आंतरिक फ़ंक्शन जोड़ सकते हैं:

def public(self, args):
   def private(self.root, data):
       if (self.root != None):
          pass #do something with data

ऐसा कुछ अगर आपको वास्तव में गोपनीयता के उस स्तर की आवश्यकता है।


9
यह सबसे अच्छा जवाब क्यों नहीं है?
21


1

बंद या कार्यों के साथ एम्बेडेड एक तरीका है। जेएस में यह सामान्य है, हालांकि गैर-ब्राउज़र प्लेटफार्मों या ब्राउज़र श्रमिकों के लिए आवश्यक नहीं है।

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


-11

पायथन के माध्यम से तीन मोड हैं। निजी, सार्वजनिक और संरक्षित। एक मॉड्यूल आयात करने वाला केवल सार्वजनिक मोड सुलभ है। निजी और संरक्षित मॉड्यूल को मॉड्यूल के बाहर से नहीं बुलाया जा सकता है, जब यह आयात किया जाता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.