2009-05-19 18 views
69

अजगर गुण के साथ, मैं यह इस तरहक्या मॉड्यूल में वही गुण हो सकते हैं जो ऑब्जेक्ट्स कर सकते हैं?

obj.y 

सिर्फ एक मूल्य के लौटने के बजाय एक फ़ंक्शन को कॉल कर सकते हैं।

क्या मॉड्यूल के साथ ऐसा करने का कोई तरीका है? मेरे पास एक मामला है जहां मैं चाहता हूं कि

module.y 

फ़ंक्शन को कॉल करने के बजाय, वहां संग्रहीत मूल्य को वापस करने के बजाय।

+2

फ़ंक्शन को कॉल करने में क्या गड़बड़ है? –

+8

कुछ चीजें करने के लिए इसे कम टाइप करना चाहते हैं जो बहुत कुछ किया जाता है। –

उत्तर

50

केवल नए शैली के वर्गों के उदाहरणों में गुण हो सकते हैं। आप पाइथन को विश्वास कर सकते हैं कि इस तरह का एक उदाहरण sys.modules[thename] = theinstance में इसे दबाकर एक मॉड्यूल है। तो, उदाहरण के लिए, अपने m.py मॉड्यूल फ़ाइल हो सकता है:

import sys 
class _M(object): 
    def __init__(self): 
    self.c = 0 
    def afunction(self): 
    self.c += 1 
    return self.c 
    y = property(afunction) 
sys.modules[__name__] = _M() 

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

+0

मैंने ऐसा करने के बारे में कभी सोचा नहीं होगा। मैं मानता हूं कि इसका उपयोग करने की संभावना नहीं है, लेकिन आप कभी नहीं जानते। पाइथन में अनपढ़ मार्गों के बारे में जानने के लिए हमेशा खुश रहें ... धन्यवाद। –

+1

क्या कोई और कोशिश कर रहा है? जब मैं इस कोड को एक फ़ाइल x.py में डालता हूं और इसे दूसरे से आयात करता हूं, तो XY परिणामों को AttributeError में कॉल करना: 'noneType' ऑब्जेक्ट में कोई विशेषता नहीं है 'c', क्योंकि _M किसी भी तरह का मान नहीं है ... – Stephan202

+0

आपको कुछ गलत टाइप करना होगा । $ अजगर ... >>> आयात sys >>> वर्ग _M (वस्तु): ... c = 0 ... डीईएफ़ afunction (स्वयं): एक इंटरैक्टिव सत्र की जाँच करें ... _M .c + = 1 ... वापसी _M.c ... y = संपत्ति (कार्य) ... >>> sys।मॉड्यूल [ 'भनभनाहट'] = _M() >>> भनभनाहट आयात >>> bowwow.y >>> bowwow.y >>> ... उम्मीद बिल्कुल के रूप में, निश्चित रूप से। तो, आप वास्तव में क्या कर रहे हैं में क्या अलग है? –

44

मैं ठीक से एक मॉड्यूल के सभी विशेषताओं इनहेरिट करने के लिए ऐसा करते हैं होता है, और सही ढंग से isinstance()

import types 

class MyModule(types.ModuleType): 
    @property 
    def y(self): 
     return 5 


>>> a=MyModule("test") 
>>> a 
<module 'test' (built-in)> 
>>> a.y 
5 

से पहचाना जा और फिर आप sys.modules में इस डाल सकते हैं:

sys.modules[__name__] = MyModule(__name__) # remember to instantiate the class 
+0

यह केवल मामलों के सबसे सरल के लिए काम करता प्रतीत होता है। संभावित मुद्दे हैं: (1) कुछ आयात सहायक भी अन्य गुणों की अपेक्षा कर सकते हैं जैसे '__file__' जिसे मैन्युअल रूप से परिभाषित किया जाना है, (2) कक्षा वाले मॉड्यूल में किए गए आयात रन टाइम के दौरान" दृश्यमान "नहीं होंगे .. – tutuDajuju

+1

'प्रकार। मॉड्यूल टाइप', _any_ (नई शैली) कक्षा से उप-वर्ग प्राप्त करना आवश्यक नहीं है। वास्तव में क्या विशेष मॉड्यूल विशेषताएँ जहां आप उत्तराधिकारी की उम्मीद कर रहे हैं? – martineau

+0

क्या होगा यदि मूल मॉड्यूल एक पैकेज है और मैं मूल मॉड्यूल के नीचे मॉड्यूल तक पहुंचना चाहता हूं? –

1

एक सामान्य उपयोग केस है: कुछ (कुछ) गतिशील विशेषताओं के साथ एक (विशाल) मौजूदा मॉड्यूल को समृद्ध करना - सभी मॉड्यूल सामान को क्लास लेआउट में बदल दिए बिना। दुर्भाग्यवश sys.modules[__name__].__class__ = MyPropertyModule जैसे सबसे सरल मॉड्यूल क्लास पैच TypeError: __class__ assignment: only for heap types के साथ विफल रहता है। तो मॉड्यूल निर्माण को फिर से चालू करने की जरूरत है।

यह दृष्टिकोण अजगर आयात हुक के बिना यह होता है, बस मॉड्यूल कोड के शीर्ष पर कुछ prolog होने से:

# propertymodule.py 
""" Module property example """ 

if '__orgmod__' not in globals(): 

    # constant prolog for having module properties/supports reload() 

    print "PropertyModule stub execution", __name__ 
    import sys, types 
    class PropertyModule(types.ModuleType): 
     def __str__(self): 
      return "<PropertyModule %r from %r>" % (self.__name__, self.__file__) 
    modnew = PropertyModule(__name__, __doc__) 
    modnew.__modclass__ = PropertyModule   
    modnew.__file__ = __file__ 
    modnew.__orgmod__ = sys.modules[__name__] 
    sys.modules[__name__] = modnew 
    exec sys._getframe().f_code in modnew.__dict__ 

else: 

    # normal module code (usually vast) .. 

    print "regular module execution" 
    a = 7 

    def get_dynval(module): 
     return "property function returns %s in module %r" % (a * 4, module.__name__)  
    __modclass__.dynval = property(get_dynval) 

उपयोग:

>>> import propertymodule 
PropertyModule stub execution propertymodule 
regular module execution 
>>> propertymodule.dynval 
"property function returns 28 in module 'propertymodule'" 
>>> reload(propertymodule) # AFTER EDITS 
regular module execution 
<module 'propertymodule' from 'propertymodule.pyc'> 
>>> propertymodule.dynval 
"property function returns 36 in module 'propertymodule'" 

नोट: from propertymodule import dynval तरह एक जमे हुए उत्पादन करेगा पाठ्यक्रम की प्रति - dynval = someobject.dynval

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