简体   繁体   中英

Calling Python functions/methods with zero arguments

According to Clean Code , a function should take zero arguments when at all possible.

If we take a trivial example in Python with a function that does nothing more than add 2 to whatever is passed to it:

def add_two(x):
    return x + 2

>add_two(1)
3

The only way I can see that such a function can have zero arguments passed to it is by incorporating it into a class:

class Number(object):
    def __init__(self, x):
        self.x = x

    def add_two(self):
        return self.x + 2

>n = Number(1)
>n.add_two()
3

It hardly seems worth the effort. Is there another way of achieving the no-argument function in this example?

If we take a trivial example in Python with a function that does nothing more than add 2 to whatever is passed to it: ... Is there another way of achieving the no-argument function in this example?

In a word, no. In several words: by definition, your function takes an argument. There's no way to take an argument without taking an argument.

In General

That is truly bad general advice, no argument methods are great for objects that modify the object in a way that requires no external data, or for functions that only interact with globals (you should really have minimal need to do this). In your case, you need to modify a given object with external data, and both objects are a builtin type ( int ).

In this case, just use a function with two arguments.

Too Many Arguments

Now, here is where the advice gets good. Say I need to do a complicated task, with numerous arguments.

def complicatedfunction(arg1, arg2, arg3, arg4, arg5, arg6):
    '''This requires 6 pieces of info'''

    return ((arg1 + arg2) / (arg3 * arg4)) ** (arg5 + arg6)

In this case, you are making unreadable code, and you should reduce the number of arguments to 5 or less .

Reducing Argument Counts

In this case, you could pass a namedtuple:

from collections import namedtuple
Numbers = namedtuple("Numbers", "numerator denominator exponent")
mynumber = Numbers(1+2, 3+4, 5+6)

def complicatedfunction(number):
    return (number.numerator / number.denominator) ** (number.exponent)

This has the added benefit of then making your code easy to modify in the future. Say I need to add another argument: I can just add that as a value into the namedtuple.

from collections import namedtuple
Numbers = namedtuple("Numbers", "numerator denominator exponent add")
mynumber = Numbers(1+2, 3+4, 5+6, 2)

def complicatedfunction(number):
    value = (number.numerator / number.denominator) ** (number.exponent)
    return value + number.add

Object-Oriented Design

Or, if I want to use that specific namedtuple for a lot of different tasks, I can subclass it and then get a 0-argument method for a specific goal. I can add as many methods as I want, which allows me to use the object in a versatile manner, as follows:

from collections import namedtuple


class Numbers(namedtuple("Numbers", "numerator denominator exponent add")):

    def process(self):
        value = (self.numerator / self.denominator) ** (self.exponent)
        return value + self.add

mynumber = Numbers(1+2, 3+4, 5+6, 2)

Why don't you use default argument method

def add_two(x=0):
    return x + 2
>>> add_two(1)
3
>>> add_two()
2
>>>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM