2014-06-26 48 views
0

我有4個變量,其中一些將是True和False,並且對於每個組合,我將不得不調用一個或幾個函數。 我目前對每個案例都使用了if else語句,我想知道是否有更好的方法來獲得與字典或其他內容相同的結果。如何簡化if語句中的布爾邏輯?

謝謝

這裏是我的代碼:簡化它會識別並分解出重複

if (self.cpe_ip and self.cpe_passwd) and self.phone and self.pppoe: 
     print "launch ISP portal, modem and radius" 
     if self.isp() == "east": 
      self.launchbell() 
     else: 
      self.launchtelus() 
     print 'check modem...' 
     self.modemstatus() 
     radius = sgp_radius.Radius(self.pppoe) 
     print 'check radius logs...' 
     self.data = radius.sgp() 

     self.radius_save() 

     #exit(0) 
    elif (self.cpe_ip and self.cpe_passwd) and not self.phone and not self.pppoe: 
     print "launch modem test only" 
     self.modemstatus() 


     #exit(0) 
    elif not(self.cpe_ip and self.cpe_passwd) and self.phone and not self.pppoe: 
     #print "only Bell portal" 
     if self.isp() == "east": 
      self.launchbell() 
     else: 
      self.launchtelus() 

    elif (self.cpe_ip and self.cpe_passwd) and not self.phone and self.pppoe: 
     #print "launch modem and radius test." 
     self.modemstatus() 

     radius = sgp_radius.Radius(self.pppoe) 
     print 'check radius logs...' 
     self.data = radius.sgp() 
     self.radius_save() 

    elif not(self.cpe_ip and self.cpe_passwd) and not self.phone and self.pppoe: 
     #print "only radius tests." 
     radius = sgp_radius.Radius(self.pppoe) 
     self.data = radius.sgp() 

     self.radius_save() 

    elif not(self.cpe_ip and self.cpe_passwd) and self.phone and self.pppoe: 
     print "bell and radius tests." 
     if self.isp() == "east": 
      self.launchbell() 
     else: 
      self.launchtelus() 

     radius = sgp_radius.Radius(self.pppoe) 
     print 'check radius logs...' 
     self.data = radius.sgp() 
     self.radius_save() 

    elif (self.cpe_ip and self.cpe_passwd) and self.phone and not self.pppoe: 
     #print "launch modem and bell tests." 
     if self.isp() == "east": 
      self.launchbell() 
     else: 
      self.launchtelus() 
     self.modemstatus() 

    else: 
     #print "test bell only" 
     #launchbell(self.phone) 
     exit(0) 

回答

5

方式一:

if self.phone: 
    if self.isp() == "east": 
     self.launchbell() 
    else: 
     self.launchtelus() 

if self.cpe_ip and self.cpe_passwd: 
    print 'check modem...' 
    self.modemstatus() 

if self.pppoe: 
    radius = sgp_radius.Radius(self.pppoe) 
    print 'check radius logs...' 
    self.data = radius.sgp() 
    self.radius_save() 
+0

您的快速回答OK THKS,這意味着我將不得不使用一個for循環來測試每個元素,並推出如果函數其中之一是真的... – neonet

+0

@neonet我不太贊同你的評論。這三個獨立的'if'子句不需要循環,你可以把它們放在我給他們看的地方;一個接一個地在你的(我猜)測試函數中。 – jonrsharpe

+0

如果他想根據不同的組合打印當前註釋掉的字符串,該怎麼辦? (或者更一般地說,如果明天邏輯改變,重複數量減少) – GreenAsJade

2

你在你的問題暗示邏輯的某種查找表可能是要走的路,而且有很多方法可以製作類似的東西。

正如你所說,一種方法是使用字典,如下所示。

這種方式導致看起來相當複雜的代碼比您的特定示例的「簡化和分解複製」解決方案更好看,但此方法更容易擴展到您針對不同情況具有更多不同邏輯的情況。 ..我不是說它「更好」......只是一個不同的選擇!

def launch_isp_portal_and_radius(): 
    print "launch ISP portal, modem and radius" 
    # etc 

# etc 

DecisionTable = { 
# cpe_ip cpe_passwd phone ppoe 
    (True, True, True, True) : launch_isp_portal_and_radius, 
    (True, True, False, False) : launch_modem_test_only, 
    (False, False, True, False) : only_Bell_portal, 
    (False, True, True, False) : only_Bell_portal, 
    (True, False, True, False) : only_Bell_portal, 
    (True, True, False, True) : launch_modem_and_radius_test, 
    (False, False, False, False) : only_radius_tests, 
    (False, True, False, False) : only_radius_tests, 
    (True, False, False, False) : only_radius_tests, 
    (False, False, True, True) : bell_and_radius_tests 
    (False, True, True, True) : bell_and_radius_tests, 
    (True, False, True, True) : bell_and_radius_tests, 
    (True, True, True, False) : launch_modem_and_bell_tests 
} 

action = DecisionTable.get((self.cpe_ip, self.cpe_passwd, self.phone, self.ppoe)) 

if action: 
    action() 
else: 
    raise StandardError("Whoa, internal logic error!") 

(當然還有其他的方法來做出決定表 - 數組是另一種顯而易見的選擇使用陣列的問題是使它的靜態聲明看可讀性它所代表的邏輯......。 )

(編輯:作出的字典索引的元組,按照JONS建議)

+1

這實際上是我在我腦中的另一種方法!兩條評論:1.一個四元組布爾值可能是一個更好的關鍵('input = tuple(map(bool,(cpe_ip,cpe_passwd,phone,ppoe))'';和2.我會將子測試(例如啓動ISP)分成子功能。我也會試用'try:DecisionTable [inputs]();除了KeyError:...'。 – jonrsharpe

+1

是的 - 完全同意分解常見的子功能。但是,哦,我的上帝......我不知道你可以用一個元組索引一個字典!這是_heaps_更優雅......我會重寫! – GreenAsJade

+0

任何可以進行哈希和相等比較的東西(包括實現'__hash__'和'__eq__'的自定義類)都可以成爲關鍵。請注意,您沒有定義「選擇」,因此您的最後一行是「NameError」。 – jonrsharpe