पायथन के 'निजी' तरीके वास्तव में निजी क्यों नहीं हैं?


657

पायथन हमें इस तरह नाम के लिए डबल अंडरस्कोर लगाकर एक वर्ग के भीतर 'निजी' तरीके और चर बनाने की क्षमता देता है __myPrivateMethod():। फिर कैसे, यह कोई भी समझा सकता है

>>> class MyClass:
...     def myPublicMethod(self):
...             print 'public method'
...     def __myPrivateMethod(self):
...             print 'this is private!!'
... 
>>> obj = MyClass()
>>> obj.myPublicMethod()
public method
>>> obj.__myPrivateMethod()
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: MyClass instance has no attribute '__myPrivateMethod'
>>> dir(obj)
['_MyClass__myPrivateMethod', '__doc__', '__module__', 'myPublicMethod']
>>> obj._MyClass__myPrivateMethod()
this is private!!

क्या बात है?!

मैं इसे उन लोगों के लिए थोड़ा समझाता हूँ, जिन्हें यह समझ नहीं आया।

>>> class MyClass:
...     def myPublicMethod(self):
...             print 'public method'
...     def __myPrivateMethod(self):
...             print 'this is private!!'
... 
>>> obj = MyClass()

मैंने जो कुछ किया वह एक सार्वजनिक पद्धति और एक निजी पद्धति के साथ एक वर्ग बनाना है और इसे तत्काल करना है।

इसके बाद, मैं इसकी सार्वजनिक विधि कहता हूं।

>>> obj.myPublicMethod()
public method

इसके बाद, मैं इसके निजी तरीके को आजमाता हूं।

>>> obj.__myPrivateMethod()
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: MyClass instance has no attribute '__myPrivateMethod'

यहाँ सब कुछ अच्छा लग रहा है; हम इसे कॉल करने में असमर्थ हैं। यह वास्तव में, 'निजी' है। खैर, वास्तव में यह नहीं है। ऑब्जेक्ट पर रनिंग डिर () एक नई जादुई विधि को प्रकट करता है जो अजगर आपके सभी 'निजी' तरीकों के लिए जादुई रूप से बनाता है।

>>> dir(obj)
['_MyClass__myPrivateMethod', '__doc__', '__module__', 'myPublicMethod']

इस नए तरीके का नाम हमेशा अंडरस्कोर होता है, उसके बाद क्लास नाम, उसके बाद मेथड नेम।

>>> obj._MyClass__myPrivateMethod()
this is private!!

इतना एनकैप्सुलेशन के लिए, एह?

किसी भी मामले में, मैंने हमेशा सुना होगा पायथन एनकैप्सुलेशन का समर्थन नहीं करता है, इसलिए भी कोशिश क्यों करें? क्या देता है?


18
जावा या C # के लिए समान है यदि आप परावर्तन का उपयोग करते हैं (जो किसी तरह आप वहां कर रहे हैं)।
0x434D53

4
यह यूनिट परीक्षण उद्देश्य के लिए बनाया गया था, इसलिए आप उस "हैक" का उपयोग कर सकते हैं ताकि यूनिट अपनी कक्षा के निजी तरीकों का बाहर से परीक्षण कर सके।
वास १

16
क्या निजी तरीकों का परीक्षण एक प्रतिमान नहीं है? निजी तरीकों का इस्तेमाल कुछ सार्वजनिक तरीकों में किया जाएगा, यकीन है कि यह हमेशा के लिए अप्रयुक्त है। और निजी तरीकों का परीक्षण करने का सही तरीका (थॉटवर्क्स से अब तक मेरे सीखने के आधार पर) यह है कि आप केवल सार्वजनिक तरीकों के लिए परीक्षण लिखते हैं जो सभी मामलों को कवर करता है। यदि यह ठीक काम करता है, तो आपको बाहर से निजी तरीकों का परीक्षण करने की आवश्यकता नहीं है।
विष्णु नारंग

