2013-03-03 6 views
19

के लिए क्लास वैरिएबल को डिफ़ॉल्ट मान के रूप में असाइन करना मैं इस कक्षा से लिया गया डिफ़ॉल्ट मान तर्कों के साथ कक्षा के अंदर एक विधि बनाना चाहता हूं। आम तौर पर मैं कुछ डेटा पर फ़िल्टरिंग करता हूं। मेरी कक्षा के अंदर मेरे पास एक तरीका है जहां आम तौर पर मैं डेटा के वेक्टर पास करता हूं। कभी-कभी मेरे पास वेक्टर नहीं होता है और मैं नकली डेटा लेता हूं। हर बार जब मैं एक विशेष वेक्टर पास नहीं करता हूं तो मैं डिफ़ॉल्ट रूप से अनुरूपित डेटा लेना चाहता हूं। मैंने सोचा कि यह एक आसान निर्माण होना चाहिए जहां मेरी विधि परिभाषा के अंदर मैं a=self.vector कहता हूं। लेकिन किसी कारण से मुझे एक त्रुटि NameError: name 'self' is not defined है। सरलीकृत निर्माण है:वर्ग विधि तर्क

class baseClass(object): # This class takes an initial data or simulation 
    def __init__(self): 
     self.x = 1 
     self.y = 2 

class extendedClass(baseClass): # This class does some filtering 
    def __init__(self): 
     baseClass.__init__(self) 
     self.z = 5 
    def doSomething(self, a=self.z): 
     self.z = 3 
     self.b = a 

if __name__ == '__main__': 
    a = extendedClass() 
    print a.__dict__ 
    a.doSomething() 
    print a.__dict__ 

एक उत्पादन मैं उम्मीद किया जाना चाहिए:

{'y': 2, 'x': 1, 'z': 5} 
{'y': 2, 'x': 1, 'z': 3, 'b': 5} 

मैं डिफ़ॉल्ट असाइनमेंट की कोशिश की def doSomething(self, a=z): के रूप में स्पष्ट रूप से यह कभी काम नहीं करता। जहां तक ​​मैं समझता हूं self.z इस दायरे में दिखाई देता है और इसे डिफ़ॉल्ट मान के रूप में रखने में कोई समस्या नहीं होनी चाहिए। पता नहीं क्यों मुझे यह त्रुटि है और यह कैसे करें। यह शायद एक आसान सवाल है, लेकिन मैं इसे समझने की कोशिश करता हूं या बिना किसी कमी के समाधान को ढूंढता हूं। मुझे similar केवल अन्य भाषाओं के लिए प्रश्न मिले।

उत्तर

25

आपकी समझ गलत है। self स्वयं उस फ़ंक्शन परिभाषा का पैरामीटर है, इसलिए उस बिंदु पर दायरे में कोई रास्ता नहीं हो सकता है। यह केवल कार्य के भीतर ही दायरे में है।

जवाब None को तर्क डिफ़ॉल्ट, और फिर विधि के अंदर है कि के लिए जाँच बस है:

def doSomething(self, a=None): 
    if a is None: 
     a = self.z 
    self.z = 3 
    self.b = a 
+0

यदि तर्क गलत मूल्यों पर नहीं ले सकता है, तो आपको केवल 'अगर: a = self.z' या यहां तक ​​कि' a = a या self.z' लिखना चाहिए। – danijar

+0

मुझे लगता है कि आपका मतलब है 'अगर नहीं: a = self.z' – BBischof

+0

क्या यह एक मानक पायथनिक पैटर्न है, यानी एक क्लास प्रॉपर्टी को डिफॉल्ट के साथ एक वैकल्पिक विधि प्रॉपर्टी से फॉल-बैक के रूप में उपयोग किया जाता है? या वैकल्पिक 'z = none' प्रॉपर्टी को शामिल करने के लिए' विस्तारित क्लास '__init__ कन्स्ट्रक्टर को बदलना बेहतर है, और यदि' कोई नहीं 'विधि के अंदर कुछ डिफ़ॉल्ट पर सेट करता है, और इसे विधि पैरामीटर के रूप में नहीं रखता है? मैं केवल इतना सोच सकता हूं कि हार्ड-कोडेड क्लास प्रॉपर्टी उपयोगी है यदि यह वास्तव में स्थिर है, और एक से अधिक तरीकों से आवश्यक है, अन्यथा क्यों नहीं, विधि के दायरे में 'z' को प्रतिबंधित करें, शायद कोई वर्ग या ऑब्जेक्ट न हो संपत्ति बिल्कुल? – Davos

3

डिफ़ॉल्ट तर्क, केवल एक बार का मूल्यांकन करने के लिए जब परिभाषा निष्पादित किया जाता है। इसके बजाए, ऐसा करें:

def doSomething(self, a=None): 
    if a is None: 
     a = self.z 
    self.z = 3 
    self.b = a 

http://docs.python.org/release/3.3.0/tutorial/controlflow.html#more-on-defining-functions भी देखें।

6

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

वर्ग बनाने के लिए, BUILD_CLASS नाम 'A', अड्डों tuple(object,), और एक dict उस वर्ग नाम स्थान की विशेषताओं में शामिल है लेता है। यह type(name, bases, dict) पर कॉल करके मैन्युअल रूप से एक प्रकार को तुरंत चालू करने जैसा है। dict बनाने के लिए, कोड ऑब्जेक्ट A से फ़ंक्शन बनाया गया है और कहा जाता है। अंत में, क्लास ऑब्जेक्ट मॉड्यूल नेमस्पेस में STORE_NAME के माध्यम से संग्रहीत किया जाता है।

कोड ऑब्जेक्ट A, self.z को MAKE_FUNCTION पर तर्क के रूप में ढेर पर लोड किया गया है। बाइटकोड सेशन LOAD_NAME वर्तमान स्थानीय क्षेत्रों में self की खोज करेगा (यानी कक्षा नामस्थान परिभाषित किया जा रहा है), मॉड्यूल ग्लोबल्स और बिल्टिन। यदि self वैश्विक या बिल्टिन स्कोप में परिभाषित नहीं किया गया है तो यह स्पष्ट रूप से विफल हो जाएगा; यह स्पष्ट रूप से स्थानीय दायरे में परिभाषित नहीं है।

यदि यह सफल हुआ, तो फ़ंक्शन (self.z,) के साथ __defaults__ विशेषता के रूप में बनाया जाएगा, और फिर स्थानीय नाम test पर संग्रहीत किया जाएगा।

>>> code = compile(''' 
... class A(object): 
... def test(self, a=self.z): pass 
... ''', '<input>', 'exec') 

>>> dis.dis(code) 
    2   0 LOAD_CONST    0 ('A') 
       3 LOAD_NAME    0 (object) 
       6 BUILD_TUPLE    1 
       9 LOAD_CONST    1 (<code object A ...>) 
      12 MAKE_FUNCTION   0 
      15 CALL_FUNCTION   0 
      18 BUILD_CLASS   
      19 STORE_NAME    1 (A) 
      22 LOAD_CONST    2 (None) 
      25 RETURN_VALUE 

>>> dis.dis(code.co_consts[1]) # code object A 
    2   0 LOAD_NAME    0 (__name__) 
       3 STORE_NAME    1 (__module__) 

    3   6 LOAD_NAME    2 (self) 
       9 LOAD_ATTR    3 (z) 
      12 LOAD_CONST    0 (<code object test ...>) 
      15 MAKE_FUNCTION   1 
      18 STORE_NAME    4 (test) 
      21 LOAD_LOCALS   
      22 RETURN_VALUE  

@uselpa: आपका pastebin उदाहरण (2.x के लिए फिर से लिखा):

>>> code = compile(''' 
... default = 1 
... class Cl(object): 
...  def __init__(self, a=default): 
...   print a 
... Cl() 
... default = 2 
... Cl() 
... ''', '<input>', 'exec') 
>>> dis.dis(code) 
    2   0 LOAD_CONST    0 (1) 
       3 STORE_NAME    0 (default) 

    3   6 LOAD_CONST    1 ('Cl') 
       9 LOAD_NAME    1 (object) 
      12 BUILD_TUPLE    1 
      15 LOAD_CONST    2 (<code object Cl ...>) 
      18 MAKE_FUNCTION   0 
      21 CALL_FUNCTION   0 
      24 BUILD_CLASS   
      25 STORE_NAME    2 (Cl) 

    6   28 LOAD_NAME    2 (Cl) 
      31 CALL_FUNCTION   0 
      34 POP_TOP    

    7   35 LOAD_CONST    3 (2) 
      38 STORE_NAME    0 (default) 

    8   41 LOAD_NAME    2 (Cl) 
      44 CALL_FUNCTION   0 
      47 POP_TOP    
      48 LOAD_CONST    4 (None) 
      51 RETURN_VALUE   

आप देख सकते हैं, वर्ग वस्तु Cl (और समारोह वस्तु __init__) केवल instantiated है और एक बार स्थानीय नाम 'Cl' में संग्रहीत किया गया। मॉड्यूल अनुक्रमिक रूप से रन टाइम पर निष्पादित करता है, इसलिए बाद में default नाम को पुनर्निर्मित करने से __init__ में डिफ़ॉल्ट मान पर कोई प्रभाव नहीं पड़ेगा।

आप गतिशील रूप से पहले से संकलित कोड और एक नया डिफ़ॉल्ट मान का उपयोग कर एक नया कार्य का दृष्टांत सकता है: एक नया __defaults__ टपल के साथ एक समारोह बनाने के लिए

>>> default = 1 
>>> class Cl(object): 
...  def __init__(self, a=default): 
...   print a 
... 

>>> from types import FunctionType 
>>> default = 2 
>>> Cl.__init__ = FunctionType(
... Cl.__init__.__code__, globals(), '__init__', (default,), None) 
>>> c = Cl() 
2 

यह __init__.__code__ से पहले से ही संकलित कोड वस्तु पुनः उपयोग कर लेता:

>>> Cl.__init__.__defaults__ 
(2,) 
+1

मैं अटक गया हूँ। यदि कक्षा और विधि तत्काल समय पर बनाई गई हैं, तो वे स्पष्ट रूप से http://pastebin.com/UJfMpnqW पर मेरे उदाहरण में क्यों नहीं हैं? – uselpa

+0

@uselpa: मैंने "संकलन समय" और "रन टाइम" के बीच अंतर को स्पष्ट रूप से स्पष्ट करने के लिए अपना उदाहरण जोड़ा। एक मॉड्यूल कोई वाक्यविन्यास त्रुटियों के साथ ठीक संकलित कर सकता है, लेकिन आयातित (निष्पादित) होने पर अभी भी रनटाइम त्रुटियां हैं। – eryksun

+0

मुझे लगता है कि मुझे यह मिल रहा है। आपके धैर्य के लिए बहुत बहुत धन्यवाद! – uselpa

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