通过两个函数python维护列表

时间:2019-05-11 18:44:23

标签: python mysql

我正在尝试使用python创建字符选择CLI。

我想显示用户的“当前角色选择方”,以便他们可以看到他们已经选择的人。用户不能两次选择相同的字符。用户必须有4个字符才能继续

我创建了以下代码(我确实称呼它不用担心!):

def ChooseCharacters():
    CharList=[]
    CurrentParty=[]
    print("Select up to 4 explorers!")
    while len(CharList)!=4:
        if len(CharList)!=4:
            if len(CharList)==0:
                pass
            else:
                for CharID in list(set(CharList)):
                    print(CharList)
                    SQL=("SELECT firstname,secondname FROM characters WHERE CharID=%s")
                    mycursor.execute(SQL,(CharID,))
                    myresult=mycursor.fetchone()
                    Name=(myresult[0]+" "+myresult[1])
                    CurrentParty= list(set(CurrentParty))
                    CurrentParty.append(Name)
                print("Current Party: ",CurrentParty)
        PrintChoice(CharList)
def PrintChoice(CharList):
    mycursor.execute("SELECT * FROM characters")
    myresults=mycursor.fetchall()
    Num=0
    for char in myresults:
        Num = Num + 1
        print(str(Num)+("."),char[1],char[2])
    Choice=input("Select Character: ")
    if Choice in CharList:
        print("Character already selected!")
        return
    CharList.append(Choice)
    print(CharList)

似乎第一个选择的字符在列表中重复,其余代码正常工作。

预期结果

Current Party:  ['Sam Jordan']

Current Party:  ['Sam Jordan','Olivia Cope']

Current Party:  ['Sam Jordan','Olivia Cope','Dylan Nesbitt']

实际结果

Current Party:  ['Sam Jordan']

Current Party:  ['Olive Cope', 'Sam Jordan', 'Sam Jordan']

Current Party:  ['Sam Jordan', 'Olive Cope', 'Dylan Nesbitt', 'Sam Jordan']

我无法确定第一个输入的第二次复制发生在哪里,因为第一个输入正确无误。

如果您需要查看数据库表,请询问。

2 个答案:

答案 0 :(得分:1)

您当前的代码有点困难,因为它包含了非常不同类型的活动:从数据库读取,让用户以交互方式进行选择以及常规算法逻辑。此外,代码还依赖于通常最好避免的模式-即,将数据结构传递给其他函数,以便其他函数可以对其进行修改。编写获取数据并返回新数据的函数通常更为简单和明智。

我建议您将其重构以进行更清晰的分离,而不是困惑于如何解决当前代码。这是一个简单的例子:

import string

# A top-level function to orchestrate things.
def choose_characters():
    chars = get_characters_from_db(12)  # Read 12 from DB.
    selected = select_items(chars, 4)   # Select 4 of them.
    print(selected)

# One or more functions to interact with the database.
# In this example we just return some mock data.
def get_characters_from_db(n):
    return string.ascii_uppercase[0:n]

# A general function to have a user select N items.
def select_items(xs, n):
    selected = []
    print('Choices:')
    for i, x in enumerate(xs):
        print(i + 1, x)
    print()
    while len(selected) < n:
        s = input('=> ')
        try:
            i = int(s) - 1
            x = xs[i]
        except Exception:
            print('Invalid entry')
            continue
        if x in selected:
            print('Already selected')
        else:
            selected.append(x)
    print()
    return selected

choose_characters()

答案 1 :(得分:0)

问题出在CurrentPartyCharList列表的处理上。在获取名称的for循环的开头,CurrentParty包含上次选择字符时添加的名称。由于调用CharListset中元素的顺序可能在每次循环执行中发生变化,因此添加到CurrentParty的姓氏可能已经存在。

一个简单的解决方案可能是在每次执行循环时重新初始化CurrentParty,并删除CharList不必要的设置。该功能的简化版本可能是:

def ChooseCharacters():
    CharList = []
    print("Select up to 4 explorers!")
    while len(CharList) < 4:
        PrintChoice(CharList)
        CurrentParty = []
        for CharID in CharList:
            SQL = "SELECT firstname,secondname FROM characters WHERE CharID=%s"
            mycursor.execute(SQL, (CharID,))
            myresult = mycursor.fetchone()
            Name = myresult[0] + " " + myresult[1]
            CurrentParty.append(Name)
        print("Current Party: ", CurrentParty)
    print("Final Party: ", CurrentParty)
    print()

正如用户FMc在其答案中观察到的那样,问题中的代码难以理解。这是代码的一个版本,该版本试图减少重复,对每个函数保持明确的职责并最大程度地减少对数据库的调用。为简单起见,假设mycursor作为全局变量存在。

此代码是使用Python 3.7编写的;如果您使用的是Python的早期版本,请将all_chars设为OrderedDict,以确保行为正确。

def main():
    # Call this function to run the code.
    all_chars = fetch_characters()
    selected = select_characters(all_chars)
    party_ids = map_selection_to_ids(selected, all_chars)
    print_party(party_ids, all_chars)
    # Do rest of the program.
    return


def fetch_characters():
    # Make a dictionary that maps database id to character name.
    all_chars = {}
    stmt = """SELECT CharID, firstname, secondname FROM characters;"""
    mycursor.execute(stmt)
    for id_, firstname, secondname in mycursor.fetchall():
        all_chars[id_] = '{} {}'.format(firstname, secondname)
    return all_chars


def select_characters(all_chars):
    # Display the selection menu.
    # Note the values that the user selects will not necessarily 
    # correspond to the database id.
    selected = set()
    while len(selected) < 4:
        for idx, name in enumerate(all_chars.values(), start=1):
            print('{}. {}'.format(idx, name))
        print()
        choice = input('Select Character: ')
        if choice in selected:
            print("Character already selected!")
            continue
        selected.add(choice)
    return selected


def map_selection_to_ids(selected, all_chars):
    # Given the values selected by the user, get the corresponding 
    # database id.
    party_ids = []
    char_ids = list(all_chars.keys())
    for selection in selected:
        adjusted = int(selection) - 1
        party_ids.append(char_ids[adjusted])
    return party_ids


def print_party(party_ids, all_chars):
    names = []
    for id_ in party_ids:
        names.append(all_chars[id_])
    print(', '.join(names))
    return