3
@VishnuNarang: हाँ, यह अक्सर सिखाया जाता है। लेकिन हमेशा की तरह, " हमेशा ऐसा करने वाला" लगभग "धार्मिक" दृष्टिकोण , ऐसा कभी नहीं करता है "केवल" कभी भी अच्छा नहीं होता है। यदि यूनिट परीक्षण "केवल" प्रतिगमन परीक्षणों या सार्वजनिक एपीआई के परीक्षण के लिए उपयोग किया जाता है, तो आपको निजीकरण का परीक्षण करने की आवश्यकता नहीं है। लेकिन अगर आप इकाई परीक्षण संचालित विकास करते हैं, तो विकास के दौरान निजी तरीकों का परीक्षण करने के अच्छे कारण हैं (उदाहरण के लिए जब सार्वजनिक इंटरफ़ेस के माध्यम से कुछ असामान्य / चरम मापदंडों का मज़ाक उड़ाना मुश्किल है)। कुछ भाषाएँ / यूनिट परीक्षण वातावरण आपको ऐसा करने की अनुमति नहीं देते हैं, जो IMHO अच्छा नहीं है।
मार्को फ्रायडेनबर्गर

5
@MarcoFreudenberger मैं आपकी बात देखता हूं। मुझे इकाई परीक्षण संचालित विकास में अनुभव है। अक्सर जब मापदंडों का मजाक उड़ाना मुश्किल हो जाता है, तो अधिकतर इसे डिजाइन को बदलने और सुधारने से हल किया जाता है। मुझे अभी तक एक ऐसे परिदृश्य के बारे में पता नहीं चला है जहाँ डिज़ाइन सही है और फिर भी निजी विधियों के परीक्षण से बचने के लिए यूनिट परीक्षण बेहद कठिन है। मैं ऐसे मामलों की तलाश करूंगा। धन्यवाद। मुझे खुशी होगी अगर आप मुझे समझने में मदद करने के लिए अपने सिर के ऊपर से एक परिदृश्य साझा कर सकते हैं।
विष्णु नारंग

जवाबों:


592

स्क्रैचिंग नाम का उपयोग यह सुनिश्चित करने के लिए किया जाता है कि उपवर्ग गलती से अपने सुपरक्लास की निजी विधियों और विशेषताओं को ओवरराइड न करें। इसे बाहर से जानबूझकर पहुंचने से रोकने के लिए नहीं बनाया गया है।

उदाहरण के लिए:

>>> class Foo(object):
...     def __init__(self):
...         self.__baz = 42
...     def foo(self):
...         print self.__baz
...     
>>> class Bar(Foo):
...     def __init__(self):
...         super(Bar, self).__init__()
...         self.__baz = 21
...     def bar(self):
...         print self.__baz
...
>>> x = Bar()
>>> x.foo()
42
>>> x.bar()
21
>>> print x.__dict__
{'_Bar__baz': 21, '_Foo__baz': 42}

बेशक, यह टूट जाता है अगर दो अलग-अलग वर्गों का एक ही नाम हो।


12
docs.python.org/2/tutorial/classes.html । अनुभाग: 9.6 निजी चर और स्थानीय-स्थानीय संदर्भों पर।
गजैन

72
उन लोगों के लिए जो स्क्रॉल / खोज करने के लिए बहुत आलसी हैं: धारा 9.6 सीधा लिंक
कोड 3monk3y

3
आपको यह निर्दिष्ट करने के लिए एक एकल अंडरस्कोर रखना चाहिए कि चर को निजी माना जाना चाहिए। फिर, यह किसी को वास्तव में उस तक पहुंचने से नहीं रोकता है।
इगन

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

1
यदि आप "जानबूझकर पहुंच को रोकने" की कसौटी पर चलते हैं, तो अधिकांश ओओपी भाषाएँ वास्तव में निजी सदस्यों का समर्थन नहीं करती हैं। C ++ में उदाहरण के लिए आपके पास मेमोरी तक कच्ची पहुंच है और C # विश्वसनीय कोड में निजी प्रतिबिंब का उपयोग किया जा सकता है।
कोडइन्चोस 19

