本書籍の特徴はタイトルの通り様々な側面から悪いサンプル(Harmful)をまず示した上でPythonicなサンプル(Idiomatic)を示して、どこが悪いかどこを直すべきかが分かりやすく解説されています。今回は4章「Control Structures and Functions」で参考になったTipsをメモしておこうと思います。
※ここで紹介してるのはごく一部なので興味あれば一度本書席をチェックしていただければと思います。
4.1 If Statement
4.1.2 Avoid repeating variable name in compound in statement
# Harmful is_generic_name = False name = 'Tom' if name == 'Tom' or name == 'Dick' or name == 'Harry': is_generic_name = True # Idiomatic name = 'Tom' is_generic_name = name in ('Tom', 'Dick', 'Harry')
4.2 For Loops
4.2.3 Use else to execute code after a for loop concludes
# Harmful for user in get_all_users(): has_malformed_email_address = False print ('Checking {}'.format(user)) for email_address in user.get_all_email_addresses(): if email_is_malformed(email_address): has_malformed_email_address = True print (u'email addressが不正な形式です!') break if not has_malformed_email_address: print ('All email address are valid!') # Idiomatic for user in get_all_users(): print ('Checking {}'.format(user)) for email_address in user.get_all_email_addresses(): if email_is_malformed(email_address): print(u'email addressが不正な形式です!') break else: print('All email address are valid')
4.3 Functions
4.3.2 Use *args and **kwargs to accept arbitrary arguments
# Harmful def make_api_call(foo, bar, baz): if baz in ('Unicorn', 'Oven', 'New York'): return foo(bar) else: return bar(foo) # I need to add another parameter to 'make_api_call' # without breaking everyone's existing code. # I have two options... def so_many_options(): # I can tack on new parameters, but only if I make # all of them optional ... def make_api_call(foo, bar, baz, qux=None, foo_polarity=None, baz_coefficient=None, quux_capacitor=None, file_not_fould=None): # ... and so on ad infinitum return file_not_found def version_graveyard(): # ... or I can create a new function each time the signature # hanges. def make_api_call_v2(foo, bar, baz, qux): return make_api_call(foo, bar, baz) - qux def make_api_call_v3(foo, bar, baz, qux, foo_polarity): if foo_polarity != 'reserved': return make_api_call_v2(foo, bar, baz, qux) return None def make_api_call_v4(foo, bar, baz, qux, foo_polarity, baz_coefficient): return make_api_call_v3(foo, bar, baz, qux, foo_polarity) * baz_coefficient def make_api_call_v5(foo, bar, baz, qux, foo_polarity, baz_coefficient, quux_capacitor): # I don't need 'foo', 'bar', or 'baz' anymore, but I have to keep # supporting them... return baz_coefficient * quux_capacitor # ... # Idiomatic def make_api_call(foo, bar, baz): if baz in ('Unicorn', 'Oven', 'New York'): return foo(bar) else: return bar(foo) # I need to add another parameter to 'make_api_call' # without breaking everyone's existing coe. # Easy ... def new_hotness(): def make_api_call(foo, bar, baz, *args, **kwargs): # Now I can accept any type and number of arguments # without worring about breaking existing code. baz_coefficient = kwargs['the_baz'] # I can even forward my args to a different fucntion # without knwoing their contents! return baz_coefficient in new_functions(args)
4.4 Exceptions
4.4.2 Use Exceptions to Write Code in an "EAFP" Style
※EASP→Easier to Ask for Forgiveness than Permission( which assumes things will go well and catches exceptions if they don't.)# Harmful def get_log_level(config_dict): if 'ENABLE_LOGGING' in config_dict: if config_dict['ENABLE_LOGGING'] != True: return None elif not 'DEFAULT_LOG_LEVEL' in config_dict: return None else: return None # Idiomatic def get_log_level(config_dict): try: if config_dict['ENABLE_LOGGING']: return config_dict['DEFAULT_LOG_LEVEL'] except KeyError: # if either value wasn't present, # a KeyError will be raised, so return None return None
4.4.3 Avoid "Swallowing(無条件で受け入れる)" Useful Exceptions With Bare Except Clauses
# Harmful import requests def get_json_response(url): try: r = requests.get(url) return r.json() except: print('Oops, something went wrong!') return None # Idiomatic import requests def get_json_response(url): return requests.get(url).json() # If we need to make note of the exception, we # would write the function this way ... def alternate_get_json_response(url): try: r = requests.get(url) return r.json() except: # do some logging here, but don't handle the exception ... raise
0 件のコメント:
コメントを投稿