2010-10-22 9 views
25

मैं कक्षा में स्थिरांक का एक सेट परिभाषित करना चाहता हूं जैसे:पायथन कक्षा में स्थिरांक परिभाषित करना, वास्तव में स्वयं की जरूरत है?

class Foo(object): 
    (NONEXISTING,VAGUE,CONFIRMED) = (0,1,2) 
    def __init__(self): 
     self.status = VAGUE 

हालांकि, मुझे

NameError: global name 'VAGUE' is not defined 

मिलता है क्या global का उपयोग किए बिना कक्षा के अंदर इन स्थिरांक को परिभाषित करने का कोई तरीका है या self.NONEXISTING = 0 आदि?

उत्तर

36

जब आप कक्षा के शरीर में नाम निर्दिष्ट करते हैं, तो आप कक्षा के गुण बना रहे हैं। आप कक्षा या सीधे या परोक्ष रूप से कक्षा का जिक्र किए बिना उन्हें संदर्भित नहीं कर सकते हैं। आप Foo.VAGUE का उपयोग अन्य उत्तरों के रूप में कर सकते हैं, या आप self.VAGUE का उपयोग कर सकते हैं। के गुणों के लिए आपको असाइन करने की आवश्यकता नहीं है।

आमतौर पर, self.VAGUE का उपयोग करके आप जो चाहते हैं उसका उपयोग करते हैं क्योंकि यह उप-वर्गों को उन सभी विधियों को पुन: कार्यान्वित किए बिना विशेषता को फिर से परिभाषित करने की अनुमति देता है - ऐसा नहीं कि यह इस विशेष उदाहरण में करने के लिए एक समझदार चीज़ जैसा लगता है, लेकिन कौन जानता है ।

7

के बजाय का प्रयास करें:

self.status = VAGUE 

इस एक:

self.status = Foo.VAGUE 

आप वर्ग

3

एक ही रास्ता वर्ग के नाम से भी पहुंच रहा है का उल्लेख करना होगा जैसे

Foo.VAGUE 

यदि एसी __init__ फ़ंक्शन, या फ़ंक्शन के अंदर केवल VAGUE का अनुमान लगाएं, इसे उस तरीके से घोषित किया जाना चाहिए जिस तरह से आप चाहते हैं।

स्वयं का उपयोग कक्षा के उदाहरण के लिए भी है।

+0

ठीक है, यह बहुत बुरा है। मुझे याद है कि आप ऐसा कुछ कर सकते थे जो मैं जावा में करने की कोशिश कर रहा था? मुझे यकीन नहीं है। – Theodor

+0

मुझे पूरा यकीन है कि आप जावा में जो कुछ भी पूछते हैं वह कर सकते हैं! – Iacks

+2

और मुझे पूरा यकीन है कि आप जावा में अन्य 9 0% चीजें नहीं कर सकते हैं जिन्हें आप करना चाहते हैं। प्रयास और प्रतिबिंब हैकिंग के लिए – aaronasterling

3

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

#!/usr/bin/python 
# -*- coding: utf-8-unix -*- 
# 
# AST hack to replace symbol reference in instance methods, 
# so it will be resolved as a reference to class variables. 
# 

import inspect, types, ast 

def trim(src): 
    lines = src.split("\n") 
    start = lines[0].lstrip() 
    n = lines[0].index(start) 
    src = "\n".join([line[n:] for line in lines]) 
    return src 

# 
# Method decorator that replaces symbol reference in a method 
# so it will use symbols in belonging class instead of the one 
# in global namespace. 
# 
def nsinclude(*args): 
    # usecase: @nsinclude() 
    # use classname in calling frame as a fallback 
    stack = inspect.stack() 
    opts = [stack[1][3]] 

    def wrap(func): 
     if func.func_name == "tempfunc": 
      return func 

     def invoke(*args, **kw): 
      base = eval(opts[0]) 

      src = trim(inspect.getsource(func)) 
      basenode = ast.parse(src) 

      class hackfunc(ast.NodeTransformer): 
       def visit_Name(self, node): 
        try: 
         # if base class (set in @nsinclude) can resolve 
         # given name, modify AST node to use that instead 
         val = getattr(base, node.id) 

         newnode = ast.parse("%s.%s" % (opts[0], node.id)) 
         newnode = next(ast.iter_child_nodes(newnode)) 
         newnode = next(ast.iter_child_nodes(newnode)) 
         ast.copy_location(newnode, node) 
         return ast.fix_missing_locations(newnode) 
        except: 
         return node 

      class hackcode(ast.NodeVisitor): 
       def visit_FunctionDef(self, node): 
        if func.func_name != "tempfunc": 
         node.name = "tempfunc" 
         hackfunc().visit(node) 

      hackcode().visit(basenode) 

      newmod = compile(basenode, '<ast>', 'exec') 
      eval(newmod) 
      newfunc = eval("tempfunc") 
      newfunc(*args, **kw) 
     return invoke 


    # usecase: @nsinclude 
    if args and isinstance(args[0], types.FunctionType): 
     return wrap(args[0]) 

    # usecase: @nsinclude("someclass") 
    if args and args[0]: 
     opts[0] = args[0] 
    return wrap 

class Bar: 
    FOO = 987 
    BAR = 876 

class Foo: 
    FOO = 123 
    BAR = 234 

    # import from belonging class 
    @nsinclude 
    def dump1(self, *args): 
     print("dump1: FOO = " + str(FOO)) 


    # import from specified class (Bar) 
    @nsinclude("Bar") 
    def dump2(self, *args): 
     print("dump2: BAR = " + str(BAR)) 

Foo().dump1() 
Foo().dump2() 
+1

+1। इस परिदृश्य में बहुत उपयोगी नहीं है, लेकिन प्रतिबिंब हैकिंग हमेशा मजेदार है! –

3

python3 में कोई नुकसान, आप भी संदर्भित कर सकते हैं VAGUE करता है गोली मार दी जानी चाहिए के रूप में:

type(self).VAGUE 

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

ध्यान दें कि यह विधि कम से कम मेरे परीक्षणों में नहीं है, जहां type(self) कक्षा के बजाय instance लौटाया गया है। इसलिए थॉमस वौटर का जवाब शायद बेहतर है, इस पर विचार करते हुए कि पाइथन 2 कितनी व्यापक है।

संबंधित मुद्दे