列表类保留新列表Python的旧值

时间:2015-02-08 09:09:34

标签: python list class object

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

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这是原始列​​表。

有人知道我搞砸了吗?

1 个答案:

答案 0 :(得分:1)

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

替换整个循环:

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

对列表没有任何作用(“替换”该项目。)

使用python的map来将函数应用于iterable并创建结果列表:

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会返回上一个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 []