2012年9月13日 星期四

Python動態改變繼承的父類別

最近在研究Trillr的原始碼,發現在其程式中,有一段Code是如下寫的:

class UserMixin(object):
    """
    Additional methods for users.
    """
    def user_timeline(self):
        return self.statuses.all().order_by('-created_at')

    def friends_timeline(self):
        friends = self.get_friends() + [self]
        return Status.objects.filter(user__in=friends).order_by('-created_at')
 
    def get_friends(self):
        # this was expensive
        return [f.target for f in self.friends.select_related('target')]

    def get_followers(self):
        # this was expensive
        return [f.follower for f in self.followers.select_related('follower')]
 
    def get_followers_count(self):
        return Following.objects.filter(target=self).exclude(follower=self).count()
 
if len(User.__bases__) == 1: User.__bases__ += (UserMixin,)

透過Object.__bases__+=去改變物件的__bases__屬性。

Google一下在Python __bases__屬性的用途如下
From Gossip@caterpillar:在Python中,類別有個__bases__特性,記錄著所繼承的父類別,__bases__是個 Tuple,有趣的是,你可以改變__bases__來動態改變繼承的父類別。
所以Trillr在此處透過這樣的方式讓User可以多重繼承本身的繼承物件外,也繼承了UserMixin的Class,這樣就可以很方便的透過django.contrib.auth.models的User物件去使呼叫這些function。這個方法可以使django的物件簡單的去呼叫自定的function,這樣程式碼應該能更簡單漂亮,學了一課。

參考資料:
  1. Python Gossip: 繼承

沒有留言:

張貼留言