टीएल; डीएक संदर्भ प्रबंधक का उपयोग करें। उनके बारे में महत्वपूर्ण सावधानी के लिए इस उत्तर के नीचे देखें।
फ़ाइलें जबकि वहाँ कुछ तरीके कि सामान्य उपयोगकर्ता वर्गों पर इस्तेमाल किया जा सकता है, उन तरीकों में निर्मित वर्गों के साथ काम नहीं करते पायथन 3. में और अधिक जटिल हो गया। एक तरह से मिश्रण में करने के लिए इसे instanciating से पहले एक वांछित वर्ग है, लेकिन यह जानने के क्या मिश्रण में वर्ग पहले किया जाना चाहिए की आवश्यकता है:
class MyFileType(???):
def __init__(...)
# stuff here
def close(self):
# more stuff here
क्योंकि वहाँ इतने सारे प्रकार के होते हैं, और अधिक संभवतः में जोड़ा जा सकता है भविष्य (असंभव, लेकिन संभव), और हम निश्चित रूप से नहीं जानते हैं कि के बाद open
पर कॉल करने के बाद वापस लौटाया जाएगा, यह विधि काम नहीं करती है।
एक अन्य विधि हमारे कस्टम प्रकार के लिए लौट आए उदाहरण के __class__
विशेषता को संशोधित करने के लिए लौट आए फ़ाइल के ___bases__
, और करने के लिए दोनों हमारे कस्टम प्रकार बदलने के लिए है:
class MyFileType:
def close(self):
# stuff here
some_file = open(path_to_file, '...') # ... = desired options
MyFileType.__bases__ = (some_file.__class__,) + MyFile.__bases__
लेकिन यह अभी तक पैदावार
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: __bases__ assignment: '_io.TextIOWrapper' deallocator differs from 'object'
एक और तरीका जो शुद्ध उपयोगकर्ता वर्गों के साथ काम कर सकता है वह फ्लाई पर कस्टम फ़ाइल प्रकार बनाना है, सीधे लौटाए गए इंस्टेंस के वर्ग से, और फिर लौटा हुआ इंस्टेंस क्लास अपडेट करें:
some_file = open(path_to_file, '...') # ... = desired options
class MyFile(some_file.__class__):
def close(self):
super().close()
print("that's all, folks!")
some_file.__class__ = MyFile
लेकिन फिर से:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: __class__ assignment: only for heap types
इसलिए, यह सबसे अच्छा तरीका है कि अजगर 3 में सब पर काम करेंगे, और सौभाग्य से भी अजगर 2 में काम करेंगे की तरह दिखता है (उपयोगी आप एक ही कोड चाहते हैं
class Open(object):
def __init__(self, *args, **kwds):
# do custom stuff here
self.args = args
self.kwds = kwds
def __enter__(self):
# or do custom stuff here :)
self.file_obj = open(*self.args, **self.kwds)
# return actual file object so we don't have to worry
# about proxying
return self.file_obj
def __exit__(self, *args):
# and still more custom stuff here
self.file_obj.close()
# or here
और इसका इस्तेमाल करने के:
with Open('some_file') as data:
# custom stuff just happened
for line in data:
print(line)
# data is now closed, and more custom stuff
# just happened
दोनों संस्करणों पर काम करने की) आधार एक कस्टम संदर्भ प्रबंधक है
एक महत्वपूर्ण बात को ध्यान में रखना: __init__
या __enter__
में किसी भी बिना क्रिया का अपवाद चलने से __exit__
कर पाएगा, इसलिए उन दो स्थानों में आप अभी भी यकीन है कि आप डॉन बनाने के लिए try
/except
और/या try
/finally
मुहावरों का प्रयोग करना होगा संसाधनों को रिसाव नहीं करें।
शायद फ़ाइल ऑब्जेक्ट को विस्तारित करने के बजाय आप एक 'ऑब्जेक्ट' कथन के साथ उपयोग करने के लिए एक कस्टम ऑब्जेक्ट बना सकते हैं? –
एक वर्ग जो 'ओपन' के वापसी मूल्य को लपेटता है इतना बुरा क्यों होगा? थोक विधियों को आगे बढ़ाने के लिए आप '__getattr__' को ओवरराइड कर सकते हैं। –
@ बेंजामिन होडसन यह काफी लंबा रहा है कि मुझे बिल्कुल याद नहीं आया कि मैं क्या सोच रहा था, लेकिन शायद यह "लाइनों का 9 0% करना आसान होगा और हर अंतिम कोने के मामले में एक बड़ा दर्द होगा पकड़ लिया।" मैंने पायथन में ऑब्जेक्ट आत्मनिरीक्षण के साथ बहुत कुछ नहीं किया है, और जब मैंने कोशिश की है तो यह मुझे भ्रमित तरीकों से फिसल गया है। – zwol