Damon Timm wrote:
Hi Everyone - thanks for your responses. Answered my direct questions:
[1] can't be done at the top and
actually you can, but it's opening a can of worms that I wouldn't dare
to go near:
VIDEO_RE = {
re.compile(r'regex here'): 'Youtube',
re.compile(r'regex there'): 'Vimeo',
re.compile(r'regex over here'): 'Blip',
)
or
VIDEO_TYPES = {
'Youtube': re.compile(r'regex here'),
'Vimeo': re.compile(r'regex here'),
'Blip': re.compile(r'regex here'),
}
[2] would have to move the tuple somewhere else
as well as gave me some new ideas about completely rethinking the
design ... I love keeping the RE definitions with the child classes
... makes it easy just to add a child anywhere without having to fool
with the original code.
One of my issues has been fixed using the @staticmethod decorator
(which I did not know about). Here is what I have now, and my final
question (perhaps) follows.
####
#this is a django app, by the way
class Video(models.Model):
url = models.URLField('Video URL')
# more fields and functions here
def sync(self):
'Update videos external data - for children only'
pass
You may want to raise an exception or `assert False` here since
Video.sync() should never be called (because children class must always
override it). Alternatively, you can just not define sync so it raises
AttributeError.
@staticmethod
def add_video(url):
'add a video only if it matches correct regex -- need ExceptionHandler'
for sc in Video.__subclasses__():
if sc.RE.match(url):
return sc(url=url)
class YoutubeVideo(Video):
RE =
re.compile(r'([^(]|^)http://www\.youtube\.com/watch\?\S*v=(?P<youtubeid>[A-Za-z0-9_-]+)\S*')
def sync(self):
# do custom syncing here
print "am syncing a YOUTUBE video"
class ViemoVideo(Video):
RE = re.compile(r'([^(]|^)http://(www.|)vimeo\.com/(?P<vimeoid>\d+)\S*')
def sync(self):
# do custom syncing here
print "am syncing a VIMEO video"
##############
So, this is *great* because now I can "add_video" without knowing the
video url type at all.
v = Video.add_video(url="http://www.youtube.com/watch?v=UtEg3EQwN9A")
v
<YoutubeVideo: >
Perfect! The last part is figuring out the syncing -- what I would
like to do would be either:
Video.sync_all_videos() #create another static method
Or, if I had to, create another function that did a:
for video in Video.objects.all(): # object.all() is a django function that
returns everything
... video.sync()
However, I am not sure how to determine the "actual" class of a video
when I am dealing only with the parent. That is, how do I call a
child's sync() function when I am dealing the parent object?
Just run v.sync(); python's object model will determine the correct
.sync() to call (i.e. v.sync() will call YoutubeVideo.sync(v) if
isinstance(v, YoutubeVideo); OR ViemoVideo.sync(v) if isinstance(v,
ViemoVideo); etc). This is known as `polymorphism`, in OOP terms.
As
suggested (in email below) I could re-run the regex for each parent
video for each sync, but that seems like it could be an expensive
operation (supposing one day I had thousands of videos to deal with).
You're on the right mindset. It's not just an expensive operation,
rechecking the url type on every function calls defeats the whole
purpose of OOP. Check the url type only once when you instantiate the
video container class, and use polymorphism for the rest of the day.
_______________________________________________
Tutor maillist - Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor