I have a method that takes a generator, converts it into a tuple to sort it, then into a list. It works perfectly, but being as I am fairly new to the Python world, I keep asking myself if it is worth doing or not...
@property
def tracks(self):
if 'tracks' not in self.cache:
s = Search(Track)
q = {'query': self.name}
if self.artists[0]['name'] != 'Various Artists':
q.update({'artist': self.artists[0]['name']})
_, tracks = s.search(**q)
tracks = sorted(((int(i.track_number), i) for i in tracks))
self.cache['tracks'] = [t for n, t in tracks]
return self.cache['tracks']
I could care less about track_number as the track[i] already has that information, I'm just using it to sort the track list. s.search(**q) generates a generator of Track instances from a json object, I sort the track list, then I turn it back to a generator for an output.
Is there a better way? Should I just deal with the track number being there?
for _, track for Album.tracks:
# work with track
Update:
The way the backend API works it only requires the first artist in the search, on a collaborated album of various artists, it just gives Various Artists, hence the self.artists[0]['name'] which is usually the only item in the list anyways.
And I know q['key'] = value is better practice than q.update({key: value}), originally it was taking more than a few items, hence the use of .update(), I just never changed that part.
The method is being called in Album.tracks where s = Search(Track) tells the Search class to use the Track class.
## models.py
class Album:
@property
def tracks(self):
s = Search(Track)
## search.py
class Search(Service):
def __init__(self, model):
self.model = model
Instead of:
## models.py
class Album:
@property
def tracks(self):
s = Search('track')
## search.py
from models import *
MODELS = {
'album': Album,
'artist': Artist,
'track': Track
}
class Search(Service):
def __init__(self, model):
self.model = MODELS[model]
Search calls a backend api service that returns queries in JSON objects which then generates instances based on what self.model is set to. s = Search(Tracks) tells Search to call the track api and iterate through the results and return Track instances.
The main question here is, the current method that I have, is it doing too much? It generates the Track instances from the Search.search() generator, which is a somewhat abstract method for calling the api service for Album, Artist, and Track so it does nothing but generating instances based on what model it is given. Which is why I then have Album.tracks create a tuple so that I can sort the tracks base on track number, and then return a list of the tracks, nice and sorted.
Main point: Should I be worried about getting rid of the track numbers and just return the tuple, or is it fine to return the list?
Update 2:
class Album:
@property
def tracks(self):
if 'tracks' not in self.cache:
s = Search(Track)
q = {'query': '', 'album': self.name}
if self.artists[0]['name'] != 'Various Artists':
q['artist'] = self.artists[0]['name']
_, tracks = s.search(**q)
self.cache['tracks'] = sorted(tracks,
key = lambda track: int(track.track_number))
return self.cache['tracks']
class Track(BaseModel):
def __repr__(self):
artist = ', '.join([i['name'].encode('utf-8') for i in self.artists])
track = self.name.encode('utf-8')
return '<Track - {artist}: {track}>'.format(artist=artist, track=track)
Calling it:
album_meta = Search(Album)
results = album_meta.search('making mirrors', artist='gotye')
for album results:
print album.tracks
''' Output
[<Track - Gotye: Making Mirrors>,
<Track - Gotye: Easy Way Out>,
<Track - Gotye, Kimbra: Somebody That I Used To Know>,
<Track - Gotye: Eyes Wide Open>,
<Track - Gotye: Smoke And Mirrors>,
<Track - Gotye: I Feel Better>,
<Track - Gotye: In Your Light>,
<Track - Gotye: State Of The Art>,
<Track - Gotye: Don’t Worry, We’ll Be Watching You>,
<Track - Gotye: Giving Me A Chance>,
<Track - Gotye: Save Me>,
<Track - Gotye: Bronte>] '''