Python将代码分割成函数

Python splitting code into functions

本问题已经有最佳答案,请猛点这里访问。

抱歉,这个长度,但我认为更多的信息比不够好!!

我正试图将(正在工作的)python代码分割成函数,以使其更清晰/更容易使用,但一旦我将这些代码转换成函数,它们就会失去联系。它基本上是一个密码生成器,它只在密码符合所有4个类别的字符条件时,尝试向用户输出密码。(小写、大写、数字和符号)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import random
import string
lowerasciis = string.ascii_letters[0:26]
upperasciis = string.ascii_letters[26:]
numberedstrings = str(1234567809)
symbols ="!@$%^&*()[]"
password_length = int(raw_input("Please enter a password length:"))

while True:
    lowerasscii_score = 0
    upperascii_score = 0
    numberedstring_score = 0
    symbol_score = 0
    password_as_list = []

    while len(password_as_list) < password_length:
        char = random.choice(lowerasciis+upperasciis+numberedstrings+symbols)
        password_as_list.append(char)
    for x in password_as_list:
        if x in lowerasciis:
            lowerasscii_score +=1
        elif x in upperasciis:
            upperascii_score +=1
        elif x in numberedstrings:
            numberedstring_score +=1
        elif x in symbols:
            symbol_score +=1
# a check for the screen. Each cycle of the loop should display a new score:
    print lowerasscii_score, upperascii_score, numberedstring_score, symbol_score

    if lowerasscii_score >= 1 and upperascii_score >= 1 and numberedstring_score >= 1 and symbol_score >=1:
        password ="".join(password_as_list)
        print password
        break

这是我试图分裂它的尝试。当我尝试运行下面的命令时,它会在scorepassword_中抱怨"unboundlocalerror:local variable'upperascii_score'referenced before assignment"as_a_list()函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import random
import string
lowerasciis = string.ascii_letters[0:26]
upperasciis = string.ascii_letters[26:]
numberedstrings = str(1234567809)
symbols ="!@$%^&*()[]"
password_length = int(raw_input("Please enter a password length:"))
lowerasscii_score = 0
upperascii_score = 0
numberedstring_score = 0
symbol_score = 0
password_as_list = []

def genpassword_as_a_list():
    while len(password_as_list) < password_length:
        char = random.choice(lowerasciis+upperasciis+numberedstrings+symbols)
        password_as_list.append(char)

def scorepassword_as_a_list():
    for x in password_as_list:
        if x in lowerasciis:
            lowerasscii_score +=1
        elif x in upperasciis:
            upperascii_score +=1
        elif x in numberedstrings:
            numberedstring_score +=1
        elif x in symbols:
            symbol_score +=1
    # give user feedback about password's score in 4 categories
    print lowerasscii_score, upperascii_score, numberedstring_score, symbol_score

def checkscore():
    if lowerasscii_score >= 1 and upperascii_score >= 1 and numberedstring_score >= 1 and symbol_score >=1:
        return 1
    else:
        return 0

def join_and_printpassword():
    password ="".join(password_as_list)
    print password  

while True:
    genpassword_as_a_list()
    scorepassword_as_a_list()
    if checkscore() == 1:
        join_and_printpassword()
        break


这里的主要问题是,您需要跟踪正在使用的各种变量的范围。通常,将代码拆分为函数(如果操作得当)的好处之一是,可以重用代码,而不必担心是否在其他地方修改了任何初始状态。具体来说,在您的特定示例中,即使您使事情正常运行(使用全局变量),每次调用某个函数时,您都必须担心,例如lowerassci_score没有重置为0。

相反,您应该接受函数作为参数运行并输出一些返回值所需的任何内容,而不需要操纵全局变量。一般来说,这一想法被称为"避免副作用"。下面是重新编写的示例,请记住:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
import random
import string
lowerasciis = string.ascii_letters[0:26]
upperasciis = string.ascii_letters[26:]
numberedstrings = str(1234567809)
symbols ="!@$%^&*()[]"

def genpassword_as_a_list(password_length):
    password_as_list = []
    while len(password_as_list) < password_length:
        char = random.choice(lowerasciis+upperasciis+numberedstrings+symbols)
        password_as_list.append(char)
    return password_as_list

def scorepassword_as_a_list(password_as_list):
    lowerasscii_score = 0
    upperascii_score = 0
    numberedstring_score = 0
    symbol_score = 0
    for x in password_as_list:
        if x in lowerasciis:
            lowerasscii_score +=1
        elif x in upperasciis:
            upperascii_score +=1
        elif x in numberedstrings:
            numberedstring_score +=1
        elif x in symbols:
            symbol_score +=1
    # give user feedback about password's score in 4 categories
    return (
        lowerasscii_score, upperascii_score, numberedstring_score,
        symbol_score
    )

def checkscore(
        lowerasscii_score, upperascii_score, numberedstring_score,
        symbol_score):
    if lowerasscii_score >= 1 and upperascii_score >= 1 and numberedstring_score >= 1 and symbol_score >=1:
        return 1
    else:
        return 0

def join_and_printpassword(password_as_list):
    password ="".join(password_as_list)
    print password  

password_length = int(raw_input("Please enter a password length:"))

while True:
    password_list = genpassword_as_a_list(password_length)
    current_score = scorepassword_as_a_list(password_list)
    if checkscore(*current_score) == 1:
        join_and_printpassword(password_list)
        break

关于这方面的一些注意事项:

  • 注意,在scorepassword_as_list函数中引入了"score"变量,并且(基于作用域规则)是该函数的局部变量。我们通过将它们作为返回值传递出去,将它们从函数中去掉。
  • 我用了一点魔法在接近尾声的时候使用了*current_score。在这里,星号用作"splat"或"unpack"操作符。我可以很容易地写下checkscore(current_score[0], current_score[1], current_score[2], current_score[3]),它们的意思是相同的。
  • 在python中进一步阅读变量范围和名称空间可能会很有用。这里有一个指南,但可能有更好的。