मैं पायथन में एक स्थिरांक कैसे बनाऊं?


988

क्या पायथन में एक स्थिर घोषित करने का एक तरीका है? जावा में हम इस तरीके से निरंतर मान बना सकते हैं:

public static final String CONST_NAME = "Name";

पायथन में उपरोक्त जावा निरंतर घोषणा के बराबर क्या है?


6
वास्तव में केवल पठनीय बनाने का तरीका अजगर के संपत्ति फ़ंक्शन / डेकोरेटर के माध्यम से संभव है । जवाब के निवेश संबंधी निर्णय निर्माताओं की एक कस्टम उपयोग का एक उदाहरण है। संपत्ति उससे अधिक सामान्य उपयोग है, हालांकि, यह कैसे शलभ चतुर्वेदी के पायथन गुण और विधियों पर काम करता है, का एक अच्छा विश्लेषण है ।
n611x007

20
IMHO, निरंतरता को लागू करना "पाइथोनिक नहीं" है। पायथन 2.7 में आप लिख भी सकते हैं True=False, और फिर (2+2==4)==Trueलौट सकते हैं False
osa

8
जैसा कि अन्य उत्तरों से पता चलता है कि स्थिरांक घोषित करने का कोई तरीका या तरीका नहीं है। लेकिन आप इस पीईपी को सम्मेलनों के बारे में पढ़ सकते हैं । उदा। THIS_IS_A_CONSTANT
परेरा

34
@ डोसा: आप अजगर 3 में ऐसा नहीं कर सकते - SyntaxError: can't assign to keyword। यह एक गुड थिंग की तरह लगता है।
n

3
हैरानी की बात यह है कि अब तक उल्लेख नहीं किया गया है, लेकिन Enums एक निरंतर स्थिरांक को परिभाषित करने के लिए एक अच्छा तरीका है।
cs95

जवाबों:


973

नहीं वहाँ नहीं है। आप पायथन में स्थिर के रूप में एक चर या मूल्य घोषित नहीं कर सकते। बस इसे बदल नहीं है।

यदि आप एक वर्ग में हैं, तो समतुल्य होगा:

class Foo(object):
    CONST_NAME = "Name"

यदि नहीं, यह सिर्फ है

CONST_NAME = "Name"

लेकिन आप एलेक्स मार्टेली द्वारा पायथन में कोड स्निपेट कॉन्स्टेंट पर एक नज़र रखना चाह सकते हैं ।


पायथन 3.8 के रूप में, एक typing.Finalवैरिएबल एनोटेशन है जो स्टेटिक टाइप चेकर्स (जैसे कि मैपी) को बताएगा कि आपके वेरिएबल को फिर से असाइन नहीं किया जाना चाहिए। यह जावा के सबसे नजदीक है final। हालाँकि, यह वास्तव में पुनर्मूल्यांकन को नहीं रोकता है :

from typing import Final

a: Final = 1

# Executes fine, but mypy will report an error if you run mypy on this:
a = 2

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

26
लोग पर्ल में उसी विशेषता के बारे में पूछते हैं। एक आयात मॉड्यूल है जिसे "निरंतर उपयोग करें" कहा जाता है, लेकिन (AFAIK) यह केवल एक आवरण है जिससे एक छोटे फ़ंक्शन का निर्माण होता है जो मान लौटाता है। मैं पायथन में भी यही करता हूं। उदाहरण:def MY_CONST_VALUE(): return 123
केविनरपे

8
"नहीं वहाँ नहीं है।" सच है, लेकिन अन्य लोगों के काम पर निर्माण करते हुए, मैंने अजगर 2.7 (जिसके लिए "एनम" का अभाव है) के लिए "कॉन्स्टेंट" के एक छोटे और सरल कार्यान्वयन के साथ, नीचे, एक उत्तर जोड़ा है। ये एनम-लाइक रीड-ओनली हैं name.attribute, और इसमें कोई भी मूल्य हो सकता है। घोषणा करना आसान है Nums = Constants(ONE=1, PI=3.14159, DefaultWidth=100.0), उपयोग सीधा है print 10 + Nums.PI, अपवाद में परिणाम बदलने का प्रयास Nums.PI = 22=> ValueError (..)।
टूलमेकरसेव

108
बस इसे बदल नहीं है। आपने मेरा दिन बनाया
हाय-एंजेल

89
"बस इसे मत बदलो" बिल्कुल भी मददगार नहीं है। यह सवाल का जवाब नहीं देता है और मैं सुझाव दूंगा कि इसे हटा दिया जाए।
बार्टेक बैनवाक्विज़

354

constअन्य भाषाओं की तरह कोई कीवर्ड नहीं है , हालांकि डेटा को पढ़ने के लिए एक "गेट्टर फ़ंक्शन" एक संपत्ति बनाना संभव है , लेकिन डेटा को फिर से लिखने के लिए कोई "सेटर फ़ंक्शन" नहीं हैयह अनिवार्य रूप से पहचानकर्ता को परिवर्तित होने से बचाता है।

यहाँ वर्ग संपत्ति का उपयोग कर एक वैकल्पिक कार्यान्वयन है:

ध्यान दें कि कोड एक पाठक के लिए स्थिरांक के बारे में सोचना आसान है। नीचे देखें स्पष्टीकरण

def constant(f):
    def fset(self, value):
        raise TypeError
    def fget(self):
        return f()
    return property(fget, fset)

class _Const(object):
    @constant
    def FOO():
        return 0xBAADFACE
    @constant
    def BAR():
        return 0xDEADBEEF

CONST = _Const()

print CONST.FOO
##3131964110

CONST.FOO = 0
##Traceback (most recent call last):
##    ...
##    CONST.FOO = 0
##TypeError: None

कोड स्पष्टीकरण:

  1. एक फ़ंक्शन को परिभाषित करें जो constantएक अभिव्यक्ति लेता है, और इसका उपयोग "गेट्टर" के निर्माण के लिए करता है - एक ऐसा फ़ंक्शन जो केवल अभिव्यक्ति के मूल्य को वापस करता है।
  2. सेटर फ़ंक्शन एक टाइप-इयरर को उठाता है इसलिए यह केवल पढ़ने के लिए है
  3. constantफ़ंक्शन का उपयोग करें जिसे हमने सजावट के रूप में बनाया है, केवल पढ़ने के लिए केवल गुणों को परिभाषित करने के लिए।

और कुछ अन्य पुराने ढंग से:

(कोड काफी पेचीदा है, नीचे और अधिक स्पष्टीकरण)

class _Const(object):
    @apply
    def FOO():
        def fset(self, value):
            raise TypeError
        def fget(self):
            return 0xBAADFACE
        return property(**locals())

CONST = _Const()

print CONST.FOO
##3131964110

CONST.FOO = 0
##Traceback (most recent call last):
##    ...
##    CONST.FOO = 0
##TypeError: None

ध्यान दें कि @apply डेकोरेटर को पदावनत किया जा रहा है।

  1. पहचानकर्ता FOO को परिभाषित करने के लिए, दो कार्य परिभाषित करते हैं (fset, fget - नाम मेरी पसंद पर हैं)।
  2. फिर propertyएक ऑब्जेक्ट का निर्माण करने के लिए अंतर्निहित फ़ंक्शन का उपयोग करें जो "सेट" या "प्राप्त" हो सकता है।
  3. ध्यान दें कि propertyफ़ंक्शन के पहले दो पैरामीटर नामित हैं fsetऔर fget
  4. इस तथ्य का उपयोग करें कि हमने अपने स्वयं के गेटटर और सेटर के लिए इन नामों को चुना है और propertyफ़ंक्शन के मापदंडों को पारित करने के लिए उस दायरे की सभी स्थानीय परिभाषाओं पर लागू ** (डबल तारांकन) का उपयोग करके एक कीवर्ड-शब्दकोश बनाएं।

11
दस्तावेज़ के आधार पर AttributeErrorऔर TypeError, मुझे लगता है कि उठाया गया अपवाद एक नई त्रुटि होनी चाहिए, जिसे मैंने नामकरण ConstantErrorया ऐसा कुछ प्रस्तावित किया है, जो एक उपवर्ग है TypeError। डॉक्स में वह खंड जो मुझे लगता है कि बनाता है: docs.python.org/2/library/exception.html
ArtOfWarfare

3
मैं इस कोड से हैरान हूं। क्यों FOO () और BAR () तरीके फ़ॉन्ट में एक तर्क के रूप में स्व है? मेरा IDE लाल ("संकलन" त्रुटि) कोष्ठक को रेखांकित करता है। मैं इसमें खुद को डालने के लिए थक गया लेकिन फिर मुझे एक त्रुटि मिली।
user3770060

10
इन लंबाई पर जाने से अजगर भाषा में स्पष्ट कमी को रेखांकित करता है। उन्होंने पायथन 3 में इसे जोड़ने की आवश्यकता क्यों महसूस नहीं की। 3. मैं विश्वास नहीं कर सकता कि किसी ने भी इसका सुझाव नहीं दिया है और मैं बस कुछ समिति के पीछे तर्क नहीं देख सकता हूं कि नाह, स्थिरांक? नाह। '
एंड्रयू एस

8
और आपका समाधान अभी भी एक निर्धारित अजगर प्रोग्रामर द्वारा संशोधित किया जा सकता हैCONST.__dict__['FOO'] = 7
पिपरी

11
@Oscarmith, मुझे लगता है कि यह 'स्व दस्तावेज कोड' डिजाइन में सुधार करेगा। जब मैं कोड में स्पष्ट करता हूं कि कुछ मूल्य नहीं बदल सकते हैं, तो सभी स्रोत कोड को पढ़ने और यह समझने में आसान है कि कुछ मूल्य कभी नहीं बदलते हैं। इसके अलावा, यह किसी के मूल्य को बदलने की संभावना को रोकता है जो कि, अच्छी तरह से, स्थिर होना चाहिए। याद रखें: स्पष्ट निहितार्थ से बेहतर है।
गैब्रियल

112

पायथन में भाषा को लागू करने के बजाय, लोग __methodनिजी तरीकों के लिए नामकरण सम्मेलनों का उपयोग करते हैं और _methodसंरक्षित तरीकों के लिए उपयोग करते हैं।

तो उसी तरीके से आप बस स्थिरांक को सभी कैप्स जैसे घोषित कर सकते हैं

MY_CONSTANT = "one"

यदि आप चाहते हैं कि यह स्थिरांक कभी न बदले, तो आप विशेषता एक्सेस में हुक कर सकते हैं और ट्रिक्स कर सकते हैं, लेकिन एक सरल दृष्टिकोण एक फ़ंक्शन घोषित करना है

def MY_CONSTANT():
    return "one"

केवल समस्या हर जगह है आपको MY_CONSTANT () करना होगा, लेकिन फिर MY_CONSTANT = "one"से अजगर (आमतौर पर) में सही तरीका है।

आप स्थिरांक बनाने के लिए नामपट्ट का भी उपयोग कर सकते हैं :

>>> from collections import namedtuple
>>> Constants = namedtuple('Constants', ['pi', 'e'])
>>> constants = Constants(3.14, 2.718)
>>> constants.pi
3.14
>>> constants.pi = 3
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: can't set attribute

17
def MY_CONSTANT(): return "one"किसी को करना बंद नहीं होगा, बाद में कोड में, कर MY_CONSTANT = "two"(या फ़ंक्शन redeclaring)।
मैथ्यू Schinckel

6
@MatthewSchinckel यह कन्वेंशन के बारे में है, MY_CONSTANT बदलने से भी MY_CONSTANT () का उपयोग नहीं बदलेगा, लेकिन एरर फेकेंगे, और अजगर में अगर आप चाहते हैं कि आप कुछ भी बदल सकें, तो कोई भी चालाक चाल आपकी रक्षा नहीं कर सकती।
अनुराग उनियाल

3
नामांकित दृष्टिकोण लाने के लिए धन्यवाद। निश्चित रूप से अभिनव। आपको यहाँ मेरी "टिप्पणी" प्रासंगिक लग सकती है।
रायलू

@MatthewSchinckel आप अजगर में किसी भी चीज़ को फिर से परिभाषित कर सकते हैं, इसलिए यह वास्तव में एक अच्छा बिंदु नहीं है।
cslotty

@MatthewSchinckel विचार लिखने के लिए नहीं है MY_CONSTANT = MY_CONSTANT(), बल्कि MY_CONSTANT()निरंतर के रूप में उपयोग करने के लिए है। बेशक, यह। लेकिन यह ठीक है और अजगर सिद्धांत "हम सभी यहां वयस्क हैं" के साथ बहुत अधिक है - अर्थात डेवलपर को एक नियम को ओवरराइड करने का निर्णय लेने के लिए शायद ही मना किया जाएगा जब उनके पास अच्छे कारण हैं और जानते हैं कि वे क्या कर रहे हैं।
jonathan.scholbach

69

मैंने हाल ही में इसके लिए एक बहुत ही सफल अद्यतन पाया है जो स्वचालित रूप से सार्थक त्रुटि संदेश उठाता है और इसके माध्यम से पहुंच को रोकता है __dict__:

class CONST(object):
    __slots__ = ()
    FOO = 1234

CONST = CONST()

# ----------

print(CONST.FOO)    # 1234

CONST.FOO = 4321              # AttributeError: 'CONST' object attribute 'FOO' is read-only
CONST.__dict__['FOO'] = 4321  # AttributeError: 'CONST' object has no attribute '__dict__'
CONST.BAR = 5678              # AttributeError: 'CONST' object has no attribute 'BAR'

हम खुद को एक उदाहरण के रूप में परिभाषित करते हैं और फिर यह सुनिश्चित करने के लिए स्लॉट का उपयोग करते हैं कि कोई अतिरिक्त विशेषता नहीं जोड़ी जा सकती है। यह __dict__एक्सेस रूट को भी हटा देता है । बेशक, पूरी वस्तु अभी भी पुनर्परिभाषित की जा सकती है।

संपादित करें - मूल समाधान

मैं शायद यहाँ एक चाल याद आ रही है, लेकिन यह मेरे लिए काम करने लगता है:

class CONST(object):
    FOO = 1234

    def __setattr__(self, *_):
        pass

CONST = CONST()

#----------

print CONST.FOO    # 1234

CONST.FOO = 4321
CONST.BAR = 5678

print CONST.FOO    # Still 1234!
print CONST.BAR    # Oops AttributeError

उदाहरण बनाने से मैजिक __setattr__विधि को FOOवैरिएबल को सेट करने और इंटरसेप्ट करने का प्रयास करने की अनुमति मिलती है । यदि आप चाहते हैं तो आप यहां एक अपवाद फेंक सकते हैं। वर्ग के नाम पर इंस्टेंटेटिंग को सीधे क्लास के माध्यम से एक्सेस करने से रोकता है।

यह एक मूल्य के लिए कुल दर्द है, लेकिन आप अपनी CONSTवस्तु के लिए बहुत कुछ संलग्न कर सकते हैं । एक उच्च वर्ग के होने के बाद, कक्षा का नाम भी थोड़ा शॉर्टलिस्ट लगता है, लेकिन मुझे लगता है कि यह कुल मिलाकर काफी सफल है।


11
यह सबसे अच्छा और सबसे स्पष्ट जवाब है, क्योंकि इसमें सबसे कम "तंत्र" है, लेकिन सबसे अधिक कार्यक्षमता है। एक अपवाद उठाना महत्वपूर्ण है, हालांकि ... विकल्प नहीं है।
एरिक एरोनिटी

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

क्या अफ़सोस है कि आपको अभी भी इस CONST.उपसर्ग की ज़रूरत है मल्टी-मॉड्यूल स्थितियों में भी यह जटिल होने वाला है।
अल्फ

1
मुझे लगता है कि आम तौर पर आप कुछ भी संबंधित बंडलों में समूह के सदस्यों को उस स्थिति में चाहते हैं (बजाय एक विशाल CONST ऑब्जेक्ट के), इसलिए यह शायद ऐसी बुरी बात नहीं है।
जॉन बेट्स

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

34

अजगर में स्थिरांक नहीं होते हैं।

