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


वहां एक है पाइथन में स्थैतिक चर को अनुकरण करने के लिए पूछने वाले प्रश्न

साथ ही, वेब पर स्थिर चर बनाने के लिए कई अलग-अलग समाधान मिल सकते हैं। (हालांकि मैंने ऐसा नहीं देखा है जिसे मैं अभी तक पसंद करता हूं।)

पाइथन विधियों में स्थिर चर का समर्थन क्यों नहीं करता है? क्या यह अवांछित माना जाता है या क्या यह पाइथन के वाक्यविन्यास के साथ कुछ करने के लिए है?

संपादित करें:

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


44
2018-02-26 23:28


मूल


जवाब के साथ क्या गलत था stackoverflow.com/questions/460586/...? सवाल फिर से क्यों पूछें? - S.Lott
मैंने स्पष्ट रूप से यह नहीं पूछा कि इसे कैसे अनुकरण किया जाए, लेकिन इस निर्णय का कारण क्या है। - Georg Schölly


जवाब:


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

यदि आप एक समारोह में राज्य की जानकारी संलग्न करना चाहते हैं, तो आपको एक वर्ग की आवश्यकता है। एक मामूली सरल वर्ग, शायद, लेकिन एक वर्ग फिर भी:

def foo(bar):
    static my_bar # doesn't work

    if not my_bar:
        my_bar = bar

    do_stuff(my_bar)

foo(bar)
foo()

# -- becomes ->

class Foo(object):
    def __init__(self, bar):
        self.bar = bar

    def __call__(self):
        do_stuff(self.bar)

foo = Foo(bar)
foo()
foo()

यदि आप अपने कार्य के व्यवहार को हर बार बदलने के लिए चाहते हैं, तो आपको जेनरेटर की आवश्यकता है:

def foo(bar):
    static my_bar # doesn't work

    if not my_bar:
        my_bar = bar

    my_bar = my_bar * 3 % 5

    return my_bar

foo(bar)
foo()

# -- becomes ->

def foogen(bar):
    my_bar = bar

    while True:
        my_bar = my_bar * 3 % 5
        yield my_bar

foo = foogen(bar)
foo.next()
foo.next()

बेशक, स्थैतिक चर कर रहे हैं त्वरित और गंदे स्क्रिप्ट के लिए उपयोगी जहां आप छोटे कार्यों के लिए बड़ी संरचनाओं की परेशानी से निपटना नहीं चाहते हैं। लेकिन वहां, आपको वास्तव में कुछ भी नहीं चाहिए global - यह एक लेकिन क्लेडी लग सकता है, लेकिन यह छोटी, एक-ऑफ स्क्रिप्ट के लिए ठीक है:

def foo():
    global bar
    do_stuff(bar)

foo()
foo()

75
2018-02-27 00:04



ठीक है इस तथ्य के लिए कि आपको वास्तव में कक्षा की आवश्यकता हो सकती है। बदसूरत बोर्ग पैटर्न के अलावा, यह वर्ग यह सुनिश्चित करने का कोई वास्तविक तरीका नहीं है कि यह वर्ग एक सिंगलटन है। असल में पैकेज का आयात इसे काफी दर्द देता है। - fulmicoton
क्लास नमूना ऐसा नहीं लगता है कि यह पाइथन है। मुझे लगता है कि आपका मतलब था: "निजी बार" => "बार = कोई नहीं", और init में आपके पास "self.my_bar = bar" होगा। - Heikki Toivonen
@ हेक्की टिवोनन: सहमत हैं, पहले उदाहरण में "my_bar" को क्लास वैरिएबल नहीं होना चाहिए, एक इंस्टेंस वैरिएबल भी काम करेगा। - dF.
@ पॉल: केवल क्लास-स्तरीय चर और @classmethod सजावट का उपयोग करें और आपकी कक्षा भी एक सिंगलटन ऑब्जेक्ट है। - S.Lott
अवधारणा के लिए +1, उपरोक्त टिप्पणियों के रूप में पाइथन कोड को साफ करने की आवश्यकता है :) - Ryan


कक्षा के लिए एक विकल्प एक समारोह विशेषता है:

def foo(arg):
    if not hasattr(foo, 'cache'):
        foo.cache = get_data_dict()
    return foo.cache[arg]

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


19
2018-02-27 01:41



