पायथन वैरिएबल घोषणा


85

अजगर सीखना , और कुछ बुनियादी संदेह हैं।

1. मैंने चर घोषणा (यहां पथ) के रूप में देखा है

class writer:
    path = ""

कभी कभी, कोई स्पष्ट घोषणा लेकिन के माध्यम से प्रारंभ __init__

def __init__(self, name):
    self.name = name

मैं इसका उद्देश्य समझता हूं __init__, लेकिन क्या किसी अन्य कार्य में परिवर्तनशील घोषित करना उचित है।

2. कैसे मैं एक कस्टम प्रकार धारण करने के लिए चर बना सकते हैं?

class writer:
    path = "" # string value
    customObj = ??

12
और, 2 वें प्रश्न के विषय में: पायथन में, चर प्रकार नहीं हैं: मान करते हैं। तो कोई भी चर आपके कस्टम ऑब्जेक्ट को पकड़ सकता है।
jpaugh

4
यदि आप नाम / निष्क्रियताओं को चर के रूप में सोचना बंद कर देंगे तो यह मदद करेगा । वे वस्तुओं के संदर्भ हैं
जॉन ला रूय

2
@gnibbler या उनके लिए नाम ...
6:13

1
@ मुझे लगता है कि नाम एक बुरा विकल्प है। आमतौर पर चीजों का केवल एक नाम होता है जबकि किसी वस्तु में कई संदर्भ हो सकते हैं
जॉन ला रोय

2
@ जॉनसन, लेकिन अजगर गणित की तरह काम नहीं करता है। यदि आप अजगर को समझना चाहते हैं, तो आपको यह जानना होगा कि एक __name__विशेषता वाले ऑब्जेक्ट का "नाम" है। सभी वस्तुओं में एक __name__विशेषता नहीं है, लेकिन आप अभी भी उनके संदर्भ ले सकते हैं। यदि हम "संदर्भ" को "नाम" कहना शुरू करते हैं, तो हम शुरुआत कर रहे हैं ट्रैक के नीचे एक असंतोष।
जॉन ला रोय

जवाबों:


202

ठीक है, पहले चीजें पहले।

पायथन में "वैरिएबल डिक्लेरेशन" या "वैरिएबल इनिशियलाइजेशन" जैसी कोई चीज नहीं है।

वहाँ बस है जिसे हम "असाइनमेंट" कहते हैं, लेकिन शायद सिर्फ "नामकरण" कहा जाना चाहिए।

असाइनमेंट का अर्थ है "बाएं हाथ की तरफ का यह नाम अब दाहिने हाथ की ओर के मूल्यांकन के परिणाम को संदर्भित करता है, भले ही यह पहले (अगर कुछ भी) संदर्भित किया गया हो"।

foo = 'bar' # the name 'foo' is now a name for the string 'bar'
foo = 2 * 3 # the name 'foo' stops being a name for the string 'bar',
# and starts being a name for the integer 6, resulting from the multiplication

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

दूसरा बिंदु: कक्षाओं में आने पर पायथन एक बहुत ही सरल नियम का पालन करता है, जो कि वास्तव में जावा, सी ++ और सी # जैसी भाषाओं की तुलना में बहुत अधिक सुसंगत है: ब्लॉक के अंदर घोषित सब कुछ classकक्षा का हिस्सा है । इसलिए, defयहां लिखे गए कार्य ( ) तरीके हैं, अर्थात कक्षा ऑब्जेक्ट का हिस्सा (प्रति-उदाहरण के आधार पर संग्रहीत नहीं), जैसे जावा, सी ++ और सी # में; लेकिन यहाँ अन्य नाम भी कक्षा का हिस्सा हैं । फिर, नाम सिर्फ नाम हैं, और उनके पास संबद्ध प्रकार नहीं हैं, और फ़ंक्शन भी पायथन में ऑब्जेक्ट हैं। इस प्रकार:

class Example:
    data = 42
    def method(self): pass

कक्षाएं पिथॉन में भी ऑब्जेक्ट हैं