207

निजी समारोह का उदाहरण

import re
import inspect

class MyClass :

    def __init__(self) :
        pass

    def private_function ( self ) :
        try :
            function_call = inspect.stack()[1][4][0].strip()

            # See if the function_call has "self." in the begining
            matched = re.match( '^self\.', function_call )
            if not matched :
                print 'This is Private Function, Go Away'
                return
        except :
            print 'This is Private Function, Go Away'
            return

        # This is the real Function, only accessible inside class #
        print 'Hey, Welcome in to function'

    def public_function ( self ) :
        # i can call private function from inside the class
        self.private_function()

### End ###

12
self = MyClass() self.private_function()। : निश्चित रूप से यह कक्षाओं में काम नहीं करता है, लेकिन आपको बस एक कस्टम फ़ंक्शन को परिभाषित करना है: def foo(self): self.private_function()
केसी कुबल

161
बस के मामले में यह स्पष्ट नहीं था: वास्तविक कोड में ऐसा कभी न करें;)
सूडो बैश

10
@ थोरसुमोनर या बस function_call.startswith('self.')
nyuszika7h

13
inspect.stack()[1][4][0].strip()<- वो १, ४, और ० जादू नंबर क्या हैं?
अक्खी

5
ऐसा करने self = MyClass(); self.private_function()से इसे आसानी से हराया जा सकता है और यह x = self.private_function()एक विधि के अंदर उपयोग करने पर विफल हो जाता है ।
विल

171

जब मैं पहली बार जावा से पायथन में आया तो मुझे इससे नफरत थी । इसने मुझे मौत से डरा दिया।

आज यह सिर्फ एक चीज हो सकती है जिसे मैं पायथन के बारे में सबसे ज्यादा प्यार करता हूं

मुझे एक मंच पर रहना पसंद है, जहां लोग एक-दूसरे पर भरोसा करते हैं और ऐसा महसूस नहीं करते कि उन्हें अपने कोड के आसपास अभेद्य दीवारें बनाने की जरूरत है। यदि किसी एपीआई में बग है, और दृढ़ता से संकुचित भाषाओं में, आपको पता चल गया है कि क्या गलत है, तो आप अभी भी इसके आसपास काम करने में असमर्थ हो सकते हैं क्योंकि आवश्यक विधि निजी है। पायथन में दृष्टिकोण है: "सुनिश्चित"। यदि आपको लगता है कि आप स्थिति को समझते हैं, तो शायद आपने भी इसे पढ़ा है, तो हम सभी कह सकते हैं कि "अच्छी किस्मत!"।

याद रखें, एनकैप्सुलेशन भी कमजोर रूप से "सुरक्षा" से संबंधित नहीं है, या बच्चों को लॉन से दूर रखना है। यह सिर्फ एक और पैटर्न है जिसका उपयोग कोड आधार को समझने में आसान बनाने के लिए किया जाना चाहिए।


36
@CamJackson जावास्क्रिप्ट आपके उदाहरण है ?? एकमात्र व्यापक रूप से इस्तेमाल की जाने वाली भाषा जिसमें प्रोटोटाइब-आधारित विरासत है और एक भाषा जो कार्यात्मक प्रोग्रामिंग का पक्ष लेती है? मुझे लगता है कि जेएस को अन्य भाषाओं की तुलना में सीखना बहुत कठिन है, क्योंकि यह पारंपरिक ओओपी से कई ऑर्थोगोनल कदम उठाता है। ऐसा नहीं है कि यह बेवकूफों को JS लिखने से रोकता है, वे इसे नहीं जानते हैं;)
Ktete

