RubyのForwardableモジュールをPythonでも

30分プログラム、その624。RubyForwardableモジュールPythonに移植してみた。委譲
とか好きだからー。

Forwardableは、単に委譲するだけのメッソドを手書きするのはバカらしいから、簡単に書けるようにするモジュール。くわしくは、るびまを見るといいと思います。

Rubyみたいにクラスを定義してる途中でクラスオブジェクトを取得する方法が分からなかったので、ちょっと無理をしている。

class Stack():
    # ホントはここでごにょごにょしたい
    # でも、まだStackクラスには触れないのでガマンする
    def __init__(self):
        self.s = []

# ここで初めてStackに触れる
delegate(Stack,'__repr__','s')

使い方

class Stack():
    def __init__(self):
        self.s = []

# Stackの__repr__として、self.s.__repr__を使う
delegate(Stack,'__repr__','s')

# pushとpopに名前を変える
delegate(Stack,'push','s','append')
delegate(Stack,'pop','s','pop')

stack = Stack()
stack.push(1)
stack.push(2)
stack.push(3)

print stack # => [1,2,3]

print stack.pop() # => 3
print stack.pop() # => 2
print stack.pop() # => 1

ソースコード

#! /usr/bin/python
# -*- mode:python; coding:utf-8 -*-
#
# forwardable.py -
#
# Copyright(C) 2009 by mzp
# Author: MIZUNO Hiroki / mzpppp at gmail dot com
# http://howdyworld.org
#
# Timestamp: 2009/07/21 21:13:33
#
# This program is free software; you can redistribute it and/or
# modify it under MIT Lincence.
#

def delegate(klass,klass_attr,target,target_attr=None):
    target_attr = target_attr if target_attr else klass_attr
    def f(self,*args):
        return apply(getattr(getattr(self,target),target_attr),args)
    setattr(klass,klass_attr,f)

class Stack():
    def __init__(self):
        self.s = []
delegate(Stack,'__repr__','s')
delegate(Stack,'push','s','append')
delegate(Stack,'pop','s','pop')

stack = Stack()
stack.push(1)
stack.push(2)
stack.push(3)

print stack # => [1,2,3]

print stack.pop() # => 3
print stack.pop() # => 2
print stack.pop() # => 1