如何正确创建 returns 从 python 中的文件生成的列表的列表子类?

How to properly create a list subclass that returns a list generated from file in python?

我 运行 遇到一些子 classing 问题。

我需要创建一个继承列表属性的 class 但我需要 returned 列表 (self.tiles_pool) 是一个在构造 class 时创建。该列表由外部 CSV 文件生成。我尝试在没有继承的情况下创建 class,但很快意识到如果不创建单独的方法就无法 return 我的列表。但是我需要 class 的实例是一个列表对象(即在我打印对象时打印生成的列表)。 class 用于创建拼贴池,例如拼字游戏中的字母拼贴袋。

如果有某种方法 returning 我的列表 (self.tiles_pool) 无需继承不使用用户定义的方法会更好。

到目前为止,这是我的代码:

import csv
import random


class TilePool(list):
    def __init__(self):
        list.__init__(self)

        # Open csv file
        with open("tiles.csv") as f:
            # Read csv into list of lists of each lines values
            tiles_csv = csv.reader(f, delimiter=",")

            # Convert the list into a tile pool
            self.tiles_pool = [(line[0], line[1])
                               for line in tiles_csv if len(line[0]) == 1
                               for x in xrange(int(line[2]))]

            del tiles_csv

    def pop(self, tile_count=None):
        assert len(self.tiles_pool) > 0, "# Tile Pool is empty"

        if tile_count is None:
            tile_count = 7

        assert tile_count in xrange(1, 8), "# Tile Count must be between 1 and 7"

        new_tiles = []
        counter = 1
        while len(self.tiles_pool) > 0 and counter <= tile_count:
            rand_choice = random.choice(self.tiles_pool)  # Get a random tile
            new_tiles.append(rand_choice)  # Add it to new_tiles list
            self.tiles_pool.remove(rand_choice)  # Delete it from pool

            counter += 1

        return new_tiles

    def view_pool(self):
        if len(self.tiles_pool) == 0:
            print("# Tile Pool is empty")

        else:
            for tile in self.tiles_pool:
                print("{letter}: {score}".format(letter=tile[0], score=tile[1]))

            print len(self.tiles_pool)

我知道这个实现可能看起来很奇怪,我可能只是把它放在一个函数中,但我正在按照指示将它变成 class。任何帮助或建议将不胜感激。谢谢

如果您不使用它,为什么要子类化 listself就是你想要的列表,不需要再创建tiles_pool。由于列表可以用序列初始化,延迟父 __init__ 直到你可以将 csv 提供给它。你的代码做了一些我不明白的事情,比如复制图块 line[2] 次,但我想你知道你在那里做什么。

在此示例中,我删除了 tiles_pool 以支持使用 self 并进行了一些其他调整,例如使用列表的 "truthiness"(bool([1]) is Truebool([]) is False) 而不是使用 len 但它应该和原来的一样工作。

import csv
import random


class TilePool(list):
    def __init__(self):
        with open("tiles.csv") as f:
            tiles_csv = csv.reader(f, delimiter=",")
            list.__init__(self, (line[0:2]
                           for line in tiles_csv if len(line[0]) == 1
                           for x in xrange(int(line[2]))))


    def pop(self, tile_count=None):
        # non-empty list is truthy
        assert self, "# Tile Pool is empty"

        if tile_count is None:
            tile_count = 7

        assert tile_count in range(1, 8), "# Tile Count must be between 1 and 7"

        new_tiles = []
        counter = 1
        while self and counter <= tile_count:
            rand_choice = random.choice(self)  # Get a random tile
            new_tiles.append(rand_choice)  # Add it to new_tiles list
            self.remove(rand_choice)  # Delete it from pool
            counter += 1
        return new_tiles

    def view_pool(self):
        if not self:
            print("# Tile Pool is empty")
        else:
            for tile in self:
                print("{letter}: {score}".format(letter=tile[0], score=tile[1]))
            print len(self)

t = TilePool()
t.pop(3)
t.view_pool()

如果您想避免继承和用户定义的方法,我会利用 python 的 magic 方法来实现。