शायद सबसे आसान विकल्प इसके लिए एक फ़ंक्शन को परिभाषित करना है:

def MY_CONSTANT():
    return 42

MY_CONSTANT() अब एक निरंतर की सभी कार्यक्षमता है (प्लस कुछ कष्टप्रद ब्रेसिज़)।


1
मैं सिर्फ इस सुझाव को जोड़ना चाहता था, लेकिन सौभाग्य से मैंने कम-रेटेड उत्तरों को नीचे स्क्रॉल किया। मुझे उम्मीद है कि इसे आगे बढ़ाया जाएगा और मैं पूरी तरह से सहमत हूं कि इसमें निरंतरता की सभी कार्यक्षमता है और यह बहुत सरल और सीधा है। सभी परिष्कृत समाधानों में बॉयलरप्लेट कोड की मात्रा को देखते हुए मुझे ब्रेसिज़ अपेक्षाकृत अननोइंग लगता है।
याकूब

1
यह सबसे सरल उत्तर है, हालांकि यह ध्यान दिया जाना चाहिए कि इसमें कुछ ओवरहेड है और यह रिटर्न वैल्यू को संशोधित करने वाले बेवकूफों को बंद नहीं करेगा। यह स्रोत को बदलने वाली रेखा के आगे कोड को रोक देगा
MrMesees

@Mresees रिटर्न मान को संशोधित करता है? क्या आप स्रोत को संपादित करना चाहते हैं? लेकिन इससे आप C ++ में भी सुरक्षित नहीं हैं, जहाँ स्थिरांक (जैसे constexpr) वास्तविक कठोर स्थिरांक हैं।
रुस्लान

@Ruslan मेरा क्या मतलब था कि चूंकि अजगर के पास कोई बाधा नहीं है, यह बाहरी संदर्भ में वापस आने के बाद संपादित किए जा रहे मूल्य को रोक नहीं पाएगा। इस उदाहरण में जमे हुए राज्य को लागू करने के लिए 42 से कुछ भी नहीं किया गया है।
MrMesees

20

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

>>> from named_constants import Constants
>>> class Colors(Constants):
...     black = 0
...     red = 1
...     white = 15
...
>>> c = Colors.black
>>> c == 0
True
>>> c
Colors.black
>>> c.name()
'black'
>>> Colors(0) is c
True

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

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


3
मुझे GitHub पर आपका कार्यान्वयन पसंद है। मैं एक मूल वर्ग लिखने के लिए लगभग तैयार था जिसने रिवर्स लुकअप कार्यक्षमता को लागू किया था, लेकिन मुझे लगता है कि आपने ऐसा किया है और अधिक!
केर

धन्यवाद, @ केर, यह पहली प्रतिक्रिया है जो मुझे मिली और मुझे खुशी हुई। :-)
hans_meine

बहुत बढ़िया। मैंने बस यही कोशिश की। इस विकल्प के रूप में अच्छा लगा। हालाँकि मैंने यह तय नहीं किया है कि मैं केवल पढ़ने के बजाय केवल पढ़ने के लिए पर्याप्त पहलू की परवाह करता हूँ def enum(**enums): return type('Enum', (), enums)Numbers = enum(ONE=1, TWO=2, THREE='three'), के अनुसार stackoverflow.com/a/1695250/199364 , अनुभाग "पहले के संस्करणों में ..."
टूलमेकरसर्व

19

गुण स्थिरांक बनाने का एक तरीका है। आप इसे गटर प्रॉपर्टी घोषित करके कर सकते हैं, लेकिन सेटर को अनदेखा कर सकते हैं। उदाहरण के लिए:

class MyFinalProperty(object):

    @property
    def name(self):
        return "John"

आप एक लेख पर नज़र डाल सकते हैं जो मैंने पायथन गुणों का उपयोग करने के लिए और अधिक तरीके खोजने के लिए लिखा है।


मूल्यवान समाधान के तहत। मैंने इस पृष्ठ को खोजने के बाद इसे लागू किया है (इस उत्तर को नहीं) और पहले से न होने पर इसे जोड़ने के लिए वापस चक्कर लगाया। मैं इस उत्तर की उपयोगिता को रेखांकित करना चाहता था।
मार्क

18

संपादित करें: पायथन 3 के लिए जोड़ा गया नमूना कोड

नोट: यह अन्य उत्तर ऐसा लगता है जैसे यह निम्नलिखित (अधिक सुविधाओं के साथ) के समान अधिक संपूर्ण कार्यान्वयन प्रदान करता है।

सबसे पहले, एक मेटाक्लस बनाएं :

class MetaConst(type):
    def __getattr__(cls, key):
        return cls[key]

    def __setattr__(cls, key, value):
        raise TypeError

यह स्टैटिक्स गुणों को बदलने से रोकता है। फिर एक और वर्ग बनाएं जो उस मेटाक्लास का उपयोग करता है:

class Const(object):
    __metaclass__ = MetaConst

    def __getattr__(self, name):
        return self[name]

    def __setattr__(self, name, value):
        raise TypeError

या, यदि आप पायथन 3 का उपयोग कर रहे हैं:

class Const(object, metaclass=MetaConst):
    def __getattr__(self, name):
        return self[name]

    def __setattr__(self, name, value):
        raise TypeError

यह उदाहरणों को बदलने से रोकता है। इसका उपयोग करने के लिए, इनहेरिट करें:

class MyConst(Const):
    A = 1
    B = 2

अब प्रॉप्स, सीधे या उदाहरण के माध्यम से एक्सेस किया जाना चाहिए, स्थिर होना चाहिए:

MyConst.A
# 1
my_const = MyConst()
my_const.A
# 1

MyConst.A = 'changed'
# TypeError
my_const.A = 'changed'
# TypeError

यहाँ ऊपर कार्रवाई में एक उदाहरण है। यहाँ पायथन 3 के लिए एक और उदाहरण दिया गया है।


10

प्रभावी रूप से एक स्थिरांक बनाने के लिए आप एक नामित नाम का उपयोग कर सकते हैं जो जावा में स्थैतिक अंतिम चर के समान काम करता है (एक जावा "स्थिरांक")। के रूप में workarounds जाने, यह सुंदर की तरह है। (अधिक सुंदर दृष्टिकोण केवल पायथन भाषा को बेहतर बनाने के लिए होगा --- किस तरह की भाषा आपको पुनर्परिभाषित करने देती है math.pi? - लेकिन मैं इसे स्वीकार करता हूं।)