इसे आधिकारिक कार्यवाही माना जाना चाहिए। +1 - Triptych
मुझे इसके बारे में क्या पसंद नहीं है, इस विधि को विधि का नाम लिखना आवश्यक है। अगर मैंने नाम बदल दिया तो मुझे आधे कोड को फिर से लिखना होगा। - Georg Schölly
@gs: हाँ, यह एक कमी है। मैं नाम (स्वयं की तरह कुछ) का उपयोग करने के बजाय वर्तमान फ़ंक्शन को संदर्भित करने का कोई तरीका ढूंढ रहा था, लेकिन मुझे नहीं लगता कि ऐसा कोई तरीका है। आप शीर्ष पर "यह = foo" कर सकते हैं और फिर हर जगह "यह" संदर्भित कर सकते हैं ताकि एक नाम बनाए रखना आसान हो। - davidavr
यह इस तरह काम करता है, लेकिन आप वास्तव में परेशानी के लिए खुद को स्थापित कर रहे हैं जब कोई फू आसपास गुजरता है और नाम प्राप्त करता है: वैश्विक नाम 'foo' परिभाषित नहीं किया गया है - Josh Lee
@jleedev: इस्तेमाल किए गए ग्लोबल्स (जिसमें "foo" नाम होता है) फ़ंक्शन है जब से मॉड्यूल ग्लोबल्स होते हैं बनाया था, जहां से इसे बुलाया जाता है (जो कि गतिशील के बजाय गतिशील स्कोपिंग को इंगित करेगा)। इसे चारों ओर पास करने से कोई फर्क नहीं पड़ता। - Brian


पायथन 3 में, मैं एक बंद करने का उपयोग करता हूं:

def makefoo():
    x = 0
    def foo():
        nonlocal x
        x += 1
        return x
    return foo

foo = makefoo()

print(foo())
print(foo())

8
2018-03-08 04:39



हैलो मैं अभी भी यह पता लगाने की कोशिश कर रहा हूं कि यह कैसे काम करता है। क्या आप थोड़ी और व्याख्या कर सकते हैं? अग्रिम में धन्यवाद। :) - BugShotGG


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


6
2018-02-26 23:35



मैं डिस्क से लोड चीजों को कैश करने के लिए उनका उपयोग करना चाहता हूं। मुझे लगता है कि यह उदाहरण कम हो जाता है, अगर मैं उन्हें समारोह में असाइन कर सकता हूं। - Georg Schölly


यह एक डिजाइन पसंद है।

मुझे लगता है कि गिडो सोचता है कि आपको अक्सर उनकी आवश्यकता नहीं है, और आप कभी नहीं वास्तव में उन्हें चाहिए: आप हमेशा एक ग्लोबल वैरिएबल का उपयोग कर सकते हैं और हर किसी को अपने चिकना पंजे को अपने चर को रखने के लिए कह सकते हैं ;-)


5
2018-02-26 23:37



ओह, या आप ऑब्जेक्ट को सामान्य के रूप में पास कर सकते हैं।
मान लीजिए कि आप QuickSort में अपने खुद के यादृच्छिक जनरेटर का उपयोग करना चाहते हैं। कॉलर्स यादृच्छिकता में गुजरना चाहिए? नहीं। क्या इसे (अन्यथा स्वतंत्र) कॉल के बीच अपडेट किया जाना चाहिए? हाँ। कभी-कभी आप ऑब्जेक्ट्स को पास नहीं करना चाहते हैं ... - Jonas Kölker
हाँ मुझे लगता है कि यह एक सही है, अगर सुंदर हाशिए, उदाहरण


कैशिंग के लिए या Memoization उद्देश्यों, सजावटी एक सुरुचिपूर्ण और सामान्य समाधान के रूप में इस्तेमाल किया जा सकता है।


4
2018-02-27 00:54





इसका जवाब उतना ही वही है जैसा कि कोई भी स्थिर तरीकों का उपयोग नहीं करता है (भले ही वे मौजूद हैं)। आपके पास एक मॉड्यूल-स्तरीय नेमस्पेस है जो किसी भी उद्देश्य के बारे में एक ही उद्देश्य के बारे में कार्य करता है।


0
2018-02-27 00:28





एक बीमार सलाह दी गई विकल्प:

आप फ़ंक्शन डिफ़ॉल्ट के परिभाषा समय मूल्यांकन के दुष्प्रभावों का भी उपयोग कर सकते हैं:

def func(initial=0, my_static=[])
  if not my_static:
    my_static.append(initial)

   my_static[0] += 1
  return my_static[0]

print func(0), func(0), func(0)

आईटी इस वास्तव में बदसूरत और आसानी से उलटा, लेकिन काम करता है। का उपयोग करते हुए global इससे बेहतर होगा, इमो।


0
2018-02-27 04:04