列表 class 为新列表 Python 保留旧值

List class retaining old values for new list Python

我用一些简单的方法创建了一个列表class。

class ListQ(object):
    """List object creation"""
    def __init__(self, earlier_list=[]):
        self.list=earlier_list

    def isEmpty(self):
        """checks if list is empty"""
        if len(self.list)==0:
            return(True)
        else:
            return(False)

    def put(self, new_item):
        """puts new_item last in list"""
        self.list.append(new_item)

    def get(self):
        """returns the next item in line"""
        self.first_item = self.list.pop(0)
        return self.first_item

我还有一个功能可以帮助创建这些列表。 (帮助解决魔术纸牌戏法)

def create_card_list(card_list=None):
    """creates listQ of cards from user input"""
    if card_list!=None: #if user already has list of cards
        for item in card_list:
            item=replace_card_strings(item) #replaces any strings in list
            if item == False:
                print('One of your cards does not exist, list creation failed')
                return(False)
        cards=ListQ(card_list)

replace_card_strings() 函数已经过正确测试,我不认为它有问题,但无论如何它都在这里。

def replace_card_strings(word):
    """replaces strings of words with their numbers and returns edited list"""
    if type(word)!=int:
        if word.lower()=='one':
            word=1
        elif word.lower()=='two':
            word=2
        elif word.lower()=='three':
            word=3
        elif word.lower()=='four':
            word=4
        elif word.lower()=='five':
            word=5
        elif word.lower()=='six':
            word=6
        elif word.lower()=='seven':
            word=7
        elif word.lower()=='eight':
            word=8
        elif word.lower()=='nine':
            word=9
        elif word.lower()=='ten':
            word=10
        elif word.lower()=='jack':
            word=11
        elif word.lower()=='queen':
            word=12
        elif word.lower()=='king':
            word=13
        elif word.lower()=='ace':
            word=1
        else:
            word=False #if card doesnt exist
    return(word)

当我运行下面的测试是问题开始的时候。

cards=create_card_list(['one', 2, 3])
one=cards.get()
two=cards.get()
three=cards.get()
print(one, two, three)
if one==1 and two==2 and three==3:
    print("create_card_list gives the correct answer")
else:
    print("create_card_list gives the wrong answer")

它打印函数给出了错误的答案并且 print(one, two, three) 打印 one 2 3 这是原始列​​表。

有人知道我哪里搞砸了吗?

您不是在替换列表中的项目,只是在循环的上下文中:

替换整个循环:

    for item in card_list:
        item=replace_card_strings(item) #replaces any strings in list
        ....

它不会对列表做任何事情(它不会 "replace" 项目)。

使用 python 的 map 用于将函数应用于可迭代对象并创建结果列表:

card_list = map(replace_card_strings, card_list)

如果你不想使用 map 你可以使用 list comprehension:

card_list = [replace_card_strings(card_str) for card_str in card_list]

现在您将拥有:

def create_card_list(card_list=None):
    """creates listQ of cards from user input"""
    if card_list != None:
        card_list = map(replace_card_strings, card_list)
    cards=ListQ(card_list)

提示:

你可以替换冗长的函数replace_card_strings:

def replace_card_strings(word):
    """replaces strings of words with their numbers and returns edited list"""

    word = word.lower()

    string_to_int = {"one":1, "two":2 ...}

    return word in string_to_int and string_to_int[word]

这是因为 and returns 最后一个 Truth-y 结果或第一个 False-y 结果。

你也可以使用dict.get:

# return word in string_to_int and string_to_int[word]
# try and read value from dict, return False otherwise
return string_to_int.get(word, False)

哪个更干净(感谢@padraic)。

提示 2:您不希望两个地方引用并可能改变同一个列表。看起来您正在保留对用于在生成的对象之外构建卡片列表的同一列表的引用。这很容易出错。您应该做的是在通过时复制列表:

def __init__(self, earlier_list=[]):
    self.list=earlier_list[:]

提示 3: python 有一个 known "gotcha" with mutable default argument,这正是您在这里使用的 (earlier_list=[])。这也很容易出错,因为 python 绑定默认参数一次。你应该改为:

def __init__(self, earlier_list=None):
    # copy passed list or create a new one if none passed.
    self.list=earlier_list[:] if earlier_list else []