在循环中创建类,其中类名来自列表

Nic*_*mps 0 python

我基本上试图从播放列表中提取歌曲名称,然后我想为播放列表中的每首歌创建一个类,其中包括该歌曲的所有相关数据(歌曲标题,艺术家,每首歌曲的位置等)

我有一个列表,其中列表中的每个项目都是歌曲名称.我正在尝试创建一个循环,创建一个以列表中的每个项目命名的新类.

这是我到目前为止:

class MyClass():
    var = "hi"

songNames = ['song1', 'song2', 'song3']

for name in songNames:
    name = MyClass()
Run Code Online (Sandbox Code Playgroud)

这是行不通的,我认为这是因为Python遇到了麻烦/无法为这样的类分配名称.我是Python的初学者,经过广泛的搜索,我无法想出一个解决方案.这样做的正确方法是什么?


所以我一直在研究代码并取得了一些进展:

class SongData(object):
    def __init__(self, title="", artist="", directory=""):
        self.title, self.artist, self.directory = title, artist, directory
    def __str__(self):
        desc_str = "Title: %s \nArtist: %s \nDirectory: %s \n" %(self.title,
                                            self.artist, self.directory)
        print desc_str

songNames = ['song1', 'song2', 'song3']
artistNames = ['artist1', 'artist2', 'artist3']
dirNames = ['dir1', 'dir2', 'dir3']

songs = {name: SongData(title=name) for name in songNames}
artists = {band: SongData(artist=band) for band in artistNames}
directorys = {direc: SongData(directory=direc) for direc in dirNames}
Run Code Online (Sandbox Code Playgroud)

我希望能够desc_str为每首歌打印出来,所以它看起来像这样:

Title: song1 
Artist: artist1 
Directory: dir1
Run Code Online (Sandbox Code Playgroud)

但到目前为止,我只设法在一次呼叫中的一个数据类别,所以它打印Title: song1,但离开Artist:Directory:部分空白.

如何让它一次打印出来?

aba*_*ert 14

你不想为每首歌创建一个类; 你想为每首歌创建一个类的实例.例如:

class Song(object):
    def __init__(self, name):
        self.name = name

songNames = ['song1', 'song2', 'song3']

songs = []
for name in songNames:
    songs.append(Song(name))
Run Code Online (Sandbox Code Playgroud)

请注意,我正在将Song对象存储在列表中.你需要将它们存储在某个地方,或者你以后不能再次访问它们,对吗?

如果您希望以后能够通过名称访问它们,而不是仅仅遍历所有这些:

songs = {}
for name in songNames:
    songs[name] = Song(name)
Run Code Online (Sandbox Code Playgroud)

您可以使用理解将其中任何一个转换为单行:

songs = [Song(name) for name in songNames]
songs = {name: Song(name) for name in songNames}
Run Code Online (Sandbox Code Playgroud)

来自评论:

我曾经打算按类看下面的内容,因为每首歌都会有相同的变量:

class songData: 
    title = "" 
    artist = "" 
    directory = "" 
    tempStr = ""
    def description(self): 
        desc_str = "%s is by %s, located at %s" %(self.title, self.artist,self.directory)
        return desc_str
Run Code Online (Sandbox Code Playgroud)

由于我已经解释过的原因,这是错误的:您正在创建类属性,而不是实例属性.这意味着每个实例都将共享一个标题等,这不是您想要的.此外,这意味着self.title误导(虽然它会起作用).

同时,如果这是Python 2,那么你将再次创建一个经典类.此外,您可能想要一个__str__方法而不是一个特殊的description方法,因为那样你就可以print(song)而不是必须print(song.description()).最后,对变量和类使用相同的命名约定有点令人困惑.

你可能想要的是:

class SongData:
    def __init__(self, title="", artist="", directory=""):
        self.title, self.artist, self.directory = title, artist, directory
    def __str__(self): 
        desc_str = "%s is by %s, located at %s" % (self.title, self.artist,self.directory)
        return desc_str
Run Code Online (Sandbox Code Playgroud)

现在,您可以使用与Song上面的类基本相同的方法:

songNames = ['song1', 'song2', 'song3']
songs = {name: SongData(title=name) for name in songNames}
Run Code Online (Sandbox Code Playgroud)

现在你可以做这样的事情:

name = input('What song do you want info on?') # raw_input, if Python 2
print(songs[name])
Run Code Online (Sandbox Code Playgroud)

(当然这不是很有用,除非你也有代码将艺术家和目录设置在某个地方,因为它只是打印Song Windowlicker is by , located at.但我不知道你打算从哪里获取它们.)


您的新代码有两个问题.第一:

def __str__(self):
    desc_str = "Title: %s \nArtist: %s \nDirectory: %s \n" %(self.title,
                                        self.artist, self.directory)
    print desc_str
Run Code Online (Sandbox Code Playgroud)

你需要在return desc_str这里,而不是print它.


第二:

songNames = ['song1', 'song2', 'song3']
artistNames = ['artist1', 'artist2', 'artist3']
dirNames = ['dir1', 'dir2', 'dir3']

songs = {name: SongData(title=name) for name in songNames}
artists = {band: SongData(artist=band) for band in artistNames}
directorys = {direc: SongData(directory=direc) for direc in dirNames}
Run Code Online (Sandbox Code Playgroud)

在这里,您将创建三个独立的SongData对象集合,每个对象只填充一个属性.

这里的关键是zip.一旦你掌握了它的功能,它就是Python中最有用的功能之一,但在你了解它之前,你永远不会想到它.如果我展示它的作用,则更容易描述:

>>> zip(songNames, artistNames, dirNames)
[('song1', 'artist1', 'dir1'),
 ('song2', 'artist2', 'dir2'),
 ('song3', 'artist3', 'dir3')]
Run Code Online (Sandbox Code Playgroud)

因此,它为您提供了一个元组列表,其中每个元组都有一个歌曲名称,一个艺术家和一个dir.第一个元组是第一元组,第二元组是第二元组,等等.

现在,您可以SongData非常轻松地构建每个元组:

songs = {}
for title, artist, directory in zip(songNames, artistNames, dirNames):
     songs[title] = SongData(title, artist, directory)
Run Code Online (Sandbox Code Playgroud)

作为一个词典理解,它有点冗长:

songs = {title: SongData(title, artist, directory)
         for title, artist, directory in zip(songNames, artistNames, dirNames)}
Run Code Online (Sandbox Code Playgroud)

但你可以用另一个技巧来简化它:解包参数:

songs = {t[0]: SongData(*t) for songtuple in zip(songNames, artistNames, dirNames)}
Run Code Online (Sandbox Code Playgroud)

当然你可以不用这样做zip,但它看起来像一团糟:

songs = {SongData(songNames[i], artistNames[i], dirNames[i])
         for i in range(len(songNames))}
Run Code Online (Sandbox Code Playgroud)

...如果你有一个包含不匹配列表的小错误,那么很难理解和调试这种方式.通常,无论何时for i in range(len(foo))使用Python 编写,都可能有一种简单的方法.


无论你构建它,你都可以按照你的期望使用它:

>>> print songs['song1']
Title: song1 
Artist: artist1 
Directory: directory1
Run Code Online (Sandbox Code Playgroud)

当我们处于它的时候,你可能不希望在每行输出的末尾有一个空格.它对人类来说是不可见的,但它可能会混淆你后来编写的代码来解析输出,并浪费空间,并没有真正的好处.只需把每一个放在\n后面%s.