替换为“if”根据参数在函数中执行不同的操作

时间:2014-02-13 18:02:55

标签: python function arguments

我正在尝试根据传入的参数更改函数的行为。我正在考虑使用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

编辑:好的,因为这个例子没有很多我提出真正的功能。对困惑感到抱歉!欢迎任何建议!

我需要这样的东西:

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

这真的很可怕, 这真的是唯一的方法吗?是不是有更优雅的工作?

3 个答案:

答案 0 :(得分: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)]()

一般来说,为此选择一种技术,你要看两种情况之间的相同和不同之处,并决定在此基础上使用哪些抽象。但在这种情况下,两者之间没有任何相同之处。

有一种丑陋的,丑陋的&#34;在这里工作的原则:基本上没有办法表达两个不相关的操作,除了在两个不同的地方分别编写它们。无论是将这些位置分隔为if的子句,还是作为两个不同的函数,或者将两个不同的类与多态相区分,如果代码中只有一个点负责定义它们,则几乎无关紧要,在它们之间进行选择,并执行一个。如果这三件事情是在不同的地方完成的,那么你就要做出重大决定。

对于您的真实代码,这就是我认为我写的东西,以及它的价值。完全有可能我已经介绍了一个错误,但我不认为这么多代码我想要编写更多功能。我没有声称理解代码的目的,因为,就像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)可能会更好。

答案 1 :(得分:1)

恕我直言,需要此功能表明可能是糟糕的设计。通常,一个函数应该实现一个明确的目标。如果需要两种不同的行为,则应将其实现为过于不同的功能。

def block_script():
    while True:
        pass

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

一个函数可以使用不同的参数集实现相同的目标。在这种情况下,通常可以首先检查参数以使用默认值填充缺失的参数,根据参数准备数据,然后运行相同的算法。对于静态类型语言有一种特殊情况,其中算法本身的实现必须根据参数的类型进行更改,然后重载是一个很好的特性。但事实并非如此。

/* 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):
        # ...

答案 2 :(得分: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]之外,则需要在索引列表或词典之前对其进行约束。