我基本上是尝试从播放列表中提取歌曲名称,然后我想为播放列表中的每首歌创建一个类,其中包含该歌曲的所有相关数据(歌曲标题,艺术家,每首歌曲的位置等)。 )
我有一个列表,其中列表中的每个项目都是歌曲名称。我正在尝试创建一个循环,创建一个以列表中的每个项目命名的新类。
这是我到目前为止所做的:
class MyClass():
var = "hi"
songNames = ['song1', 'song2', 'song3']
for name in songNames:
name = MyClass()
这不起作用,我认为这是因为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}
我希望能够为每首歌打印desc_str
所以它看起来像这样:
Title: song1
Artist: artist1
Directory: dir1
但到目前为止,我只设法同时调用一个数据类别,因此它会打印Title: song1
,但会将Artist:
和Directory:
部分留空。
如何让它一次打印出来?
答案 0 :(得分:13)
你不想为每首歌创建一个类;你想为每首歌创建一个类的实例。例如:
class Song(object):
def __init__(self, name):
self.name = name
songNames = ['song1', 'song2', 'song3']
songs = []
for name in songNames:
songs.append(Song(name))
请注意,我正在将Song
个对象存储在列表中。你需要将它们存储在某个地方,或者你以后不能再次访问它们,对吗?
如果您希望以后能够通过名称访问它们,而不是仅仅遍历所有这些:
songs = {}
for name in songNames:
songs[name] = Song(name)
你可以使用理解将其中任何一个转换为单行:
songs = [Song(name) for name in songNames]
songs = {name: Song(name) for name in songNames}
来自评论:
我原本打算按类看下面的内容,因为每首歌都会有相同的变量:
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
由于我已经解释过的原因,这是错误的:你正在创建类属性,而不是实例属性。这意味着每个实例都将共享一个标题等,这不是您想要的。此外,这意味着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
现在,您可以使用与上面的Song
类基本相同的方法:
songNames = ['song1', 'song2', 'song3']
songs = {name: SongData(title=name) for name in songNames}
现在你可以这样做:
name = input('What song do you want info on?') # raw_input, if Python 2
print(songs[name])
(当然这不是很有用,除非你还有代码将艺术家和目录设置在某个地方,因为它只会打印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
您需要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}
在这里,您要创建三个独立的SongData
个对象集合,每个对象只填充一个属性。
这里的关键是zip
。一旦你掌握了它的功能,它就是Python中最有用的功能之一,但在你了解它之前,你永远不会想到它。如果我展示它的作用,则更容易描述:
>>> zip(songNames, artistNames, dirNames)
[('song1', 'artist1', 'dir1'),
('song2', 'artist2', 'dir2'),
('song3', 'artist3', 'dir3')]
因此,它会为您提供一个元组列表,其中每个元组都有一个歌曲名称,一个艺术家和一个dir。第一个元组是第一元组,第二元组是第二元组,等等。
现在你可以很容易地从每个元组中构建一个SongData
:
songs = {}
for title, artist, directory in zip(songNames, artistNames, dirNames):
songs[title] = SongData(title, artist, directory)
作为一个词典理解,它有点冗长:
songs = {title: SongData(title, artist, directory)
for title, artist, directory in zip(songNames, artistNames, dirNames)}
但你可以用另一个技巧来简化它:unpacking arguments:
songs = {t[0]: SongData(*t) for songtuple in zip(songNames, artistNames, dirNames)}
当然你可以在没有zip
的情况下做到这一点,但它看起来像一团糟:
songs = {SongData(songNames[i], artistNames[i], dirNames[i])
for i in range(len(songNames))}
...如果你有一个包含不匹配列表的小错误,那么很难理解和调试这种方式。通常,无论何时在Python中编写for i in range(len(foo))
,都可能有一种简单的方法。
无论你构建它,你都可以按照你的期望使用它:
>>> print songs['song1']
Title: song1
Artist: artist1
Directory: directory1
虽然我们处于此状态,但您可能不希望每行输出结束时有空格。它对人类来说是不可见的,但它可能会混淆你后来编写的代码来解析输出,并浪费空间,并没有真正的好处。只需将\n
放在%s
之后。
答案 1 :(得分:2)
我同意你似乎想要为每首歌创建一个实例而不是一个类。但是如果你想为每首歌创建一个类,请使用type(className, parentTuple, attributeDict)
函数。它返回一个具有给定名称的新类。
E.g。
songClasses = []
for name in songNames:
songClasses.append(type(name, (), {}))