(जैसा कि मैं इसे लिखता हूं, मुझे नामित नाम के इस प्रश्न का एक और उत्तर मिलता है, लेकिन मैं यहां जारी रखूंगा क्योंकि मैं एक वाक्यविन्यास दिखाऊंगा कि जावा में आप क्या उम्मीद करेंगे और अधिक बारीकी से बताएंगे, क्योंकि नाम बनाने की कोई आवश्यकता नहीं है नाम टाइप करने के लिए टाइप करें।

अपने उदाहरण के बाद, आपको याद होगा कि जावा में हमें कुछ वर्ग के अंदर स्थिरांक को परिभाषित करना चाहिए ; क्योंकि आपने कक्षा के नाम का उल्लेख नहीं किया है, इसलिए इसे कॉल करें Foo। यहाँ जावा वर्ग है:

public class Foo {
  public static final String CONST_NAME = "Name";
}

यहाँ बराबर पायथन है।

from collections import namedtuple
Foo = namedtuple('_Foo', 'CONST_NAME')('Name')

जो मुख्य बिंदु मैं यहां जोड़ना चाहता हूं, वह यह है कि आपको एक अलग Fooप्रकार की जरूरत नहीं है ("अनाम नाम का टुपल" अच्छा होगा, भले ही यह एक ऑक्सीमोरोन जैसा लगता है), इसलिए हम अपने नामित नाम को रखते हैं, ताकि _Fooउम्मीद है कि यह नहीं होगा मॉड्यूल आयात करने के लिए बच।

यहां दूसरा बिंदु यह है कि हम तुरंत इसे कॉल करते हुए, nametuple का एक उदाहरण बनाते हैंFoo ; इसे अलग चरण में करने की आवश्यकता नहीं है (जब तक आप नहीं चाहते हैं)। अब आप जावा में क्या कर सकते हैं:

>>> Foo.CONST_NAME
'Name'

लेकिन आप इसे असाइन नहीं कर सकते:

>>> Foo.CONST_NAME = 'bar'

AttributeError: can't set attribute

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

ध्यान दें कि दुर्भाग्य से (यह अभी भी पायथन है), आप संपूर्ण Fooअसाइनमेंट को पूरी तरह से मिटा सकते हैं:

>>> Foo = 'bar'

(Facepalm)

लेकिन कम से कम हम Foo.CONST_NAMEमूल्य को बदलने से रोक रहे हैं , और यह कुछ भी नहीं से बेहतर है। सौभाग्य।


नामांकित दृष्टिकोण लाने के लिए धन्यवाद। निश्चित रूप से अभिनव। आपको यहाँ मेरी "टिप्पणी" प्रासंगिक लग सकती है।
रायलू

10

पीईपी 591 में 'फाइनल' क्वालिफायर है। प्रवर्तन प्रकार चेकर के लिए नीचे है।

तो आप कर सकते हैं:

MY_CONSTANT: Final = 12407

नोट: Final कीवर्ड केवल पायथन 3.8 संस्करण के लिए लागू है


9

यहां एक "कॉन्स्टेंट" वर्ग का कार्यान्वयन है, जो केवल-पढ़ने (निरंतर) विशेषताओं के साथ उदाहरण बनाता है। ईजी को Nums.PIएक मूल्य प्राप्त करने के लिए उपयोग किया जा सकता है जिसे इसके रूप में आरंभीकृत किया गया है 3.14159, और Nums.PI = 22एक अपवाद उठाता है।

# ---------- Constants.py ----------
class Constants(object):
    """
    Create objects with read-only (constant) attributes.
    Example:
        Nums = Constants(ONE=1, PI=3.14159, DefaultWidth=100.0)
        print 10 + Nums.PI
        print '----- Following line is deliberate ValueError -----'
        Nums.PI = 22
    """

    def __init__(self, *args, **kwargs):
        self._d = dict(*args, **kwargs)

    def __iter__(self):
        return iter(self._d)

    def __len__(self):
        return len(self._d)

    # NOTE: This is only called if self lacks the attribute.
    # So it does not interfere with get of 'self._d', etc.
    def __getattr__(self, name):
        return self._d[name]

    # ASSUMES '_..' attribute is OK to set. Need this to initialize 'self._d', etc.
    #If use as keys, they won't be constant.
    def __setattr__(self, name, value):
        if (name[0] == '_'):
            super(Constants, self).__setattr__(name, value)
        else:
            raise ValueError("setattr while locked", self)

if (__name__ == "__main__"):
    # Usage example.
    Nums = Constants(ONE=1, PI=3.14159, DefaultWidth=100.0)
    print 10 + Nums.PI
    print '----- Following line is deliberate ValueError -----'
    Nums.PI = 22

@MikeGraham के फ्रोजनडिक्ट के लिए धन्यवाद , जिसे मैंने शुरुआती बिंदु के रूप में इस्तेमाल किया। परिवर्तित, इसलिए उपयोग के बजाय Nums['ONE']वाक्य रचना है Nums.ONE

और @ रौफियो के जवाब के लिए धन्यवाद, विचार के लिए __ सेटट्रा __ को ओवरराइड करना।

या अधिक कार्यक्षमता वाले कार्यान्वयन के लिए, GHHub पर @Hans_meine के name_constants देखें


2
पाइथन वयस्कों की सहमति की भाषा है। इस तरह की किसी चीज से कोई सुरक्षा नहीं है। Nums._d['PI'] = 22 भाषा खुद को चीजों को गैर-उत्परिवर्तनों के रूप में चिह्नित करने का कोई तरीका प्रदान नहीं करती है, मेरा मानना ​​है।
अजय एम

8

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

my_tuple = (0 """Or any other value""",)

इस चर के मूल्य की जांच करने के लिए, इसके समान कुछ का उपयोग करें:

if my_tuple[0] == 0:
    #Code goes here

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


7

मैं एक ऐसी कक्षा बनाऊंगा जो __setattr__बेस ऑब्जेक्ट क्लास की विधि को ओवरराइड करती है और मेरे कॉन्स्टेंट को उसी के साथ लपेटती है, ध्यान दें कि मैं pyonon 2.7 का उपयोग कर रहा हूं:

class const(object):
    def __init__(self, val):
        super(const, self).__setattr__("value", val)
    def __setattr__(self, name, val):
        raise ValueError("Trying to change a constant value", self)

एक तार लपेटने के लिए:

>>> constObj = const("Try to change me")
>>> constObj.value
'Try to change me'
>>> constObj.value = "Changed"
Traceback (most recent call last):
   ...
ValueError: Trying to change a constant value
>>> constObj2 = const(" or not")
>>> mutableObj = constObj.value + constObj2.value
>>> mutableObj #just a string
'Try to change me or not'

यह बहुत आसान है, लेकिन अगर आप अपने कॉन्स्टेंट का उपयोग उसी तरह करना चाहते हैं जैसे आप एक नॉन-कॉन्स्टेंट ऑब्जेक्ट (constObj.value का उपयोग किए बिना) करते हैं, तो यह थोड़ा अधिक गहन होगा। यह संभव है कि यह समस्याएं पैदा कर सकता है, इसलिए यह .valueदिखाने के लिए रखने के लिए सबसे अच्छा हो सकता है और यह जान लें कि आप स्थिरांक के साथ ऑपरेशन कर रहे हैं (शायद सबसे 'पायथोनिक' तरीके से नहीं)।


दिलचस्प दृष्टिकोण के लिए +1। हालांकि पहले से प्रदान किए गए उत्तरों के रूप में साफ नहीं। और यहां तक ​​कि सबसे आसान पहले सुझाए गए समाधान def ONE(): return 1का उपयोग ONE()इस उत्तर की तुलना में आसान है ONE.value
टूलमेकरसेव

7

दुर्भाग्य से अजगर के पास अभी तक कोई स्थिरांक नहीं है और यह शर्मनाक है। ES6 ने जावास्क्रिप्ट ( https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/const ) में पहले से ही समर्थन स्थिरांक जोड़े हैं क्योंकि यह किसी भी प्रोग्रामिंग भाषा में बहुत उपयोगी चीज है। जैसा कि पायथन समुदाय में अन्य उत्तरों में कहा गया है - कॉन्स्टेंट्स के रूप में कन्वेंशन - यूजर अपरकेस वैरिएबल का उपयोग करते हैं, लेकिन यह कोड में मनमानी त्रुटियों से रक्षा नहीं करता है। यदि आप चाहें, तो आपको अगले के रूप में एकल-फ़ाइल समाधान उपयोगी हो सकता है (देखें कि यह कैसे उपयोग होता है)।

फ़ाइल constants.py

import collections


__all__ = ('const', )


class Constant(object):
    """
    Implementation strict constants in Python 3.

    A constant can be set up, but can not be changed or deleted.
    Value of constant may any immutable type, as well as list or set.
    Besides if value of a constant is list or set, it will be converted in an immutable type as next:
        list -> tuple
        set -> frozenset
    Dict as value of a constant has no support.

    >>> const = Constant()
    >>> del const.temp
    Traceback (most recent call last):
    NameError: name 'temp' is not defined
    >>> const.temp = 1
    >>> const.temp = 88
    Traceback (most recent call last):
        ...
    TypeError: Constanst can not be changed
    >>> del const.temp
    Traceback (most recent call last):
        ...
    TypeError: Constanst can not be deleted
    >>> const.I = ['a', 1, 1.2]
    >>> print(const.I)
    ('a', 1, 1.2)
    >>> const.F = {1.2}
    >>> print(const.F)
    frozenset([1.2])
    >>> const.D = dict()
    Traceback (most recent call last):
        ...
    TypeError: dict can not be used as constant
    >>> del const.UNDEFINED
    Traceback (most recent call last):
        ...
    NameError: name 'UNDEFINED' is not defined
    >>> const()
    {'I': ('a', 1, 1.2), 'temp': 1, 'F': frozenset([1.2])}
    """

    def __setattr__(self, name, value):
        """Declaration a constant with value. If mutable - it will be converted to immutable, if possible.
        If the constant already exists, then made prevent againt change it."""

        if name in self.__dict__:
            raise TypeError('Constanst can not be changed')

        if not isinstance(value, collections.Hashable):
            if isinstance(value, list):
                value = tuple(value)
            elif isinstance(value, set):
                value = frozenset(value)
            elif isinstance(value, dict):
                raise TypeError('dict can not be used as constant')
            else:
                raise ValueError('Muttable or custom type is not supported')
        self.__dict__[name] = value

    def __delattr__(self, name):
        """Deny against deleting a declared constant."""

        if name in self.__dict__:
            raise TypeError('Constanst can not be deleted')
        raise NameError("name '%s' is not defined" % name)

    def __call__(self):
        """Return all constans."""

        return self.__dict__


const = Constant()


if __name__ == '__main__':
    import doctest
    doctest.testmod()

यदि यह पर्याप्त नहीं है, तो इसके लिए पूर्ण परीक्षण देखें।

import decimal
import uuid
import datetime
import unittest

from ..constants import Constant


class TestConstant(unittest.TestCase):
    """
    Test for implementation constants in the Python
    """

    def setUp(self):

        self.const = Constant()

    def tearDown(self):

        del self.const

    def test_create_constant_with_different_variants_of_name(self):

        self.const.CONSTANT = 1
        self.assertEqual(self.const.CONSTANT, 1)
        self.const.Constant = 2
        self.assertEqual(self.const.Constant, 2)
        self.const.ConStAnT = 3
        self.assertEqual(self.const.ConStAnT, 3)
        self.const.constant = 4
        self.assertEqual(self.const.constant, 4)
        self.const.co_ns_ta_nt = 5
        self.assertEqual(self.const.co_ns_ta_nt, 5)
        self.const.constant1111 = 6
        self.assertEqual(self.const.constant1111, 6)

    def test_create_and_change_integer_constant(self):

        self.const.INT = 1234
        self.assertEqual(self.const.INT, 1234)
        with self.assertRaisesRegexp(TypeError, 'Constanst can not be changed'):
            self.const.INT = .211

    def test_create_and_change_float_constant(self):

        self.const.FLOAT = .1234
        self.assertEqual(self.const.FLOAT, .1234)
        with self.assertRaisesRegexp(TypeError, 'Constanst can not be changed'):
            self.const.FLOAT = .211

    def test_create_and_change_list_constant_but_saved_as_tuple(self):

        self.const.LIST = [1, .2, None, True, datetime.date.today(), [], {}]
        self.assertEqual(self.const.LIST, (1, .2, None, True, datetime.date.today(), [], {}))

        self.assertTrue(isinstance(self.const.LIST, tuple))

        with self.assertRaisesRegexp(TypeError, 'Constanst can not be changed'):
            self.const.LIST = .211

    def test_create_and_change_none_constant(self):

        self.const.NONE = None
        self.assertEqual(self.const.NONE, None)
        with self.assertRaisesRegexp(TypeError, 'Constanst can not be changed'):
            self.const.NONE = .211

    def test_create_and_change_boolean_constant(self):

        self.const.BOOLEAN = True
        self.assertEqual(self.const.BOOLEAN, True)
        with self.assertRaisesRegexp(TypeError, 'Constanst can not be changed'):
            self.const.BOOLEAN = False

    def test_create_and_change_string_constant(self):

        self.const.STRING = "Text"
        self.assertEqual(self.const.STRING, "Text")

        with self.assertRaisesRegexp(TypeError, 'Constanst can not be changed'):
            self.const.STRING += '...'

        with self.assertRaisesRegexp(TypeError, 'Constanst can not be changed'):
            self.const.STRING = 'TEst1'

    def test_create_dict_constant(self):

        with self.assertRaisesRegexp(TypeError, 'dict can not be used as constant'):
            self.const.DICT = {}

    def test_create_and_change_tuple_constant(self):

        self.const.TUPLE = (1, .2, None, True, datetime.date.today(), [], {})
        self.assertEqual(self.const.TUPLE, (1, .2, None, True, datetime.date.today(), [], {}))

        with self.assertRaisesRegexp(TypeError, 'Constanst can not be changed'):
            self.const.TUPLE = 'TEst1'

    def test_create_and_change_set_constant(self):

        self.const.SET = {1, .2, None, True, datetime.date.today()}
        self.assertEqual(self.const.SET, {1, .2, None, True, datetime.date.today()})

        self.assertTrue(isinstance(self.const.SET, frozenset))

        with self.assertRaisesRegexp(TypeError, 'Constanst can not be changed'):
            self.const.SET = 3212

    def test_create_and_change_frozenset_constant(self):

        self.const.FROZENSET = frozenset({1, .2, None, True, datetime.date.today()})
        self.assertEqual(self.const.FROZENSET, frozenset({1, .2, None, True, datetime.date.today()}))

        with self.assertRaisesRegexp(TypeError, 'Constanst can not be changed'):
            self.const.FROZENSET = True

    def test_create_and_change_date_constant(self):

        self.const.DATE = datetime.date(1111, 11, 11)
        self.assertEqual(self.const.DATE, datetime.date(1111, 11, 11))

        with self.assertRaisesRegexp(TypeError, 'Constanst can not be changed'):
            self.const.DATE = True

    def test_create_and_change_datetime_constant(self):

        self.const.DATETIME = datetime.datetime(2000, 10, 10, 10, 10)
        self.assertEqual(self.const.DATETIME, datetime.datetime(2000, 10, 10, 10, 10))

        with self.assertRaisesRegexp(TypeError, 'Constanst can not be changed'):
            self.const.DATETIME = None

    def test_create_and_change_decimal_constant(self):

        self.const.DECIMAL = decimal.Decimal(13123.12312312321)
        self.assertEqual(self.const.DECIMAL, decimal.Decimal(13123.12312312321))

        with self.assertRaisesRegexp(TypeError, 'Constanst can not be changed'):
            self.const.DECIMAL = None

    def test_create_and_change_timedelta_constant(self):

        self.const.TIMEDELTA = datetime.timedelta(days=45)
        self.assertEqual(self.const.TIMEDELTA, datetime.timedelta(days=45))

        with self.assertRaisesRegexp(TypeError, 'Constanst can not be changed'):
            self.const.TIMEDELTA = 1

    def test_create_and_change_uuid_constant(self):

        value = uuid.uuid4()
        self.const.UUID = value
        self.assertEqual(self.const.UUID, value)

        with self.assertRaisesRegexp(TypeError, 'Constanst can not be changed'):
            self.const.UUID = []

    def test_try_delete_defined_const(self):

        self.const.VERSION = '0.0.1'
        with self.assertRaisesRegexp(TypeError, 'Constanst can not be deleted'):
            del self.const.VERSION

    def test_try_delete_undefined_const(self):

        with self.assertRaisesRegexp(NameError, "name 'UNDEFINED' is not defined"):
            del self.const.UNDEFINED

    def test_get_all_defined_constants(self):

        self.assertDictEqual(self.const(), {})

        self.const.A = 1
        self.assertDictEqual(self.const(), {'A': 1})

        self.const.B = "Text"
        self.assertDictEqual(self.const(), {'A': 1, 'B': "Text"})

लाभ: 1. पूरी परियोजना के लिए सभी स्थिरांक तक पहुँचना 2. स्थिरांक के मूल्यों के लिए सख्त नियंत्रण

कमी: 1. कस्टम प्रकार और 'तानाशाह' के लिए समर्थन नहीं

टिप्पणियाँ:

  1. Python3.4 और Python3.5 के साथ परीक्षण किया गया (मैं इसके लिए 'विषाक्त' का उपयोग कर रहा हूं)

  2. परीक्षण वातावरण:

$ uname -a
Linux wlysenko-Aspire 3.13.0-37-generic #64-Ubuntu SMP Mon Sep 22 21:28:38 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux

नामित ट्यूपलों को स्वचालित रूप से परिवर्तित करके आप इसे थोड़ा सुधार सकते हैं
पीटर शॉर्न

6

"स्थिरांक" घोषित करने का पाइथोनिक तरीका मूल रूप से एक मॉड्यूल स्तर चर है:

RED = 1
GREEN = 2
BLUE = 3

और फिर अपनी कक्षाओं या कार्यों को लिखें। चूंकि स्थिरांक लगभग हमेशा पूर्णांक होते हैं, और वे पायथन में भी अपरिवर्तनीय हैं, आपके पास इसे बदलने की बहुत कम संभावना है।

जब तक, निश्चित रूप से, यदि आप स्पष्ट रूप से सेट करते हैं RED = 2


21
हां, लेकिन "स्पष्ट रूप से सेट " करने की क्षमता को अवरुद्ध करना RED = 2(अन्य भाषाओं में) एक चर नाम को "स्थिर" घोषित करने में सक्षम होने का संपूर्ण लाभ है!
टूलमेकरसेव

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

@ केविन: " क्या आपको लाभ मिलेगा ... ", staticएक वर्ग के सभी उदाहरणों के लिए मूल्य के लिए एक ही भंडारण है? जब तक कि वास्तव में एक स्थिर / वर्ग चर घोषित करने की संभावना नहीं है।
मिनट

8
मूल मुद्दा यह है कि कुछ इसे एक ऐसे मूल्य के रूप में देख सकते हैं जो सत्य का एक स्रोत है, जिसे बदलने में असमर्थ है, और इसे जादू के मूल्यों को पेश करने के बजाय अपने कोड में सत्य के स्रोत के रूप में उपयोग करते हैं (जिसे मैं पायथन में बहुत अधिक देखता हूं) - और अन्य इसे कुछ ऐसी चीज़ों के रूप में देख सकते हैं जिन्हें वे अपनी इच्छा से बदलने की अनुमति देते हैं। जब कोई वैश्विक चर बदलता है, और आप यह नहीं बता सकते हैं कि यह कहां बदल गया है, और एप्लिकेशन क्रैश हो जाता है क्योंकि "लाल" के बजाय RED = "ब्लू", आप एक पूरी तरह से अनावश्यक समस्या का परिचय दे रहे हैं जो पहले से ही इतनी आसानी से हल हो गई है और सार्वभौमिक रूप से समझा जाता है।
डैगरूम

5

हम एक डिस्क्रिप्टर ऑब्जेक्ट बना सकते हैं।

class Constant:
  def __init__(self,value=None):
    self.value = value
  def __get__(self,instance,owner):
    return self.value
  def __set__(self,instance,value):
    raise ValueError("You can't change a constant")

1) यदि हम उदाहरण के स्तर पर स्थिरांक के साथ काम करना चाहते हैं तो:

