2012-09-04 29 views
5

हाल ही में मैं कर रहा हूँ बातें:कोड शैली - इस तरह अन्य कार्यों के अंदर कार्यों 'छुपा'

import Tkinter 
class C(object): 
    def __init__(self): 
     self.root = Tkinter.Tk() 
     def f(): 
      print 'hello' 
     self.button = Tkinter.Button(master=self.root, command=f, text='say hello') 

के रूप में कुछ इस तरह का विरोध करने के:

import Tkinter 
class C(object): 
    def __init__(self): 
     self.root = Tkinter.Tk() 
     self.button = Tkinter.Button(master=self.root, command=self.f, text='say hello') 
    def f(self): 
     print 'hello' 

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

मेरा प्रश्न है: क्या इसे अच्छी शैली के रूप में माना जाता है? मैं चिंता कर रहा हूं क्योंकि मेरे पास बहुत सारे बटनों के साथ एक जीयूआई कक्षा है - __init__ बहुत सारी स्थानीय फ़ंक्शन परिभाषाओं के साथ बहुत लंबा लग रहा है। क्या कोई और उचित विकल्प है जिसका उपयोग करना चाहिए?

उत्तर

8

Tkinter के संदर्भ में ऐसा कुछ करने का सामान्य तरीका lambda फ़ंक्शन का उपयोग करना है।

self.button = Tkinter.Button(master=self.root, 
          command=lambda:sys.stdout.write("Hello!\n"), 
          text='say hello') 

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

यहां चिंता करने के लिए दो चीजें हैं। पहला पठनीयता है। यदि __init__ पढ़ने के लिए बहुत अव्यवस्थित हो जाता है, तो आपको कोई समस्या है। आप उन कार्यों को मॉड्यूल स्तर पर ले जा सकते हैं (उन्हें संदर्भ में आयात करने से रोकने के लिए _ के साथ उपसर्ग) और यदि आवश्यक हो तो उन कार्यों के तर्क के रूप में स्थानीय चर को बांधने के लिए lambda का उपयोग करें।

यदि __init__ अव्यवस्थित नहीं हो रहा है, तो वहां कार्यों को मुक्त करने के लिए स्वतंत्र महसूस करें। वहां के कार्यों का मतलब यह है कि एक नया फ़ंक्शन हर बार एक नया उदाहरण बनाया जाता है (lambda के साथ) जो मुझे लगता है कि स्मृति के संबंध में अपमानजनक हो सकता है, लेकिन यह इतना बड़ा नहीं होना चाहिए सौदा (विशेष रूप से एक गुई में)।

चिंता करने की दूसरी बात नामस्थान अव्यवस्था है। हालांकि, यदि आपका मॉड्यूल इतना बड़ा है कि उन स्थानीय कार्यों को मॉड्यूल लेवल फ़ंक्शंस में ले जाने के लिए नामस्थान समस्या उत्पन्न होती है, तो आपका मॉड्यूल शुरू करने के लिए बहुत बड़ा है। जब तक आप अंडरस्कोर के साथ फ़ंक्शंस को उपसर्ग करते हैं (उपरोक्त सुझाव देखें), तो आपके पास इस मॉड्यूल को अन्य लोगों में आयात करने वाले नामस्थान समस्याएं नहीं होनी चाहिए।

+2

आप सही हैं, लेकिन मेरे उदाहरण के असली दुनिया संस्करण में, 'एफ' सिर्फ' प्रिंट 'हैलो से अधिक कर रहा है। यह एक लैम्ब्डा समारोह के अंदर फिट नहीं होगा। –

+0

@poorsod - अगर यह उदाहरण का उपयोग नहीं कर रहा है, तो यह एक विधि नहीं होनी चाहिए। आप इसे मॉड्यूल लेवल फ़ंक्शन बना सकते हैं, या आप इसे जिस तरह से कर रहे हैं, उसे कर सकते हैं, लेकिन अगर आपको फ़ंक्शन में इंस्टेंस की आवश्यकता नहीं है तो मैं यहां एक विधि (या यहां तक ​​कि एक staticmethod) का उपयोग नहीं करता। – mgilson

+1

@mgilson: मुझे लगता है कि आप इस सवाल के बिंदु को याद करते हैं, जो कॉलबैक गैर-कार्यशील कार्य होना चाहिए। टिंकर कॉलबैक में अक्सर लैम्ब्डा को देखने का कारण कॉलबैक में स्थानीय तर्कों को बांधना है। कॉलबैक अक्सर अन्यत्र परिभाषित किया जाता है। –

2

इस मामले में यह हानिरहित है।

1) वर्ग के एक सदस्य के रूप में कॉलबैक की परिभाषा कुछ और अधिक पठनीय है (विशेष रूप से आप की जाँच करने के pydoc का उपयोग करते समय)

: कुल मिलाकर, हालांकि, मैं यह दो कारणों से बच जाएंगे 2) दूसरे के अंदर फ़ंक्शन बनाना अधिक बंद करता है (कॉलिंग संदर्भ से विरासत में प्राप्त चर)।

+1

यह आगे ले जाने और अन्य मॉड्यूल में कॉलबैक को परिभाषित करने के लिए चोट नहीं पहुंचाएगा, जिससे गुई को एप्लिकेशन तर्क से अलग किया जा सकेगा। –