तो अब हमने एक ऑब्जेक्ट बनाया है जिसका नाम है Example, जो उन सभी चीजों के वर्ग का प्रतिनिधित्व करता है जो Exampleएस हैं। इस ऑब्जेक्ट में दो उपयोगकर्ता-प्रदत्त विशेषताएँ हैं (C C ++ में, "सदस्य"; C # में, "फ़ील्ड या गुण या विधियाँ"; जावा में, "फ़ील्ड या विधियाँ")। उनमें से एक का नाम है data, और यह पूर्णांक मान संग्रहीत करता है 42। दूसरे का नाम है method, और यह एक फ़ंक्शन ऑब्जेक्ट संग्रहीत करता है। (कई और विशेषताएँ हैं जिन्हें पायथन अपने आप जोड़ता है।)

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

आइए एक उदाहरण बनाएं:

x = Example()

अब हमारे पास नाम की एक अलग वस्तु है x, जिसका एक उदाहरण है Exampledataऔर methodवास्तव में वस्तु का हिस्सा नहीं हैं, लेकिन हम अभी भी के माध्यम से उन्हें देख सकते हैं xकुछ जादू अजगर पर्दे के पीछे है कि की वजह से। जब हम ऊपर देखते हैं method, विशेष रूप से, हम इसके बजाय एक "बाध्य विधि" प्राप्त करेंगे (जब हम इसे कहते हैं, xतो selfपैरामीटर के रूप में स्वचालित रूप से पारित हो जाता है , जो कि Example.methodसीधे ऊपर देखने पर ऐसा नहीं हो सकता है )।

जब हम उपयोग करने की कोशिश करते हैं तो क्या होता है x.data?

जब हम इसकी जांच करते हैं, तो यह पहले ऑब्जेक्ट में दिखाई देता है। यदि यह ऑब्जेक्ट में नहीं पाया जाता है, तो पायथन क्लास में दिखता है।

हालाँकि, जब हम असाइन करते हैं x.data , तो पायथन ऑब्जेक्ट पर एक विशेषता बनाएगा। यह वर्ग की विशेषता को प्रतिस्थापित नहीं करेगा ।

यह हमें ऑब्जेक्ट इनिशियलाइज़ेशन करने की अनुमति देता है । पायथन स्वचालित रूप से __init__नए इंस्टेंस पर कक्षा की विधि को कॉल करेगा जब वे बनाए जाते हैं, यदि मौजूद हो। इस विधि में, हम प्रत्येक वस्तु पर उस विशेषता के लिए प्रारंभिक मान सेट करने के लिए विशेषताओं को निर्दिष्ट कर सकते हैं:

class Example:
    name = "Ignored"
    def __init__(self, name):
        self.name = name
    # rest as before

अब हमें निर्दिष्ट करना चाहिए nameजब हम एक बनाते हैं Example, और प्रत्येक उदाहरण का अपना होता है nameExample.nameजब भी हम .nameकिसी उदाहरण को देखते हैं तो पायथन वर्ग की विशेषता को अनदेखा कर देगा , क्योंकि उदाहरण की विशेषता पहले मिल जाएगी।

एक अंतिम चेतावनी: संशोधन (उत्परिवर्तन) और असाइनमेंट अलग-अलग चीजें हैं!

पायथन में, तार अपरिवर्तनीय हैं। उन्हें संशोधित नहीं किया जा सकता है। जब तुम करोगे:

a = 'hi '
b = a
a += 'mom'

आप मूल 'हाय' स्ट्रिंग को नहीं बदलते हैं । पायथन में यह असंभव है। इसके बजाय, आप एक नया स्ट्रिंग बनाते हैं 'hi mom', और इसके aलिए एक नाम होना बंद करने का कारण बनते हैं 'hi ', और 'hi mom'इसके बजाय एक नाम होना शुरू करते हैं। हमने bएक नाम भी बनाया है 'hi ', और नाम को फिर से लागू करने के बाद a, bअभी भी एक नाम है 'hi ', क्योंकि 'hi 'अभी भी मौजूद है और इसे बदला नहीं गया है।

लेकिन सूचियों को बदला जा सकता है:

a = [1, 2, 3]
b = a
a += [4]

अब b[1, 2, 3, 4] भी है, क्योंकि हमने bएक ही चीज़ के लिए एक नाम बनाया है a, और फिर हमने उस चीज़ को बदल दिया। हमने aनाम के लिए एक नई सूची नहीं बनाई है , क्योंकि पायथन बस +=सूचियों के लिए अलग तरह से व्यवहार करता है।

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


12
यही कारण है कि हम उन्हें 'पहचानकर्ता' कहते हैं । :-)
मार्टिन पीटर्स