class A:
  NULL = Constant()
  NUM = Constant(0xFF)

class B:
  NAME = Constant('bar')
  LISTA = Constant([0,1,'INFINITY'])

>>> obj=A()
>>> print(obj.NUM)  #=> 255
>>> obj.NUM =100

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: You can't change a constant

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

# metaclass of my class Foo
class FooMeta(type): pass

# class Foo
class Foo(metaclass=FooMeta): pass

# I create constants in my metaclass
FooMeta.NUM = Constant(0xff)
FooMeta.NAME = Constant('FOO')

>>> Foo.NUM   #=> 255
>>> Foo.NAME  #=> 'FOO'
>>> Foo.NUM = 0 #=> ValueError: You can't change a constant

अगर मैं फू का एक उपवर्ग बनाऊं, तो यह वर्ग उन्हें संशोधित करने की संभावना के बिना निरंतर विरासत में मिलेगा

class Bar(Foo): pass

>>> Bar.NUM  #=> 255
>>> Bar.NUM = 0  #=> ValueError: You can't change a constant

4

पायथन डिक्शनरी परस्पर हैं, इसलिए उन्हें स्थिरांक घोषित करने का एक अच्छा तरीका नहीं लगता है:

>>> constants = {"foo":1, "bar":2}
>>> print constants
{'foo': 1, 'bar': 2}
>>> constants["bar"] = 3
>>> print constants
{'foo': 1, 'bar': 3}