23
एपीआई वास्तव में एक बहुत अच्छा उदाहरण है कि क्यों एनकैप्सुलेशन मायने रखता है और जब निजी तरीकों को प्राथमिकता दी जाएगी। निजी होने का एक तरीका दूर जा सकता है, हस्ताक्षर बदल सकते हैं, या सभी परिवर्तन व्यवहार का सबसे खराब हो सकता है - सभी चेतावनी के बिना - किसी भी बाद के नए संस्करण पर। क्या आपके स्मार्ट, वयस्क टीम के सदस्य को वास्तव में याद होगा कि जब आप अपडेट करते हैं, तो वह एक साल पहले से ही एक इरादा-से-निजी पद्धति तक पहुंचता है? क्या वह भी अब वहां काम कर रही होगी?
अशुभ

2
मैं तर्क से असहमत हूं। उत्पादन कोड में, मैं शायद एक एपीआई का उपयोग कभी नहीं करूंगा जिसमें एक बग है जो मुझे "काम" बनाने के लिए सार्वजनिक सदस्यों को बदलता है। एक एपीआई को काम करना चाहिए। यदि ऐसा नहीं होता है, तो मैं एक बग रिपोर्ट दर्ज करूंगा या स्वयं वही एपीआई बनाऊंगा। मुझे दर्शन पसंद नहीं है और मैं पाइथन का बहुत शौकीन नहीं हूँ, हालाँकि इसके वाक्य रचना में छोटी-छोटी
पटकथाएँ

4
Java मे Method.setAccessible और Field.setAccessible है। इसके अलावा डरावना?
टोनी

15
जावा और सी ++ में प्रवर्तन नहीं है क्योंकि जावा उपयोगकर्ता को अविश्वास करता है जबकि पायथन करता है। इसकी वजह यह है कि संकलक और / या vm विभिन्न मान्यताओं को बना सकते हैं, जब उनके व्यवसाय के बारे में कैसे पता चलता है अगर यह जानकारी पता है, तो उदाहरण के लिए C ++ वर्चुअल कॉल के बजाय नियमित पुराने C कॉल का उपयोग करके अप्रत्यक्ष की एक पूरी परत को छोड़ सकता है, और जब आपका प्रदर्शन उच्च प्रदर्शन या उच्च परिशुद्धता वाले सामान पर काम कर रहा हो। इसकी प्रकृति से अजगर वास्तव में इसकी गतिशीलता से समझौता किए बिना सूचना का अच्छा उपयोग नहीं कर सकता है। दोनों भाषाएं अलग-अलग चीजों पर लक्षित हैं, इसलिए न तो "गलत" हैं
Shayne

144

से http://www.faqs.org/docs/diveintopython/fileinfo_private.html

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


202
या जैसा कि गुइडो वैन रोसुम ने कहा: "हम सभी वयस्क हैं।"

35
-1: यह सिर्फ गलत है। डबल अंडरस्कोर का मतलब कभी भी निजी के रूप में इस्तेमाल नहीं किया जाना चाहिए। नीचे अालिया का जवाब मैनिंग सिंटैक्स नाम के वास्तविक इरादे को बताता है। वास्तविक सम्मेलन एकल अंडरस्कोर है।
nosklo

2
केवल एक अंडरस्कोर के साथ प्रयास करें और आपको प्राप्त परिणाम दिखाई देगा। @ नोस्कोलो
बिलाल बेगेरदज

93

आमतौर पर इस्तेमाल किया जाने वाला वाक्यांश "हम सभी यहां वयस्कों की सहमति दे रहे हैं"। एक एकल अंडरस्कोर (एक्सपोज़ न करें) या डबल अंडरस्कोर (छुपाएँ) को प्रस्तुत करने से, आप अपने वर्ग के उपयोगकर्ता को बता रहे हैं कि आप सदस्य को किसी तरह 'निजी' होने का इरादा रखते हैं। हालाँकि, आप हर किसी पर जिम्मेदारी से व्यवहार करने के लिए भरोसा कर रहे हैं और उसका सम्मान करते हैं, जब तक कि उनके पास ऐसा करने के लिए कोई आकर्षक कारण न हो (जैसे डिबगर्स, कोड पूरा होना)।

यदि आपके पास वास्तव में कुछ ऐसा है जो निजी है, तो आप इसे एक एक्सटेंशन में लागू कर सकते हैं (उदाहरण के लिए सीपी के लिए सी)। हालांकि, ज्यादातर मामलों में, आप बस चीजों को करने के पाइथोनिक तरीके को सीखते हैं।


तो क्या कुछ प्रकार के रैपर प्रोटोकॉल हैं जिन्हें मैं एक संरक्षित चर का उपयोग करने के लिए उपयोग करने वाला हूं?
१०'१०

3
"निजी" होने की तुलना में किसी भी तरह से "संरक्षित" चर नहीं हैं। यदि आप एक विशेषता को एक्सेस करना चाहते हैं जो अंडरस्कोर से शुरू होती है, तो आप इसे कर सकते हैं (लेकिन ध्यान दें कि लेखक इसे हतोत्साहित करता है)। यदि आपको एक ऐसी विशेषता का उपयोग करना चाहिए जो एक डबल अंडरस्कोर के साथ शुरू होता है, तो आप नाम को खुद से कर सकते हैं, लेकिन आप लगभग निश्चित रूप से ऐसा नहीं करना चाहते हैं।
टोनी मेयर

33

यह बिलकुल नहीं है कि आप किसी भी भाषा में सदस्यों की निजीता (C ++ में सूचक अंकगणित, .NET / Java में प्रतिबिंब) के लगभग पूर्ण रूप से प्राप्त नहीं कर सकते।

मुद्दा यह है कि यदि आप गलती से निजी पद्धति को कॉल करने का प्रयास करते हैं तो आपको एक त्रुटि मिलती है। लेकिन अगर आप खुद को पैर में गोली मारना चाहते हैं, तो आगे बढ़ें और ऐसा करें।

संपादित करें: आप अपने सामान को OO- एनकैप्सुलेशन द्वारा सुरक्षित करने की कोशिश नहीं करते हैं, क्या आप?


2
हर्गिज नहीं। मैं बस इस बात को बना रहा हूं कि डेवलपर को एक आसान देने के लिए यह अजीब है, और मेरी राय में जादुई, 'निजी' गुणों तक पहुंचने का तरीका है।
वूरर्ड

2
हाँ, मैंने सिर्फ इस बात को स्पष्ट करने की कोशिश की। कंपाइलर शिकायत करके इसे केवल "आप इसे सीधे एक्सेस नहीं करना चाहिए" कहते हुए इसे निजी बनाते हैं। लेकिन कोई वास्तव में ऐसा करना चाहता है। लेकिन हाँ, यह अन्य भाषाओं की तुलना में पायथन में आसान है।
मैक्सिमिलियन

7
जावा में, आप वास्तव में एन्कैप्सुलेशन के माध्यम से सामान को सुरक्षित कर सकते हैं, लेकिन इसके लिए आपको स्मार्ट होना चाहिए और एक सिक्योरमैनमैन में अविश्वसनीय कोड चलाना चाहिए, और बहुत सावधान रहना चाहिए। यहां तक ​​कि ओरेकल भी कभी-कभी गलत हो जाता है।
एंटीमनी

12

class.__stuffनामकरण सम्मेलन प्रोग्रामर पता है वह पहुँच उपलब्ध कराना नहीं है की सुविधा देता है__stuff बाहर से। नाम का नामकरण यह किसी को भी दुर्घटना की संभावना से नहीं करेगा।

सच है, आप अभी भी इसके चारों ओर काम कर सकते हैं, यह अन्य भाषाओं की तुलना में भी आसान है (जो कि बीटीडब्ल्यू ने आपको ऐसा करने की अनुमति भी दी है), लेकिन कोई पायथन प्रोग्रामर ऐसा नहीं करेगा यदि वह इनकैप्सुलेशन की परवाह करता है।


12

