2014-02-13 24 views
1

我試圖根據正在傳入的參數來改變函數的行爲。我想用if語句,但我真的不想。 例子:替代「如果」根據參數在函數中做不同的事情

def BigPrime(numP, plist = [], x = 1, counter =0): 
    while len(plist) <= numP: 
      if x == 1 or x == 2 or x == 5: 
        plist.append(x) 
      elif x % 2 is not 0 and int(str(x)[-1]) is not 5: 
        for div in plist[1:]: 
            #Non mettere niente qui, strane magie 
            #accadono in questo luogo... 
          if x % div == 0: 
            break 
        else: 
          plist.append(x) 
        counter += 1 
      x += 1 
    return plist, counter 

編輯:OK,因爲這個例子沒有convice很多,我把真正的功能。對困惑感到抱歉!任何建議是值得歡迎的!

我需要這樣的:

def foo(arg = 0, x = 0): 
    if not arg: 
     while True: 
      pass 
    else: 
     while x < arg: 
      print('bar') 
      x+=1 

這真的看起來可怕, 這真的是唯一的出路?沒有更優雅的工作嗎?

+0

這就是它應該是什麼樣,我把有沒有「通行證」,因爲整個代碼太長寫下來,它不是irrilevant ......我想知道的是,如果有一些事情奇怪的方法或'魔術',可以做的伎倆,而不是一個if語句。 :) – WhiteEyeTree

+0

'foo'和'arg'幾乎不是它的「應該」的樣子:)無論如何,「if/else」在Python中相當習慣,即使是頂級條件,因爲* Python不會擁有對模式匹配或功能衛士*的本機支持。我可能會使用單獨的函數來完成實際的工作,甚至可能使用嵌套函數。當然代碼可以變得像想要的那樣瘋狂。 – user2864740

+0

編輯,現在有真正的功能! :D – WhiteEyeTree

回答

1

由於您的功能foo的行爲在兩種情況下完全不相關,所以我認爲if沒有任何問題。

既然你決心避免if聲明,你可以定義兩個函數和它們之間選擇任何其他方式選擇:

def foo(arg = 0, x = 0): 
    def loop_forever(): 
     while True: 
      pass 
    def print_stuff(): 
     while x < 100: 
      print('bar') 
      x += 1 
    # now, any of these: 

    # if expression not if statement! 
    print_stuff() if arg else loop_forever() 

    # what people did before the if expression 
    # *but* you have to change print_stuff to return a true value 
    arg and print_stuff() or loop_forever() 

    # data-driven design, buzzword-compliant ;-) 
    [loop_forever, print_stuff][bool(arg)]() 

一般選擇這個技術你看看什麼是這兩種情況相同並且有所不同,並決定在此基礎上使用什麼抽象。但在這種情況下,兩者之間沒有任何相同之處。

這裏有一種「醜陋,醜陋」的原則:除了在兩個不同的地方分別書寫它們之外,基本上沒有辦法表達兩種不相關的操作。無論是將if或兩個不同的函數或兩個不同的類與多態性的子句區分開來,幾乎都是無關緊要的,如果代碼中只有一個點負責定義它們,在它們之間進行選擇,並執行一個。如果這三件事是在不同的地方完成的,那麼你會做出重大決定。

對於你的真實代碼,這是我認爲我會寫的,爲了什麼是值得的。完全有可能我已經引入了一個bug,但我認爲這不是太多的代碼,我會尋找更多的函數。我不要求理解代碼的目的,因爲,象,3是質數,但我相信下面的是等價的:

def BigPrime(numP, plist = [], x = 1, counter =0): 
    while len(plist) <= numP: 
     if x in (1, 2, 5): 
      plist.append(x) 
     elif x % 2 != 0 and x % 5 != 0 
      if all(x % div != 0 for div in plist[1:]): 
       plist.append(x) 
      counter += 1 
     x += 1 
    return plist, counter 

有一個可能的優化,即plist[1:]複製陣列等itertools.islice(plist, 1, None)可能更好。

+0

謝謝你的詳盡答案。 我擔心我只用一個函數來做太多事情。 你在那裏寫的那些表達式會非常有幫助!我今天學到了新東西,謝謝! – WhiteEyeTree

+0

我不知道所有()表達,然後更多的文件。感謝您的見解! – WhiteEyeTree

0

可以使用的功能列表或字典:

def foo_0(x): 
    while True: 
     pass 

def foo_1(x): 
    while x < 100: 
     print('bar') 
     x += 1 

def foo_list(arg=0, x=0): 
    [foo_0, foo_1][arg](x) 

def foo_dict(arg=0, x=0): 
    {0: foo_0, 1: foo_1}[arg](x) 

如果ARG可以被外界[0,1]你需要索引列表或字典之前來約束它。

1

恕我直言,需要此功能表明可能是一個糟糕的設計。通常,一個功能應該實現一個明確的目標。如果需要兩種截然不同的行爲,則應該將其實施爲功能太多不同。

def block_script(): 
    while True: 
     pass 

def wait_and_spam(x = 0): 
    while x < 100: 
     print('bar') 
     x+=1 

函數可以通過不同的參數集實現相同的目標。在這種情況下,人們通常可以首先檢查參數以用缺省值填充缺失的參數,根據參數準備數據,然後運行相同的算法。靜態類型語言有一種特殊情況,算法本身的實現必須根據參數的類型進行更改,而重載是一個很好的功能。但它不是Python的情況。

/* Add two values with protection against overflow (short) */ 
unsigned short secure_add(unsigned short a, unsigned short b) { 
    unsigned long result = (unsigned long)a + (unsigned long)b; 
    if (result > (unsigned long)0xFFFF) { 
     return (unsigned short)0xFFFF; 
    } else { 
     return (unsigned short) result; 
    } 
} 

/* Add two values with protection against overflow (char) */ 
unsigned char secure_add(unsigned char a, unsigned char b) { 
    unsigned short result = (unsigned short)a + (unsigned short)b; 
    if (result > (unsigned short)0xFF) { 
     return (unsigned char)0xFF; 
    } else { 
     return (unsigned char) result; 
    } 
} 

最後,Python提供的功能類似getattr,允許獲得基於其名稱的函數的引用。該名稱可以在運行時構建。

class Parser: 

    def parse(self, source, initpos = 0): 
     for token in self.lexer.get_tokens(source, initpos): 
       # Call the state handler 
       statemgr = getattr(self, "_s_"+self.state) 
       statemgr(token) 

    def _s_func_header(self, token): 
     if token.name == "parenthesis_open": 
      self.state = "function_arguments" 
     # ... 

    def _s_function_arguments(self, token): 
     # ... 
+0

是的,我想我給了一個單一的功能太多的目標。好吧,我試過了;) – WhiteEyeTree

相關問題