4

यहाँ एक चाल है यदि आप स्थिरांक चाहते हैं और उनके मूल्यों की परवाह नहीं करते हैं:

बस खाली वर्गों को परिभाषित करें।

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

class RED: 
    pass
class BLUE: 
    pass

4

अजगर में, एक स्थिरांक सभी राजधानियों में एक नाम के साथ एक चर है, अंडरस्कोर वर्ण द्वारा अलग किए गए शब्दों के साथ,

जैसे

DAYS_IN_WEEK = 7

मान परिवर्तनशील है, जैसा कि आप इसे बदल सकते हैं। लेकिन नाम के लिए दिए गए नियम आपको बताते हैं कि आप एक स्थिर व्यक्ति हैं, आप ऐसा क्यों करेंगे? मेरा मतलब है, यह आपका कार्यक्रम है!

यह पूरे अजगर में लिया गया दृष्टिकोण है। privateउसी कारण से कोई कीवर्ड नहीं है । एक अंडरस्कोर के साथ नाम को उपसर्ग करें और आप जानते हैं कि यह निजी होना है। कोड नियम को तोड़ सकता है .... जैसा कि एक प्रोग्रामर वैसे भी निजी कीवर्ड को हटा सकता है।

पायथन एक constकीवर्ड जोड़ सकता था ... लेकिन एक प्रोग्रामर कीवर्ड हटा सकता है और फिर स्थिर को बदल सकता है यदि वे चाहते हैं, लेकिन ऐसा क्यों करते हैं? यदि आप नियम को तोड़ना चाहते हैं, तो आप वैसे भी नियम बदल सकते हैं। लेकिन अगर नाम इरादे को स्पष्ट करता है तो नियम को तोड़ने की जहमत क्यों?

हो सकता है कि कुछ इकाई परीक्षण है जहां मूल्य में परिवर्तन लागू करने के लिए समझ में आता है? यह देखने के लिए कि वास्तविक दुनिया में 8 दिन के सप्ताह के लिए क्या होता है, हालांकि सप्ताह में दिनों की संख्या को बदला नहीं जा सकता है। यदि भाषा ने आपको एक अपवाद बनाने से रोक दिया, यदि नियम को तोड़ने के लिए सिर्फ एक ही मामला है ... तो आपको इसे एक निरंतर के रूप में घोषित करना बंद करना होगा, भले ही यह अभी भी आवेदन में एक स्थिर है, और वहां बस यह एक परीक्षा का मामला है जो देखता है कि क्या होता है अगर इसे बदल दिया जाए।

सभी ऊपरी मामले का नाम बताता है कि यह एक स्थिर रहने का इरादा है। वही महत्वपूर्ण है। ऐसी भाषा नहीं जो कोड पर अड़चन डालने के लिए बाध्य हो, आपके पास वैसे भी बदलने की शक्ति है।

वह अजगर का दर्शन है।


4

ऐसा करने का कोई सही तरीका नहीं है। जैसा कि मैं समझता हूं कि अधिकांश प्रोग्रामर केवल पहचानकर्ता को पूंजीकृत करेंगे, इसलिए PI = 3.142 को आसानी से एक स्थिरांक समझा जा सकता है।

दूसरी ओर, यदि आप कुछ ऐसा चाहते हैं जो वास्तव में एक स्थिर की तरह काम करता है, तो मुझे यकीन नहीं है कि आप इसे पा लेंगे। आप जो कुछ भी करते हैं उसके साथ हमेशा "स्थिर" संपादन का कोई न कोई तरीका होगा, इसलिए यह वास्तव में एक स्थिर नहीं होगा। यहाँ एक बहुत ही सरल, गंदा उदाहरण दिया गया है:

def define(name, value):
  if (name + str(id(name))) not in globals():
    globals()[name + str(id(name))] = value

def constant(name):
  return globals()[name + str(id(name))]

define("PI",3.142)

print(constant("PI"))

ऐसा लगता है कि यह एक PHP- शैली को स्थिर बना देगा।

हकीकत में किसी को मूल्य बदलने के लिए यह सब लगता है:

