2016-07-12 3 views
6

I, एक शुरुआती, एक साधारण कार्ड-आधारित जीयूआई पर काम कर रहा हूं, प्रत्येक वर्ग में एक ही एक्सपेक्शन को पकड़ना। पायथन में लिखा है। एक बेस क्लास है कि, अन्य चीजों के साथ, _cards = {'card1_ID': card1, 'card2_ID': card2} जैसे सभी कार्डों की शब्दावली शामिल है। जीयूआई पर कार्डों को उनके अद्वितीय आईडी द्वारा संदर्भित किया जाता है।कक्षा

जैसा कि मैं अन्य शुरुआती लोगों के लिए कोड को अबाउट बनाने की योजना बना रहा हूं, मैं उन्हें स्पष्ट रूप से सूचित करना चाहता हूं कि अगर वे एक कार्ड आईडी देते हैं जो मौजूद नहीं है (एक KeyError फेंकने के बजाय)। अब मैं बार-बार कोशिश की उम्मीद खंड के एक टन है कि मुझे शक करता है:

बिना कोड, एक पंक्ति के तरीकों का एक हिस्सा कोशिश को पकड़ने:

def shift(self, card_ID, amount): 
     """Moves the card by the given amount of pixels. 
      :param amount: the horizontal and vertical amount of shifting in pixels; tuple""" 

     try: 
      self._cards[card_ID].shift(amount) 
     except KeyError: 
      raise ValueError("Invaild card ID") 


    def align(self, card_ID, horizontal, vertical): 
     """Aligns the card to the given position.""" 

     try: 
      card = self._cards[card_ID] 
      card.align(horizontal, vertical) 
     except KeyError: 
      raise ValueError("Invaild card ID") 


    def invert(self, card_ID): 
     """Inverts the card's colour""" 

     try: 
      self._cards[card_ID].invert() 
     except KeyError: 
      raise ValueError("Invaild card ID") 

इस एक स्वीकृत अभ्यास है? कक्षा के हर तरीके में इस KeyError को पकड़ने के लिए कोई बेहतर तरीका है?

+1

एक [सजावट] पर विचार करें (http://thecodeship.com/patterns/guide-to-python-function-decorators/) – khelwood

+0

एक अन्य दृष्टिकोण _cards उदाहरण के ____ getitem \ __ को ओवरराइट करेगा। –

+0

क्या कोई कारण है कि आप अपने कार्ड संग्रह के लिए किसी ऑब्जेक्ट का उपयोग कर रहे हैं जो 'KeyError' उठाता है जब आप चाहते हैं कि 'ValueError' है? या वैकल्पिक रूप से, आप पहली जगह 'ValueError' क्यों चाहते हैं? क्यों न केवल अपने कोड के स्थान पर 'ValueError' की बजाय' KeyError' पकड़ें जो आपकी कक्षा का उपयोग कर रहा है? यदि समस्या कस्टम त्रुटि संदेश है, तो शायद सबसे अच्छी बात यह है कि अपने स्वयं के 'कार्डकोलेक्शन' प्रकार को अपने स्वयं के त्रुटि संदेश के साथ बनाया गया है। –

उत्तर

8

आईडी से कार्ड को वास्तविक तरीके से निकालने के लिए, एक कोशिश के साथ/वहां छोड़कर, और उस विधि को हर जगह से कॉल करें।

def get_card(self, card_id): 
    try: 
     return self._cards[card_ID] 
    except KeyError: 
     raise ValueError("Invaild card ID") 

def invert(self, card_id): 
    return self.get_card(card_id).invert() 

... 
+0

मैंने विधि 'get_card() 'नाम दिया होगा (यह कार्ड_आईडी वापस नहीं करता है?) ... –

+0

@brunodesthuilliers आप निश्चित रूप से सही हैं, अपडेट किया गया। –

+0

ईमानदारी से, मुझे नहीं पता कि मैंने इस बारे में क्यों नहीं सोचा है ... धन्यवाद! – Neinstein

7

आप उस दोहराव वाले बॉयलर प्लेट को हटाने के लिए एक सजावटी का उपयोग कर सकते हैं।

from functools import wraps 

def replace_keyerror(func): 
    """Catches KeyError and replaces it with ValueError""" 

    @wraps(func) 
    def inner(*args, **kwargs): 
     try: 
      func(*args, **kwargs) 
     except KeyError: 
      raise ValueError("Invaild card ID") 
    return inner 

तो फिर तुम इसे इस तरह का प्रयोग करेंगे:

@replace_keyerror 
def align(self, card_ID, horizontal, vertical): 
"""Aligns the card to the given position.""" 
    card = self._cards[card_ID] 
    card.align(horizontal, vertical) 

@replace_keyerror 
def invert(self, card_ID): 
    """Inverts the card's colour""" 
    self._cards[card_ID].invert() 
+3

ओपी के उपयोग के मामले के लिए यह एक पूरी तरह से वैध उत्तर (और पाइथन नवागंतुकों के लिए एक अच्छी तरह से जानी जाने वाली सुविधा) है, लेकिन मैं डैनियल रोज़मन के अधिक स्पष्ट समाधान का उपयोग करता हूं ... –

+0

@brunodesthuilliers दोनों बयान में सहमत हैं। मुझे सजावट करने वालों को पता है कि मुझे खुशी है, और कोई अन्य मामला मैं इस जवाब को स्वीकार करूंगा। मैं अब डैनियल रोज़मैन का चयन करता हूं क्योंकि यही वह है जो मैं वास्तव में लागू करने जा रहा हूं, लेकिन मुझे यह और पसंद है। – Neinstein

1

तुम हमेशा तुम क्या चाहते प्राप्त करने के लिए एक डेकोरेटर फ़ंक्शन का उपयोग कर सकते हैं। This link यह जानने के लिए एक उत्कृष्ट ट्यूटोरियल है कि सजावटी क्या हैं और उनका उपयोग कैसे करें। मैं आपके मामले में सजावटी का उपयोग कर एक उदाहरण समाधान दूंगा।

असल में, आप केवल एक फ़ंक्शन बनाते हैं जो एक पैरामीटर के रूप में कार्य करता है और रैपर देता है जो इसके साथ कुछ खास करता है। एक यह है कि अपने समाधान फिट हो सकता है इस प्रकार दिखाई देगा:

def catch_invalid_card_exception(func): 
    def wrapper(*args, **kwargs):  
     try: 
      return func(*args, **kwargs) 
     except KeyError: 
      raise ValueError("Invalid card ID") # Not "invaild" ;) 
    return wrapper 

... तो आप अपने कार्यों/इस तरह के तरीकों को सजाने कर सकते हैं:

@catch_invalid_card_exception 
def shift(self, card_ID, amount): 
    """Moves the card by the given amount of pixels. 
     :param amount: the horizontal and vertical amount of shifting in pixels; tuple""" 
    self._cards[card_ID].shift(amount) 

@catch_invalid_card_exception 
def align(self, card_ID, horizontal, vertical): 
    """Aligns the card to the given position.""" 
    card = self._cards[card_ID] 
    card.align(horizontal, vertical) 

@catch_invalid_card_exception 
def invert(self, card_ID): 
    """Inverts the card's colour""" 
    self._cards[card_ID].invert() 

... जो इस के लिए वास्तव में सिर्फ वाक्यात्मक चीनी है :

def shift(self, card_ID, amount): 
    # ... 
shift = catch_invalid_card_exception(shift) 

def align(self, card_ID, horizontal, vertical): 
    # ... 
align = catch_invalid_card_exception(align) 

def invert(self, card_ID): 
    # ... 
invert = catch_invalid_card_exception(invert) 
+0

लिंक और स्पष्टीकरण के लिए धन्यवाद, उन्होंने बहुत मदद की। – Neinstein

+0

@ नेनस्टीन: अगर इससे मदद मिली है, तो इसे ऊपर उठाना न भूलें या इसे जवाब के रूप में चिह्नित न करें! –

1

आप अपने कार्ड संग्रह को अपने स्वयं के संग्रह में बनाने पर विचार कर सकते हैं जो आपको आवश्यक अनुकूलित अपवाद प्रदान कर सकता है। आप अपने कार्ड संग्रह के लिए एक dict का उपयोग कर रहे हैं, तो आप इस तरह कस्टम व्यवहार के साथ अपने स्वयं dict बना सकता है:

class CardsCollection(dict): 
    '''A dict-like collection of cards''' 
    def __getitem__(self, key): 
     try: 
      # first try default behavior 
      super().__self__(key) 
     except KeyError: 
      # it didn't work! 
      raise ValueError("Invalid card ID: {!r}".format(key)) 

अब तुम सिर्फ इस तरह अपने विभिन्न तरीकों कर सकते हैं:

def align(self, card_ID, horizontal, vertical): 
     """Aligns the card to the given position.""" 
      card = self._cards[card_ID] 
      card.align(horizontal, vertical) 
etc. etc. 

.. समायोजित करें अपने ._cards विशेषता के लिए अपनी कक्षा का उपयोग करना सुनिश्चित करें।

_cards = CardsCollection(card1_ID = card1, card2_ID = card2) 

या:

_cards = CardsCollection({'card1_ID': card1, 'card2_ID': card2}) 

इस बारे में अच्छी बात यह है कि अपने यूआई वर्ग वस्तु डेटा के आयोजन के लिए अनुकूलित या असामान्य इंटरफेस (अर्थात, getcard()) किसी तरह का करने के लिए प्रतिबद्ध नहीं है। यहां इंटरफ़ेस Python data model के साथ संगत है। इसलिए, अगर किसी कारण से आप तय करते हैं कि आप एक ही ऑब्जेक्ट क्लास के लिए एक ही यूआई का उपयोग करना चाहते हैं, तो आपने एक कोशिश की और सही एपीआई का उपयोग किया है जो पाइथन के अनुरूप एक तरह से लिखे गए किसी भी चीज के बारे में बताएगा डेटा मॉडल।