@ Karl_Knechtel अंत में अपने स्ट्रिंग उदाहरण में, 'hi' का क्या होता है अगर हम इसे 'b' नाम नहीं देते हैं? क्या यह स्मृति रिसाव है?
हेटोइनफिनिटी

2
@heretoinfinity: नहीं; अजगर अनुपयोगी वस्तुओं को मुक्त करने के लिए कचरा संग्रह का उपयोग करता है
जॉन क्लेमेंट्स

चर घोषणा अच्छी तरह से इस वीडियो में समझाया गया है: youtube.com/watch?v=ao2N37E-D9s
इशाक खान

उत्तर के लिए इस वीडियो को देखें youtube.com/-
Thao N

23

यह 6 साल देर हो सकती है, लेकिन पायथन 3.5 और इसके बाद के संस्करण में, आप इस तरह एक चर प्रकार की घोषणा करते हैं:

variable_name: type_name

या यह:

variable_name # type: shinyType

तो आपके मामले में (यदि आपके पास एक CustomObjectवर्ग परिभाषित है), आप कर सकते हैं:

customObj: CustomObject

देखें इस या कि अधिक जानकारी के लिए।


22

पायथन में नए चर घोषित करने की कोई आवश्यकता नहीं है। यदि हम फ़ंक्शन या मॉड्यूल में चर के बारे में बात कर रहे हैं, तो किसी भी घोषणा की आवश्यकता नहीं है। केवल उस नाम के लिए एक मान निर्दिष्ट करें जहाँ आपको इसकी आवश्यकता है mymagic = "Magic":। पायथन में चर किसी भी प्रकार के मूल्यों को पकड़ सकते हैं, और आप इसे प्रतिबंधित नहीं कर सकते।

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

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

class Thing(object):

    def __init__(self, magic):
        self.magic = magic

आसान। अब इस वर्ग के उदाहरणों में एक magicविशेषता है:

thingo = Thing("More magic")
# thingo.magic is now "More magic"

कक्षा के नाम स्थान में चर बनाने से पूरी तरह से अलग व्यवहार होता है। यह कार्यात्मक रूप से अलग है, और आपको केवल तभी करना चाहिए जब आपके पास कोई विशिष्ट कारण हो। उदाहरण के लिए:

class Thing(object):

    magic = "Magic"

    def __init__(self):
        pass

अब कोशिश करो:

thingo = Thing()
Thing.magic = 1
# thingo.magic is now 1

या:

class Thing(object):

    magic = ["More", "magic"]

    def __init__(self):
        pass

thing1 = Thing()
thing2 = Thing()
thing1.magic.append("here")
# thing1.magic AND thing2.magic is now ["More", "magic", "here"]

इसका कारण यह है कि वर्ग का नामस्थान स्वयं से बनाई गई वस्तुओं के नामस्थान से भिन्न है। मैं इसे अनुसंधान के लिए छोड़ दूँगा कि थोड़ा और।

टेक-होम संदेश यह है कि मुहावरेदार पायथन आपकी __init__विधि में (ए) प्रारंभिक ऑब्जेक्ट विशेषताएँ है , और (बी) आवश्यकतानुसार आपके वर्ग के व्यवहार का दस्तावेजीकरण करता है। आपको जो कुछ भी लिखना है उसके लिए आपको फुल-स्फिंक्स-स्तरीय दस्तावेज़ की परेशानी में जाने की ज़रूरत नहीं है, लेकिन जो भी विवरण या किसी और के बारे में कम से कम कुछ टिप्पणियां आपको इसे लेने की आवश्यकता हो सकती है।


12

डांटने के उद्देश्य के लिए, मैं उपयोग करता हूं:

custom_object = None

1

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

list = []
for i in stuff:
  list.append(i)

वैसे, यह वास्तव में सूची को सेटअप करने का एक अच्छा तरीका नहीं है। यह कहना बेहतर होगा:

list = [i for i in stuff] # list comprehension

...लेकिन मैं पीछे हटा।

आपका अन्य प्रश्न कस्टम ऑब्जेक्ट एक वर्ग ही होना चाहिए।

class CustomObject(): # always capitalize the class name...this is not syntax, just style.
  pass
customObj = CustomObject()
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.