globals()["PI"+str(id("PI"))] = 3.1415

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

मेरी सिफारिश है कि सिर्फ सभी झंझटों से बचना है और अपने पहचानकर्ताओं को भुनाना है। यह वास्तव में एक उचित स्थिर नहीं होगा, लेकिन फिर कुछ भी नहीं होगा।


4

नामांकित के साथ ऐसा करने का एक साफ तरीका है:

from collections import namedtuple


def make_consts(name, **kwargs):
    return namedtuple(name, kwargs.keys())(**kwargs)

उपयोग उदाहरण

CONSTS = make_consts("baz1",
                     foo=1,
                     bar=2)

इस दृष्टिकोण के साथ आप अपने स्थिरांक को नामांकित कर सकते हैं।


इसे पढ़ने वाले सभी लोगों के लिए, कृपया ध्यान रखें कि, यदि आप इनमें से किसी एक स्थिरांक के रूप में एक परिवर्तनशील वस्तु निर्धारित करते हैं, तो कोई भी इसके आंतरिक मूल्य को बदल सकता है। उदाहरण के लिए, बार = [1, 2, 3] को अनुमति देता है, तो आप निम्नानुसार कर सकते हैं: CONSTS.bar [1] = 'a' और इसे अस्वीकार नहीं किया जाएगा। इसलिए इस बारे में सावधान रहें।
जुआन इग्नासियो सेंचेज

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

4

शायद pconst पुस्तकालय आपकी मदद करेगा ( github )।

$ pip install pconst

from pconst import const
const.APPLE_PRICE = 100
const.APPLE_PRICE = 200

[Out] Constant value of "APPLE_PRICE" is not editable.


3

आप StringVar या IntVar इत्यादि का उपयोग कर सकते हैं, आपका स्थिरांक const_val है

val = 'Stackoverflow'
const_val = StringVar(val)
const.trace('w', reverse)

def reverse(*args):
    const_val.set(val)

2

आप इसके साथ कर सकते हैं collections.namedtupleऔर itertools:

import collections
import itertools
def Constants(Name, *Args, **Kwargs):
  t = collections.namedtuple(Name, itertools.chain(Args, Kwargs.keys()))
  return t(*itertools.chain(Args, Kwargs.values()))

>>> myConstants = Constants('MyConstants', 'One', 'Two', Three = 'Four')
>>> print myConstants.One
One
>>> print myConstants.Two
Two
>>> print myConstants.Three
Four
>>> myConstants.One = 'Two'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: can't set attribute

2

(यह पैराग्राफ उन उत्तरों पर यहाँ और वहाँ टिप्पणी करने के लिए था , जिनका उल्लेख किया गया है namedtuple, लेकिन यह एक टिप्पणी में फिट होने के लिए बहुत लंबा हो रहा है, इसलिए, यहाँ जाता है।)

ऊपर उल्लेख किया गया नामांकित दृष्टिकोण निश्चित रूप से नवीन है। पूर्णता की खातिर, हालांकि, इसके आधिकारिक प्रलेखन के नामांकित अनुभाग के अंत में , यह पढ़ता है:

प्रगणित स्थिरांक को टुपल्स के साथ कार्यान्वित किया जा सकता है, लेकिन सरल वर्ग घोषणा का उपयोग करना सरल और अधिक कुशल है:

class Status:
    open, pending, closed = range(3)

दूसरे शब्दों में, वास्तव में केवल-पढ़ने के व्यवहार को लागू करने के बजाय व्यावहारिक तरीके से उपयोग करने के लिए आधिकारिक प्रलेखन प्रकार। मुझे लगता है कि यह अभी तक पायथन के ज़ेन का एक और उदाहरण बन गया है :

सरल जटिल से बेहतर है।

व्यावहारिकता शुद्धता को हरा देती है।


2

यहाँ यह मुहावरों का एक संग्रह है जो मैंने पहले से उपलब्ध उत्तरों में से कुछ को बेहतर बनाने के प्रयास के रूप में बनाया है।

मुझे पता है कि निरंतर का उपयोग पायथोनिक नहीं है, और आपको घर पर ऐसा नहीं करना चाहिए!

हालाँकि, पायथन ऐसी ही एक गतिशील भाषा है! इस मंच से पता चलता है कि यह कैसे निर्माणों के निर्माण संभव है कि लगता और स्थिरांक तरह लगता है। इस उत्तर में भाषा द्वारा व्यक्त की जा सकने वाली बातों का पता लगाने का प्राथमिक उद्देश्य है।

कृपया मेरे साथ बहुत कठोर न हों :-)।

अधिक जानकारी के लिए मैंने इन मुहावरों के बारे में एक संगत ब्लॉग लिखा ।

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

स्थिरांक का एक स्थान (SpaceConstants)

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

मैं कक्षा कारखाने के उपयोग का पता लगाया एक नीति आधारित डिजाइन हमशक्ल में अजगर में लागू करने के लिए stackoverflow और यह भी एक में ऐसे ब्लॉग पोस्ट को

def SpaceConstants():
    def setattr(self, name, value):
        if hasattr(self, name):
            raise AttributeError(
                "Cannot reassign members"
            )
        self.__dict__[name] = value
    cls = type('SpaceConstants', (), {
        '__setattr__': setattr
    })
    return cls()

sc = SpaceConstants()

print(sc.x) # raise "AttributeError: 'SpaceConstants' object has no attribute 'x'"
sc.x = 2 # bind attribute x
print(sc.x) # print "2"
sc.x = 3 # raise "AttributeError: Cannot reassign members"
sc.y = {'name': 'y', 'value': 2} # bind attribute y
print(sc.y) # print "{'name': 'y', 'value': 2}"
sc.y['name'] = 'yprime' # mutable object can be changed
print(sc.y) # print "{'name': 'yprime', 'value': 2}"
sc.y = {} # raise "AttributeError: Cannot reassign members"

जमे हुए मूल्यों का एक स्थान (SpaceFrozenValues)

यह अगला मुहावरा SpaceConstants का एक संशोधन है जिसमें संदर्भित उत्परिवर्तनीय वस्तुएं जमी हुई हैं। यह कार्यान्वयन सेटट्र और गेटैट्र फ़ंक्शंस के बीच साझा किए गए क्लोजर का फायदा उठाता है। परिवर्तनशील वस्तु के मूल्य को कॉपी और चर साझा फ़ंक्शन के अंदर परिभाषित चर कैश द्वारा संदर्भित किया जाता है । यह वह बनाता है जिसे मैं किसी परिवर्तनशील वस्तु की क्लोजर प्रोटेक्टेड कॉपी कहता हूं ।

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

from copy import deepcopy

def SpaceFrozenValues():
    cache = {}
    def setattr(self, name, value):
        nonlocal cache
        if name in cache:
            raise AttributeError(
                "Cannot reassign members"
            )
        cache[name] = deepcopy(value)
    def getattr(self, name):
        nonlocal cache
        if name not in cache:
            raise AttributeError(
                "Object has no attribute '{}'".format(name)
            )
        return deepcopy(cache[name])
    cls = type('SpaceFrozenValues', (),{
        '__getattr__': getattr,
        '__setattr__': setattr
    })
    return cls()

fv = SpaceFrozenValues()
print(fv.x) # AttributeError: Object has no attribute 'x'
fv.x = 2 # bind attribute x
print(fv.x) # print "2"
fv.x = 3 # raise "AttributeError: Cannot reassign members"
fv.y = {'name': 'y', 'value': 2} # bind attribute y
print(fv.y) # print "{'name': 'y', 'value': 2}"
fv.y['name'] = 'yprime' # you can try to change mutable objects
print(fv.y) # print "{'name': 'y', 'value': 2}"
fv.y = {} # raise "AttributeError: Cannot reassign members"

एक निरंतर अंतरिक्ष (ConstantSpace)

यह मुहावरा निरंतर चर या कांस्टेंटस्पेस का एक अपरिवर्तनीय नाम स्थान है । यह अद्भुत रूप में सरल जॉन बेट्स 'जवाब का एक संयोजन है stackoverflow एक साथ वर्ग कारखाने

