2013-05-08 10 views
34

मैं एक defaultdict है कि इस तरह दिखता है। यहां मिले समाधान में से एक लैम्ब्डा के बजाय मॉड्यूल-स्तरीय फ़ंक्शन का उपयोग करना है। मेरा सवाल है, मॉड्यूल-स्तरीय फ़ंक्शन क्या है? मैं cpickle के साथ शब्दकोश का उपयोग कैसे कर सकता हूं?अचार नहीं कर सकते defaultdict

उत्तर

40

इसके अलावा Martijn's explanation रहे हैं:

एक मॉड्यूल स्तरीय समारोह एक समारोह जो मॉड्यूल स्तर पर परिभाषित किया गया है, जिसका अर्थ है कि यह एक नहीं है एक वर्ग की आवृत्ति विधि, यह किसी अन्य फ़ंक्शन के भीतर घोंसला नहीं है, और यह नाम के साथ एक "वास्तविक" फ़ंक्शन है, न कि लैम्ब्डा फ़ंक्शन।

तो, अपने defaultdict अचार के लिए, एक लैम्ब्डा समारोह के बजाय मॉड्यूल स्तरीय समारोह के साथ इसे बनाने के लिए:

def dd(): 
    return defaultdict(int) 

dict1 = defaultdict(dd) # dd is a module-level function 

से आप इसे

tmp = pickle.dumps(dict1) # no exception 
new = pickle.loads(tmp) 
11

अचार सभी इंस्टेंस विशेषताओं को स्टोर करना चाहता है, और defaultdict उदाहरण default कॉल करने योग्य के संदर्भ को संग्रहीत करते हैं। अचार प्रत्येक उदाहरण विशेषता पर recurses।

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

7

आप तथापि partial उपयोग कर सकते हैं यह पूरा करने के:

>>> from collections import defaultdict 
>>> from functools import partial 
>>> pickle.loads(pickle.dumps(defaultdict(partial(defaultdict, int)))) 
defaultdict(<functools.partial object at 0x94dd16c>, {}) 
+1

क्या आप मेरे लिए यह अनपॅक कर सकते हैं कि यह कैसे काम करता है? मैं चिंतित हूं ... – Fred

1

मैं वर्तमान में कुछ इसी तरह कर रहा हूँ अचार कर सकते हैं प्रश्नकर्ता के लिए, हालांकि, मैं डिफॉल्टडिक्ट के उप-वर्ग का उपयोग कर रहा हूं जिसमें एक सदस्य फ़ंक्शन है जिसका उपयोग डिफ़ॉल्ट_फैक्टरी के रूप में किया जाता है। मेरे कोड को ठीक से काम करने के लिए (मुझे रनटाइम पर फ़ंक्शन को परिभाषित करने की आवश्यकता है), मैंने बस पिकलिंग के लिए ऑब्जेक्ट तैयार करने के लिए कुछ कोड जोड़ा।

बजाय:

.... 
factory = dict.default_factory 
dict.default_factory = None 
pickle.dump(dict, file) 
dict.default_factory = factory 
... 

इस सटीक कोड मैं अपने पेड़ के रूप में इस्तेमाल नहीं किया है एक वस्तु के रूप में एक ही पेड़ के प्रकार के उदाहरण बनाता है:

... 
pickle.dump(dict, file) 
... 

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

+0

ध्यान दें कि यह केवल तभी अच्छा है जब आप मसालेदार नियम के 'डिफ़ॉल्ट_फैक्टरी' को खोने की परवाह नहीं करते हैं। यदि आपको कारखाने की आवश्यकता नहीं है, तो आप इसे आसानी से 'कोई नहीं' पर सेट कर सकते हैं और किया जा सकता है (: – drevicko

5

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

>>> import dill 
>>> from collections import defaultdict 
>>> 
>>> dict1 = defaultdict(lambda: defaultdict(int)) 
>>> pdict1 = dill.dumps(dict1) 
>>> _dict1 = dill.loads(pdict1) 
>>> _dict1 
defaultdict(<function <lambda> at 0x10b31b398>, {}) 
+0

यह अच्छी तरह से काम करता है। क्या temp फ़ाइल में dict1 को डंप करने का कोई तरीका है और फिर इसे फिर से लोड करना है? कुछ समान फाइलों से लिखने और पढ़ने के अचार ऑपरेशन के लिए .. –

+0

निश्चित रूप से। 'डिल' सामान्य 'डंप' और 'लोड' प्रदान करता है जिसका उपयोग' अचार 'और' पिकल 'से' लोड' 'जैसा किया जा सकता है। इसके अतिरिक्त, आप शायद 'dill.temp.dump' को देखना चाहते हैं जो 'नामांकित समकालीन फ़ाइल' पर डंप करता है। –

+0

धन्यवाद, मेरी प्रोफ़ाइल पर नवीनतम प्रश्न देखें। आप अपना उत्तर वहां पोस्ट कर सकते हैं। :) –

1

आप defaultdict प्रकार संरक्षण के बारे में परवाह नहीं करते हैं, यह कन्वर्ट:

fname = "file.pkl" 

for value in nested_default_dict: 
    nested_default_dict[value] = dict(nested_default_dict[value]) 
my_dict = dict(nested_default_dict) 

with open(fname, "wb") as f: 
    pickle.dump(my_dict, f) # Now this will work 

मुझे लगता है कि इस के बाद से जब आप अचार बनाने हैं एक बेहतरीन विकल्प है, वस्तु शायद में यह अंतिम रूप है ... और, यदि वास्तव में डिफ़ॉल्ट डिफॉल्ट प्रकार की आवश्यकता है, तो आप आसानी से कनवर्ट करने के बाद वापस आ सकते हैं:

for value in my_dict: 
    my_dict[value] = defaultdict(type, my_dict[value]) 
nested_default_dict = defaultdict(type, my_dict) 
संबंधित मुद्दे