इसी तरह का व्यवहार तब होता है जब मॉड्यूल विशेषता नाम एक एकल अंडरस्कोर (उदाहरण के लिए _foo) से शुरू होता है।

इस प्रकार नामित मॉड्यूल विशेषताओं को from*विधि का उपयोग करते समय एक आयात मॉड्यूल में कॉपी नहीं किया जाएगा , उदाहरण के लिए:

from bar import *

हालांकि, यह एक सम्मेलन है और भाषा की कमी नहीं है। ये निजी गुण नहीं हैं; उन्हें किसी भी आयातक द्वारा संदर्भित और हेरफेर किया जा सकता है। कुछ का तर्क है कि इस वजह से, पायथन सही एनकैप्सुलेशन को लागू नहीं कर सकता है।


12

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

डिबगिंग हुक और परीक्षण संभव अनुप्रयोगों के रूप में दिमाग में आते हैं, जिम्मेदारी से इस्तेमाल किए जाते हैं।


4

पायथन 3.4 के साथ यह व्यवहार है:

>>> class Foo:
        def __init__(self):
                pass
        def __privateMethod(self):
                return 3
        def invoke(self):
                return self.__privateMethod()


>>> help(Foo)
Help on class Foo in module __main__:

class Foo(builtins.object)
 |  Methods defined here:
 |
 |  __init__(self)
 |
 |  invoke(self)
 |
 |  ----------------------------------------------------------------------
 |  Data descriptors defined here:
 |
 |  __dict__
 |      dictionary for instance variables (if defined)
 |
 |  __weakref__
 |      list of weak references to the object (if defined)

 >>> f = Foo()
 >>> f.invoke()
 3
 >>> f.__privateMethod()
 Traceback (most recent call last):
   File "<pyshell#47>", line 1, in <module>
     f.__privateMethod()
 AttributeError: 'Foo' object has no attribute '__privateMethod'

https://docs.python.org/3/tutorial/classes.html#tut-private

ध्यान दें कि हादसों से बचने के लिए ज्यादातर नियमों को डिजाइन किया गया है; निजी चर माने जाने वाले चर को एक्सेस करना या संशोधित करना अभी भी संभव है। यह विशेष परिस्थितियों में भी उपयोगी हो सकता है, जैसे कि डिबगर में।

यहां तक ​​कि अगर प्रश्न पुराना है, मुझे आशा है कि मेरा स्निपेट मददगार हो सकता है।


2

निजी तरीकों और विशेषताओं के बारे में सबसे महत्वपूर्ण चिंता डेवलपर्स को यह बताने के लिए है कि इसे कक्षा के बाहर नहीं बुलाया जाए और यह एनकैप्सुलेशन है। कोई भी एन्कैप्सुलेशन से सुरक्षा को गलत समझ सकता है। जब कोई जानबूझ कर आपके द्वारा बताए गए (bellow) जैसे सिंटैक्स का उपयोग करता है, तो आप एनकैप्सुलेशन नहीं चाहते हैं।

obj._MyClass__myPrivateMethod()

मैं C # से विस्थापित हो गया हूं और सबसे पहले यह मेरे लिए भी अजीब था, लेकिन थोड़ी देर बाद मुझे यह विचार आया कि केवल जिस तरह से पायथन कोड डिजाइनर OOP के बारे में सोचते हैं वह अलग है।


1

पायथन के 'निजी' तरीके वास्तव में निजी क्यों नहीं हैं?

जैसा कि मैंने इसे समझा, वे निजी नहीं हो सकते । गोपनीयता को कैसे लागू किया जा सकता है?

स्पष्ट उत्तर है "निजी सदस्यों को केवल self" के माध्यम से पहुँचा जा सकता है , लेकिन वह काम नहीं करेगा - selfपायथन में विशेष नहीं है, यह एक फ़ंक्शन के पहले पैरामीटर के लिए आमतौर पर उपयोग किए जाने वाले नाम से अधिक कुछ नहीं है।

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