def ConstantSpace(**args):
    args['__slots__'] = ()
    cls = type('ConstantSpace', (), args)
    return cls()

cs = ConstantSpace(
    x = 2,
    y = {'name': 'y', 'value': 2}
)

print(cs.x) # print "2"
cs.x = 3 # raise "AttributeError: 'ConstantSpace' object attribute 'x' is read-only"
print(cs.y) # print "{'name': 'y', 'value': 2}"
cs.y['name'] = 'yprime' # mutable object can be changed
print(cs.y) # print "{'name': 'yprime', 'value': 2}"
cs.y = {} # raise "AttributeError: 'ConstantSpace' object attribute 'x' is read-only"
cs.z = 3 # raise "AttributeError: 'ConstantSpace' object has no attribute 'z'"

एक जमे हुए स्थान (फ्रोजनस्पेस)

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

from copy import deepcopy

def FreezeProperty(value):
    cache = deepcopy(value)
    return property(
        lambda self: deepcopy(cache)
    )

def FrozenSpace(**args):
    args = {k: FreezeProperty(v) for k, v in args.items()}
    args['__slots__'] = ()
    cls = type('FrozenSpace', (), args)
    return cls()

fs = FrozenSpace(
    x = 2,
    y = {'name': 'y', 'value': 2}
)

print(fs.x) # print "2"
fs.x = 3 # raise "AttributeError: 'FrozenSpace' object attribute 'x' is read-only"
print(fs.y) # print "{'name': 'y', 'value': 2}"
fs.y['name'] = 'yprime' # try to change mutable object
print(fs.y) # print "{'name': 'y', 'value': 2}"
fs.y = {} # raise "AttributeError: 'FrozenSpace' object attribute 'x' is read-only"
fs.z = 3 # raise "AttributeError: 'FrozenSpace' object has no attribute 'z'"

2

पायथन में, स्थिरांक मौजूद नहीं हैं, लेकिन आप संकेत कर सकते हैं कि एक चर एक स्थिर है और इसे CONST_चर नाम की शुरुआत में जोड़कर नहीं बदला जाना चाहिए और यह कहते हुए कि यह एक टिप्पणी में एक निरंतर है:

myVariable = 0
CONST_daysInWeek = 7    # This is a constant - do not change its value.   
CONSTANT_daysInMonth = 30 # This is also a constant - do not change this value.

वैकल्पिक रूप से, आप एक फंक्शन बना सकते हैं जो एक स्थिरांक की तरह कार्य करता है:

def CONST_daysInWeek():
    return 7;

1

मेरे मामले में, मुझे एक क्रिप्टो लाइब्रेरी के कार्यान्वयन के लिए अपरिवर्तनीय बायट्रायर्स की आवश्यकता थी जिसमें कई शाब्दिक संख्याएं थीं जो मैं सुनिश्चित करना चाहता था कि वे निरंतर थे।

यह उत्तर काम करता है लेकिन बीटियर तत्वों के पुनर्मूल्यांकन का प्रयास एक त्रुटि नहीं बढ़ाता है।

def const(func):
    '''implement const decorator'''
    def fset(self, val):
        '''attempting to set a const raises `ConstError`'''
        class ConstError(TypeError):
            '''special exception for const reassignment'''
            pass

        raise ConstError

    def fget(self):
        '''get a const'''
        return func()

    return property(fget, fset)


class Consts(object):
    '''contain all constants'''

    @const
    def C1():
        '''reassignment to C1 fails silently'''
        return bytearray.fromhex('deadbeef')

    @const
    def pi():
        '''is immutable'''
        return 3.141592653589793

स्थिरांक अपरिवर्तनीय हैं, लेकिन निरंतर बायट्रियर असाइनमेंट चुपचाप विफल रहता है:

>>> c = Consts()
>>> c.pi = 6.283185307179586  # (https://en.wikipedia.org/wiki/Tau_(2%CF%80))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "consts.py", line 9, in fset
    raise ConstError
__main__.ConstError
>>> c.C1[0] = 0
>>> c.C1[0]
222
>>> c.C1
bytearray(b'\xde\xad\xbe\xef')

एक अधिक शक्तिशाली, सरल, और शायद और भी अधिक 'पाइथोनिक' दृष्टिकोण में मेमोरीव्यू ऑब्जेक्ट्स का उपयोग (बफर ऑब्जेक्ट्स <= python-2.6) शामिल है।

import sys

PY_VER = sys.version.split()[0].split('.')

if int(PY_VER[0]) == 2:
    if int(PY_VER[1]) < 6:
        raise NotImplementedError
    elif int(PY_VER[1]) == 6:
        memoryview = buffer

class ConstArray(object):
    '''represent a constant bytearray'''
    def __init__(self, init):
        '''
        create a hidden bytearray and expose a memoryview of that bytearray for
        read-only use
        '''
        if int(PY_VER[1]) == 6:
            self.__array = bytearray(init.decode('hex'))
        else:
            self.__array = bytearray.fromhex(init)

        self.array = memoryview(self.__array)

    def __str__(self):
        return str(self.__array)

    def __getitem__(self, *args, **kwargs):
       return self.array.__getitem__(*args, **kwargs)

ConstArray आइटम असाइनमेंट एक है TypeError:

>>> C1 = ConstArray('deadbeef')
>>> C1[0] = 0
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'ConstArray' object does not support item assignment
>>> C1[0]
222

1

मैं अजगर कॉन्स्ट के लिए एक उपयोग परिवाद लिखता हूं : kkconst - pypi समर्थन str, int, फ्लोट, डेटाइम

const क्षेत्र का उदाहरण इसका आधार प्रकार व्यवहार रखेगा।

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

from __future__ import print_function
from kkconst import (
    BaseConst,
    ConstFloatField,
)

class MathConst(BaseConst):
    PI = ConstFloatField(3.1415926, verbose_name=u"Pi")
    E = ConstFloatField(2.7182818284, verbose_name=u"mathematical constant")  # Euler's number"
    GOLDEN_RATIO = ConstFloatField(0.6180339887, verbose_name=u"Golden Ratio")

magic_num = MathConst.GOLDEN_RATIO
assert isinstance(magic_num, ConstFloatField)
assert isinstance(magic_num, float)

print(magic_num)  # 0.6180339887
print(magic_num.verbose_name)  # Golden Ratio

अधिक जानकारी के उपयोग आप pypi यूआरएल पढ़ सकते हैं: pypi या GitHub


1

आप एक स्थिर सरणी में एक स्थिर लपेट सकते हैं, इसे केवल लिख सकते हैं, और हमेशा इसे सूचकांक शून्य से कॉल करें।

import numpy as np

# declare a constant
CONSTANT = 'hello'

# put constant in numpy and make read only
CONSTANT = np.array([CONSTANT])
CONSTANT.flags.writeable = False
# alternatively: CONSTANT.setflags(write=0)

# call our constant using 0 index    
print 'CONSTANT %s' % CONSTANT[0]

# attempt to modify our constant with try/except
new_value = 'goodbye'
try:
    CONSTANT[0] = new_value
except:
    print "cannot change CONSTANT to '%s' it's value '%s' is immutable" % (
        new_value, CONSTANT[0])

# attempt to modify our constant producing ValueError
CONSTANT[0] = new_value



>>>
CONSTANT hello
cannot change CONSTANT to 'goodbye' it's value 'hello' is immutable
Traceback (most recent call last):
  File "shuffle_test.py", line 15, in <module>
    CONSTANT[0] = new_value
ValueError: assignment destination is read-only

बेशक यह केवल सामग्री की सुरक्षा करता है, न कि चर "CONSTANT" ही; आप अभी भी कर सकते हैं:

CONSTANT = 'foo'

और CONSTANT, हालांकि, यह जल्दी से एक टाइप-थ्रो फेंक देगा पहली बार CONSTANT[0]बाद में स्क्रिप्ट में कहा जाता है।

हालांकि ... मुझे लगता है कि अगर आप किसी बिंदु पर इसे बदल दिया है

CONSTANT = [1,2,3]

अब आपको टाइपरर नहीं मिलेगा। hmmmm ....

https://docs.scipy.org/doc/numpy/reference/generated/numpy.ndarray.setflags.html

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