减少Python中函数的参数数量?

Reducing the number of arguments in function in Python?

我的问题是如何处理我使用凯撒密码的那段代码。

函数解密和加密必须处理字母表的限制(a-z和a-z)。我尝试在一个名为cycleencrypt的循环函数中为两个字母编写两个可能的循环。

但是这个函数有6个参数,我在某个地方读到了一个函数中有3个以上的参数,所以我的问题是:

我是否应该通过拆分两个函数来减少参数的数量,并使代码段更长(但可能更容易理解)?谢谢你的回答,我同意。

编辑:删除了函数周围的docstring以使我问题的主要目的。

1
2
3
4
5
6
7
8
9
10
11
12
def offsetctrl(offset):
    while offset < 0:
        offset += 26
    return offset

def cycleencrypt(string, offset, index, listing, first, last):
    offset = offsetctrl(offset)
    if string >= ord(first) and string <= ord(last):
        string += offset
        while string > ord(last):
            string = ord(first) + (string - ord(last) -1)
        listing[index] = chr(string)

带大量参数的加密周期和负偏移量的控制

1
2
3
4
5
6
7
def encrypt(retezec, offset):
    listing = list(retezec)
    for index in range(0, len(retezec)):
        string = ord(retezec[index])
        cycleencrypt(string, offset, index, listing, 'A', 'Z')
        cycleencrypt(string, offset, index, listing, 'a', 'z')
    print(''.join(listing))

主加密部分采用两行多参数打印

1
2
3
4
5
6
def decrypt(retezec, offset):
    return encrypt(retezec, -offset)

if __name__ =="__main__":
encrypt("hey fellow how is it going", 5)
decrypt("mjd kjqqtb mtb nx ny ltnsl", 5)

在这种情况下,最好将代码编写为类。类的构造函数可以只接受所需的最少数量的参数(可能根本不是!),然后可以将可选参数设置为类的属性或使用其他方法。

当设计这样的类时,我发现首先编写客户机代码是最有用的——也就是说,先编写将使用类的代码,然后从那里向后工作来设计类。

例如,我可能希望代码看起来像这样:

1
2
3
4
cypher = Cypher()
cypher.offset = 17
cypher.set_alphabet('A', 'Z')
result = cypher.encrypt('hey fellow how is it going')

希望能够清楚地知道如何从这里开始设计Cypher类,但是如果没有,请询问有关堆栈溢出的问题!

如果你想提供encryptdecrypt的方便方法,那还是很容易的。例如,可以编写如下函数:

1
2
3
4
def encrypt(text, offset):
    cypher = Cypher()
    cypher.offset = offset
    return cypher.encrypt(text)


这是datetime.datetime的docstring:

1
2
3
4
class datetime(date):
   """datetime(year, month, day[, hour[, minute[, second[, microsecond[,tzinfo]]]]])
    ...
   """

施工单位签字:

1
def __new__(cls, year, month=None, day=None, hour=0, minute=0, second=0, microsecond=0, tzinfo=None):

我们可以从中学到什么:

  • 添加尽可能多的参数
  • 使用参数和为参数提供合理的默认值

旁白:您认为您的库的用户应该使用cycleencrypt()吗?您可以将其标记为私有(用下划线),这样每个人都会看到它不是公共API,他们应该使用encrypt()decrypt()


只要没有十几个论点,论点的数量就不重要了(也许有人可以链接到你所提到的超过3个论点,我可能错了)。

为了在函数定义中更易于阅读,请按照docstrings约定编写注释。

为了在函数调用时更具可读性,在定义中尽可能多地为更有用的值提供默认值(例如,默认情况下,偏移可以有值1,索引0)。

无论哪种方式,对于长线,都要使用PEP8指南,该指南描述了正确跨线的方法(根据PEP8,行不能超过80个字符)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def cycleencrypt(string, offset=1, index=0,
                     listing, first, last):
       """Description

        :param string: description
        :param offset: description
        :param index: description
        :param listing: description
        :param first: description
        :param last: description
        :return description
       """

        offset = offsetctrl(offset)
        if string >= ord(first) and string <= ord(last):
            string += offset
            while string > ord(last):
                string = ord(first) + (string - ord(last) - 1)
            listing[index] = chr(string)