Python将代码分割成函数

时间:2017-06-05 14:21:00

标签: python

很抱歉这个长度,但我觉得更多的信息比不够好!

我试图将(工作)的Python代码分割成函数以使其更清晰/更容易使用,但是一旦我将东西转移到函数中,它就会崩溃。它基本上是一个密码生成器,一旦密码符合其中包含来自所有4个类别的字符,它就会尝试仅向用户输出密码。 (小写,大写,数字和符号)。

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

这是我试图分裂它。当我尝试运行下面时,它会抱怨&#34; UnboundLocalError:局部变量&#39; upperascii_score&#39;在转让前引用&#34;在scorepassword_as_a_list()函数中

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

1 个答案:

答案 0 :(得分:1)

这里的主要问题是您需要跟踪您正在使用的各种变量的scope。通常,将代码拆分为函数(如果正确完成)的一个优点是,您可以重用代码而无需担心是否在其他位置修改了任何初始状态。具体来说,在您的特定示例中,即使您的工作正常(使用global变量),每次调用其中一个函数时,您都必须担心,例如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 未重置为0。

相反,你应该接受你的函数需要作为参数运行的任何东西并输出一些返回值,而不需要操纵全局变量。一般来说,这个想法被称为&#34;避免副作用。&#34;以下是您重写的示例:

scorepassword_as_list

关于此的几点说明:

  1. 请注意&#34;得分&#34;变量在内部 *current_score函数中引入,并且(基于scoping rules local 到该函数。我们将它们作为返回值传递出去,从函数中取出它们。
  2. 我在checkscore(current_score[0], current_score[1], current_score[2], current_score[3])附近使用了一点魔法。这里,星号用作&#34; splat&#34;或&#34;解包&#34;运营商。我可以很容易地写出public LoginPageViewModel(IApiService apiService, INavigationService navigationService) { this.apiService = apiService; this.navigationService = navigationService; LoginCommand = new DelegateCommand(Login); this.User = new Users(); } ;他们的意思是一样的。
  3. 在Python中阅读有关变量作用域和命名空间的更多内容可能会有用。 Here's one guide,但可能会有更好的。