2012-08-01 41 views
0

我有這個醜陋的代碼..Python的方式來寫這個代碼

orders = got_something_from_db() 
if orders: 
    for order in orders: 
     #print order 
     event_id = order["event_id"] 
     if event_id in event_id_dict: # something i grabbed earlier 
      product_id = order["product_id"] # products in an event 
      qty = order["qty"] 
      if product_id in product_sku_dict: 
       sku_id =product_sku_dict[product_id] 
       for i in range(qty): 
        sku_ids.append(sku_id) 

我如何使這個更Python(和簡潔)

+1

將其分解爲函數。我想你也可以用理解來代替循環和第一個「if」。您能否在代碼示例的開始部分提供一些虛擬示例數據,以便於測試答案? – millimoose 2012-08-01 00:13:51

+4

我只想提出一個元評論,即簡潔不一定總是目標(除非你打python高爾夫球)。可讀性和可維護性應該是第一位的。 – sjr 2012-08-01 00:16:33

+1

(我也考慮使用ORM和模型類,而不是混淆的詞組糾纏,對我來說就像一個PHPism。) – millimoose 2012-08-01 00:17:48

回答

2

在有限的範圍內,這裏是最好的我可以。

orders = got_something_from_db() 
for order in orders: #make got something return empty iterable on failure 
    if order["event_id"] in event_id_dict: 
     product_id = order["product_id"] 
     try: 
      sku_id = product_sku_dict[product_id] 
      #Change sku_ids to a collections.Counter (assuming order is unimportant) 
      sku_ids[sku_id] += order["qty"] 
     except KeyError: 
      pass 

另外,考慮將event_id,product_id等改爲屬性。你可能需要一個namedtuple在這裏,而不是一個字典。

1
sku_ids = [] 
event_ids = get_event_id_dict() 
orders = got_something_from_db() 

for order in orders: 
    if order["event_id"] in event_ids: 
     try: 
      sku_id = product_sku_dict[order["product_id"]] 
     except KeyError: 
      continue 

     sku_ids.extend([sku_id] * order["qty"]) 
2

我構建它類似如下:

def add_product_to_skus(product_id, qty): 
    if product_id in product_sku_dict: 
     sku_id = product_sku_dict[product_id] 
     sku_ids.extend(qty*[sku_id])  

# ... 

orders = got_something_from_db() 
if not orders: 
    return 

valid_orders = (o for o in orders if o['event_id'] in event_id_dict) 

for o in valid_orders: 
    add_product_to_skus(o['product_id'], o['qty']) 

的一些高爾夫上面會給你:

orders = got_something_from_db() 
if not orders: 
    return 
add_products_to_skus((o['product_id'], o['qty']) for o in orders 
        if o['event_id'] in event_id_dict 
        if o['product_id'] in product_sku_dict) 
# ... 
def add_product_to_skus(product_qtys): 
    for product_id, qty in product_qtys: 
     sku_id = product_sku_dict[product_id] 
     sku_ids.extend(qty*[sku_id]) 

但是從原來的這種形式的轉變不一定清楚(甚至是正確的),並且列表理解可能值得解釋過濾的評論。

1

您可能想要引發異常而不是默默忽略缺少的SKU項目。這是如何成爲最模塊化和優雅,沒有必要Python的:

database = ... 
productId_to_sku = {...} 

def productIdToSku(product_id): 
    try: 
     return productId_to_sku[product_id] 
    except IndexError: 
     raise Exception('product id #{} not in SKU database; have a manager add it'.format(product_id)) 

def getSkusFromEvent(event_id): 
    orders = database.fetch(event_id=event_id) 
    for order in orders: 
     yield (productIdToSku(order.PRODUCT_ID), order.QTY) 

collections.Counter(getSkusFromEvent(YOUR_EVENT_ID)) 
4

首先,代碼是不完全壞的 - 這是非常明顯的閱讀和理解,因此你肯定經過了比第一關更多的可維護性。

如果有問題,那就是深層嵌套。我會打破這種增長使得衆多的功能,每一個不同的經營宗旨,以他們的名義表示:

def order_has_valid_event(order): 
    """Returns True if the order was raised by an event 
    in event_id_dict""" 
    event_id = order["event_id"] 
    return event_id in event_id_dict # something i grabbed earlier 

def get_sku_from_order(order): 
    """Return the SKU of the product in an order""" 
    product_id = order['product_id'] 
    try: 
     return product_sku_dict[product_id] 
    except KeyError: 
     raise KeyError("Product {0} is not in SKU dictionary".format(product_id)) 

def get_order_skus(order): 
    """Returns a list of SKUs in an order""" 
    sku_id = get_sku_from_order(order) 
    qty = order["qty"] 
    return [sku_id] * qty 

# Modify got_something_from_db to always return a list, even if empty 
orders = got_something_from_db() 
for order in orders: 
    #print order 
    if order_has_valid_event(order): 
     try: 
      sku_ids.extend(get_order_skus(order)) 
     except KeyError: 
      continue 

請原諒這樣的嘗試,如果名稱不完全匹配你的意圖 - 只要適當地重新命名。

我試圖改進:

  • 相反循環qty次追加,你可以創建一個列表乘qty元素的列表:[「一」] * 3 = [「一」,「一」 ,'a']
  • 在商業級別,當產品ID不在SKU詞典中時,我會質疑無提示忽略的錯誤。這很可能是一個真正的問題(所有產品在我所從事的行業中都應該有一個SKU)。如果是這樣,讓錯誤迅速傳播並「大聲」傳遞給適當的錯誤處理程序,或者更可能是訂單可能被拒絕的地方。爲了更清楚地支持這一點,我已經捕獲了get_sku_from_order中的普通KeyError並拋出了更明確的異常消息。
  • 修改got_something_from_db總是返回一個列表,即使是空的。這簡化了邏輯和流程
相關問題