Make組ブログ

Python、Webサービスや製品開発、ライブラリー開発についてhirokikyが書きます

Pythonでバウンドインナークラスを使う (Python Advent Calendar 2013 最終日)

Pythonでバウンドインナークラスを使う (Python Advent Calendar 2013 最終日)

Python Advent Calendar 2013 25日目のブログ記事です。

Python Advent Calendarでは例年最終日にはゲストをお迎えして記事を書いてもらっています。今年は Python 3.4 のリリースマネージャーである Larry Hastings さんに書いていただきました。

Larry, thank you very much for your posting to this Python Advent Calendar!

ここでは日本語訳を書いていきたいと思います!

Pythonでバウンドインナークラスを使う

Python において、関数をクラス中に定義した際にはある魔法が起こります。 クラスのインスタンスを通して関数にアクセスした場合単なる関数が得られるわけではありません。 代わりに新しいオブジェクト「メソッド (method)」と呼ばれるものが返ります。 概念的にはこの関数はインスタンスに「バウンド/束縛 (bound)」されています。 実際にメソッドを呼んだ際にはそのインスタンスが関数の第一引数に自動的に 渡されます。別の位置引数 (potitional argument)は1つ後ろに追いやられます。

しかしこの魔法は関数にしか有効ではありません。クラスについて考えてみましょう。 Pythonでは、あるクラス C を別のクラス D 内に定義した際に、この C を 「インナークラス (inner class)」と呼びます (「ネステッドクラス (nested class)」かもしれません)。 D のインスタンスを通して C にアクセスした場合、 さきほどのような魔法はおこらず、単に C が返されます。 C を呼び出したとしても C.__init__ への引数は変わりません。

インナークラスが Python で使われることは稀です。なぜでしょうか。 それをする実用的な利点が無いからです。 Python のスコープルールによって面倒が生じます (後述)。

それでも私は Python でインナークラスをよく使います。 概念的に他のクラス内にあるべきクラスの場合です。 大抵の場合インナークラスはアウタークラスに “バウンド” されて欲しいものです。 しかしこのように、手動でする必要があります:

class D:
    class C:
        def __init__(self, outer):
            self.outer = outer
d = D()
c = d.C(outer)

関数がするように、インナークラスも “バウンド” されると良さそうです。 アウタークラスが自動的にインナークラスの __init__ に渡されると良さそうです。

でもこれって Python でできることなんでしょうか? 数年前、 Stack Overflow で聞いてみました:

http://stackoverflow.com/questions/2278426/inner-classes-how-can-i-get-the-outer-class-object-at-construction-time

返答には驚きました。それが不可能というだけでなく、意味がないと言うからです。 その後に Alex Martelli が、それは可能だと教えてくれました。 その解法には心底驚かされましたよ!彼の解法はクラスデコレーターを使って、 クラスを「ディスクリプター (descriptor)」にするというものでした。 これは関数がメソッドになるのと全く同じメカニズムです。実に素晴らしい!

Alexの許可を得て、私はこれを「レシピ」として、 Python Cookbookに投稿しました:

http://code.activestate.com/recipes/577070-bound-inner-classes/

このアプローチには何度も手直しをしました。今ではちゃんと動作しますよ! そして…そうなんです、このレシピは Python 2 と 3 両方で変更なしに動作します。

このバウンドインナークラス (bound inner class) のことは本当に気に入っていますし、 可能であればどこでも使います。バウンドインナークラスを人に教えたときの 一番よくあるフィードバックは 「それのユースケースは?」ですが、 私の回答はこうです「メソッド呼び出しのユースケースは?」 私が思うに、この2つは全く同じ質問です。そしてバウンドインナークラスは メソッドと同じくらい便利なものであるとオススメしておきます。 もしかしたらそれ以上かもしれません!

もちろん、クラスは関数よりも複雑なものです。つまりはバウンドインナークラスは メソッドよりも複雑です。例えば継承と2レベル以上のネストとなるとちょっと ややこしいことになります。 こんな場合でもバウンドインナークラスが実用的で、理解しやくなるよう 考えてみました。どう動作するかを少し理解して、いくつか単純なルールに従う 必要があります。これについては、上記の「レシピ」にすべて記載されています。

ぜひ皆さんのコードでもバウンドインナークラスを使ってみてください!

なぜインナークラスが不便になり得るかを疑問に思ってるかもしれませんね。 以下について考えてみてください:

class D:
    value = 5
    class C:
        value2 = value * 5

このコードは動作しません、 value について NameError を送出します。 C のコード中では value が見えないのです。 D のどのメンバーも見えません。 C が見えるすべてのメンバーはグローバルとビルドインです。 (残念ながら nonlocal キーワードもここでは助けになりません。 これはネストした関数でのみ有効で、クラス本体はネストした関数のようには 振る舞いません)

ここで、コードをこんな感じに変えてみましょう:

class D:
    value = 5
    class C:
        value2 = D.value * 5

悲しいことに、これもまた動作しません。 D はまだ存在しないからです。技術的には、 D は “まだバウンドされていません"。 このコードは D についての NameError を送出します。

唯一動作するのは、ルックアップをランタイムで行うことです:

class D:
    value = 5
    class C:
        def __init__(self):
            self.value2 = D.value * 5

言い換えると、コンパイルタイムにおいてネストしたクラスは アウタークラスのどのメンバーにもアクセスできないということです。

追伸、クリスマスを楽しむ日本の読者の皆様へ。 私が皆さんに教えてあげたいのは、実際にはアメリカ人は KFC をクリスマスに食べないということです!これは日本の KFC が創りだしたマーケティング上のギミックなのです。アメリカ人は家族でのディナーを盛大に行うものですが、伝統的なメインコースというものはありません。

以上です。

Larryさん、ありがとうございました!

(なおフッターにあるCC-BYの表記はこの記事においては有効ではありません。 The above expression about CC-BY is not available at this entry.)

Think about expression of blocks as 1 byte

Think about expression of blocks as 1 byte

This blog post for my unimportant memo.

I am creating genaa, a ASCII Art generator.

Now, It can rendering text box like this:

┌────────────────────┐
│Shut the f**k up and│
│write some code!    │
└────────────────────┘

And, I am considering about expression of blocks as 1 byte for providing new rendering feature for genaa.

Free blocks

The feature is rendering some blocks from sigunature. How can we express the following block as plain text?:

┌─┐

┌─┘ └─┐ └─────┘

(As you know, it’s the most gentle block on Tetris)

I noticed the block can be expressed by 6 characters:

69C
D47

Each characters mean the lines of the block. One character is actually hex, and each digits mean corresponding lines:

1

┌─┐

8 │ │ 2 : └─┘ : 4

And the sum of line numbers is the above character. For instance, 6 means ‘bottom’ and ‘right’:

│ 2

──┘ : 4

(Ofcause, this expression may contain some redundancies, like ‘28’)

This may be powerful and useful to render some blocks. But, the bad points is hard to read and write as plain text.

Using .raw method of Django's QuerySet

Using .raw method of Django’s QuerySet

Today, I show you to use .raw method of Django’s QuerySet. The method is powerful and it can manipurate data in DB even if a column is not appear in Model’s field.

Of cause you can choice to use executing raw query by db connection directory. But, using raw method of QuerySet is more comfy. The method allow you to map the values in DB to the objects manually.

Ok, now let me show you a example. Consider a model calss, named Post, like this:

class Post(models.Model):
    title = models.CharField(max_length=255)
    body = models.CharField(max_length=255)

The model is simple and common what in like everyday we write. And then, try to change the schema of it directory:

sqlite> ALTER TABLE demoapp_post ADD COLUMN "slug" varchar(255);
sqlite> .schema demoapp_post
CREATE TABLE "demoapp_post" (
    "id" integer NOT NULL PRIMARY KEY,
    "title" varchar(255) NOT NULL,
    "body" varchar(255) NOT NULL,
    "slug" varchar(255));

just now, I added a column named ‘slug’. The column and model fields have a difference now. This ‘slug’ appears in sqlite db column, but not in the model.

And try to insert a row:

sqlite> INSERT INTO demoapp_post ("title", "body", "slug") VALUES ("test", "test body", "test slug");
sqlite> SELECT * FROM demoapp_post;
1|test|test body|test slug

Then let’s consider how we can get the value of slug (‘test slug’).

Use .raw method

The easiest way is ‘adding a field to the model and migrating the existed DB’. Yes, I know. but, sometime we should get a value from DB even if the column is not in the model fields.

Then, you might want to use raw method?

We can write a SQL directory as a argument to raw method. and the return value of the SQL will be mapped to a Model called the raw method, like this:

>>> post = Post.objects.raw("SELECT * FROM demoapp_post")[0]
>>> post.title
u'test'
>>> post.body
u'test body'
>>> post.slug
u'test slug'
>>> post.nothing
Traceback (most recent call last):
 File "<console>", line 1, in <module>
AttributeError: 'Post' object has no attribute 'nothing'

Yeah! the value of ‘slug’ was showed up. In common way, we can’t get the vaule..:

>>> post = Post.objects.all()[0]
>>> post.title
u'test'
>>> post.body
u'test body'
>>> post.slug
Traceback (most recent call last):
 File "<console>", line 1, in <module>
AttributeError: 'Post' object has no attribute 'slug'

Mapping the attribute more flexible

And then, by specifying the ‘translations’ attribute, we can change the mapping from DB value to Model attribute.

Ok next, let’s try to get the value of ‘slug’ column, through ‘urlslug’ attribute of a model:

>>> post = Post.objects.raw("SELECT * FROM demoapp_post", translations={'slug': 'urlslug'})[0]
>>> post.slug
Traceback (most recent call last):
  File "<console>", line 1, in <module>
AttributeError: 'Post' object has no attribute 'slug'
>>> post.urlslug
u'test slug'

aw, it’s spookey, though.

(I checked above codes with Django 1.6)

Python3.4のSingle-dispatchで遊んでみた - Python Advent Calendar 2013

Python3.4のSingle-dispatchで遊んでみた - Python Advent Calendar 2013

Python Advent Calendar 2013 の 1 日目を担当します、 @hirokiky です。 昨年 に引き続きPythonAdventCalendarを主催しています。

ちなみに今年は現時点であと 4 人参加者が足りません!ぜひご参加ください

さて、今年の Python Advent Calendar のテーマは ‘Not Web’ ということなので、 Web に限らない話を書きます。

つい最近の11月24日に Python 3.4 の Beta 1 がリリースされました。 Python 3.4 b1 には無事 ensure-pip も入り、いよいよ Python 3 感が増してきました。 そんなところですが、ここで Python 3.4 から入る singleddispatch で遊んでみました。

single-dispatchって何?

singleddispatch は functools の一つで、第一引数の型に応じて処理を変更する generic function を作るものです。

単純な例で試してみます:

from functools import singledispatch

@singledispatch
def fun(arg):
    return 'default'

## Registering behaviors to correspond to each types

@fun.register(int)
def fun_int(arg):
    return 'int'

@fun.register(list)
def fun_list(arg):
    return 'list'

assert fun(3) == 'int'
assert fun([]) == 'list'
assert fun('str') == 'default' # str type is not registered.

assert fun_int('dummy') == 'int'
assert fun_list('dummy') == 'list'
assert fun(object()) == 'default'  # Using 'instance of object' to test the default behavior.

ポイント:

  • singledispatch によって generic function を定義
  • .registerによって、型と対応する処理を登録
  • 通常の関数のように generic function を呼び出す

アンチパターン

さきほどあげた例では少し簡単すぎるので、利点が伝わりにくいかもしれません。 なのでここで、アンチパターンをあげておきます:

def fun(arg):
    if isinstance(arg, int):
        return 'int'
    elif isinstance(arg, list):
        return 'list'
    else:
        return 'default'

assert fun(1) == 'int'
assert fun([]) == 'list'
assert fun('str') == 'default'

ダメなポイント:

  • 新しい型と対応する処理を後から追加できない
  • 各型に応じた処理を取り出せない (先の例でいう ‘fun_int’ などを直接テストできない)
  • 見難い

などですね。

他にもいくつか挙動を試していますが、長くなるので気になる人は Githubリポジトリ にあげてるのでそちらを参照してください。

実用例を考えてみた

さてこの singleddispatch 、たしかに面白いですが何に使えるでしょうか。 一つ考えてみたのは 「任意の型で返り値を返す関数たちについて、返り値を共通の型で包む」 というものです。ちょっと自分で言っててもよく分からないので、例を考えます。

チャットするロボットを考えます。人間とロボットはMessageというオブジェクトでやりとりするとしましょう。 ロボットは単なるcallableで、Messageオブジェクトを受け取りMessageオブジェクトを返します。 ただ実装上、このロボットが返す値をいちいちMessageオブジェクトにしてやるのは面倒なので、 ロボットから返す値をMessageオブジェクトに変換する処理を挟んでやります。 この「何らかの型」 => 「Messageオブジェクト」の変換処理をgeneric functionとして持つわけですね。「共通の型」というのがこのMessageオブジェクトです。

さてまずはロボットの実装に必要な、ライブラリとしての処理を実装します。

  • Message: ロボットとのやりとりに使うオブジェクトのクラス
  • generate_message: 各型 => Messageに変換するgeneric function
  • as_robot: 関数をロボットとして定義するデコレーター
class Message(object):
    """ Messages to communicate each robots.
    """
    def __init__(self, body, **metadata):
        self.body = body
        self.metadata = metadata

    def __str__(self):
        return '''\
{self.body}
* metadata: {self.metadata}
'''.format(self=self)

@singledispatch
def generate_message(arg):
    """ Creating Message object for each types.
    """
    raise TypeError('Unexpected type')

@generate_message.register(str)
def str_to_message(arg):
    return Message(arg)

@generate_message.register(dict)
def dict_to_message(arg):
    body = arg.pop('body')
    return Message(body, **arg)

def as_robot(func):
    def wrapped(*args, **kwargs):
        ret = func(*args, **kwargs)
        return generate_message(ret)
    return wrapped

さてこれでロボットを実装する準備ができました。 ここまでをライブラリ、フレームワーク側から提供されるべきものと想定しています。 以下はそれを利用した、ユーザー側が書くべき処理の例です:

@as_robot
def antique(message):
    return "Good morning, Master Ren."

@as_robot
def neomodel(message):
    return {'body': "I'm here.",
            'enjoyment': 1}

if __name__ == '__main__':
    print('antique::', end=' ')
    print(antique('dummy message'))
    print('neomodel::', end=' ')
    print(neomodel('dummy message'))

実装できました。

antique関数では文字列を直接返し、neomodel関数では辞書を返しています。 各関数はas_robotというデコレーターで包まれているので、戻り値がMessageオブジェクト で共通になります。

実行してやるとこんな答えが返ります:

antique:: Good morning, Master Ren.
* metadata: {}

neomodel:: I'm here.
* metadata: {'enjoyment': 1}

まぁこんなかんじで、任意の型 => 共通の型への変換処理を作るのにも使えるのではないか という例でした。 もちろんロボット関数がMessageオブジェクトを返した場合や、後から変換処理を追加する ことも考えられます。これもアップロードしてあるファイルから見てみてください。

ただこの例の場合as_robotデコレーターを外せないので、純粋な関数としての テストが難しいです。そこはas_robotデコレーターを取り外し可能にするなどして 対応するのが良いかもしれません。

まとめ

  • singleddispatch 面白い
  • 任意の型 => 共通の型 への変換などに使えそう

小さいながらも面白い機能で、とくにフレームワークやライブラリを提供するときに 使えそうな印象です。

遊びで書いたコードはここにおいていますので、より詳しくは読んでみてください:

以上です。2日目は露木さん(@everes)にお願いしたいと思います。

何かを作り続けるのはどうすればいいのだろう

何かを作り続けるのはどうすればいいのだろう

ものを作るって、ただ一発何かを作るだけじゃないと最近よく思う。 何か作ったらそれをより良くするため作りつづけたり、多くの人に 使ってもらうために広めたりする必要があると思う。

私が今、頭で考えて言っている「作る」っていうのは、 自己探求とか表現とかそういうものとちょっと違う。 広く使われていて便利なものを生み出すのはどうすれば良いのかな、という 疑問だったりする。 自分のなかにおいて探求とか表現とかいうなら、無人島にいてもコードは書ける。 そんな状況でもコードを書くのかと聞かれたらたぶんYesと答えるんだけど、 そこにあるコードはそれ以上でも以下でもないものではないかと、 今みたいに虚しくなるときがある。

自己満足だけでない良くできたコードを作っていくのは どうしたらいいんだろう。 よく「プログラミングをはじめよう」や「とりあえず何か作ってみよう」 という啓蒙があるけど、そんな話はもううんざりである。 どうすればものを作り続けてより良いものにしていけるかが知りたい。

Twitterで @chichimotsu さんが:

「どんどんいろんなもの作って、それをさらに繋げて行けたらいいよね。」

と言ってくれて、これはなかなか良いなと思った。 自分のなかでは結構さっさと飽きてしまうのだけど、それだけで終わらさない ように浮気をしつつも全体として繋がりをもたせておくのは良いかもしれない。

今日 Uiro framework 0.2 をリリースしたのだけど、何かリリースした後は どうにもこんな気分になる。平たく言うと飽きたのかもしれない。

Getting the definition order of class attributes in python

Getting the definition order of class attributes in python

Same question was in StackOverFllow, but the answer was not so soft on me.

It gave me a some hints, but it actually says ‘Watch a code’. Ok, so I read the code and understood that behavior, I will write that description here.

Why is definition order necessary

The best example is on Form libraries. The definition order will affect to rendering order directory.

Consider on a suprious form library, like this:

class MyForm(Form):
    name = StringField()
    text = StringField()

and it should be rendered that the first place is name and the second text like this oreder:

<input value='name' />
<input value='text' />

Of cause, general form libraries consider the definition order, such as Djnago Form, deform (actually, colander’s behavior).

On my case, I should handle it on creating Uiro framework, definition views in controller.

Answer

To handle the order, you should place a counter. The counter will be increased on each constraction of orderd attributes. And then, each attributes stores that counter value to it’s own.

>>> import itertools
>>> class Field(object):
...     _counter = itertools.count()
...     def __init__(self):
...         self._order = next(Field._counter)
... 
>>> class Form(object):
...     name = Field()
...     text = Field()
... 
>>> Form.name
<__main__.Field object at 0x7f0abfb26250>
>>> Form.name._order
0
>>> Form.text._order
1

Ok, seems good. Then, apply this practice on writing metaclass:

>>> class FormMetaClass(type):
...     def __new__(cls, name, base, attrs):
...         new_class = super(FormMetaClass, cls).__new__(cls, name, base, attrs)
...
...         fields = [(name, value) for name, value in attrs.items()
...                   if isinstance(value, Field)]
...
...         # sorting manually corresponds to the definision order of Fields.
...         fields.sort(key=lambda e: e[1]._order)
...
...         new_class.fields = fields
...         return new_class
... 
>>> class Form(metaclass=FormMetaClass):
...     name = Field()
...     text = Field()
... 
>>> Form.fields[0]
('name', <__main__.Field object at 0x7f0abfb26410>)
>>> Form.fields[1]
('text', <__main__.Field object at 0x7f0abfb26490>)

sweet, the definition order didn’t lost. In __new__ method, the fields before sorted, the order of Fields is not considered in fields, because the attrs is just a dictionary. so we should apply _oreder attribute to Field and re-consider the order manually using that _order.

I used this tips on this change, check it out.

アウトプットとはなんだったのか

アウトプットとはなんだったのか

よくある言葉に「インプットすればアウトプットしろ」という啓蒙がある。

感じるのは、言われているアウトプットとはブログ記事として出力されたものを 意味する場合が多いということ。 加えてカンファレンスや勉強会での発表であったり、 どこかの雑誌への連載や書籍の出版などがある。

共通して感じるのはそれら「アウトプット」が指すものは、 ある程度体系化された情報であるということ。 情報の受取り手に対して明確に「こうすればこうできる」という提示できる もの。入門、ステップバイステップ、事例、失敗談、そういった情報を指す場合が 大半なのではないかということ。

これは主観的な感想なので、そう思わない人はいて当然だけど、 どこか「アウトプットしよう」という話を聞くと疑いたくなる。

得た情報を他に伝えたり、回帰する方法は他にあるんじゃないかと。

ソースコードで表してみる

文章で説明しなくても、ソースコードに書けばいいんじゃないか。

「こんな問題があった」ならその問題を解決するようコードを修正すればいい。 「こんなふうに使うと便利」ならその方法で作ったものを公開すればいい。

根本的に問題を解決できたり、読み解くことで参考にできたりを 実装として回帰すればいいんじゃないか。

ノブの上にノブを乗せる方法や、ノブを彩色する方法や、固着したノブを こじ開ける方法ではなくて、誰でもすんなり開けれるドアノブを作ってやる。 それが誰しもが求めてるはずの、正しいことなんじゃないか。

もちろん状況によっては「正しい」解を求めるべきじゃないときもある。 固着したノブを開ける方法が必要なときもある。 でもそれは実はとっっっても下らない話で、せめて自分の制限のない時間ぐらいは 本質的に求めているドアノブについて考えるべきなんじゃないか。

例えばWebフレームワークの提示する記述方法が貧弱故にテストしにくいとして、 その解決方法はWebフレームワークから提供されるべきだと思う。

FlaskやDjangoにおいて、Viewに適応されたデコレーターはユニットテスト時に 邪魔でしかないわけだけど、Pyramidはその問題を解決している。 Djangoにおいて厄介であったテスト時のsettingsの置き換えは後のバージョンで 取り込まれたoverride_settingsによって対処された。

Pythonにおいてサーバーとアプリケーションを切り離すのにWSGIは役立っているし、 厄介であったパッケージングの問題も解決に向かっている。

多くの人が考えて苦労してどうにかしてなんとかして対処法を体系だてて 解説してきたことは、実はその手にあるノブを修理することでアッサリ 解決するんじゃないか。魔法みたいに。

まずはドアノブは誰かに提供されるだけのものじゃなくて、 自分でも修理できるものだと常に意識して、毎度本質に気づかないといけない のかもしれない。

そのソースコードの意義と説明

実装でどうにかするというのは素晴らしいのだけど、それだけだと悪い場合がある。 その実装の説明が必要な場合だ。 ソースコードに表すだけだと人にはどう考えても伝わりにくい。 ガイドとしてそれの意義、使い方を説明する必要がある。

何より厄介なのは、実装だけするということに対して直感的に「悪い」 という感情を自分自身が持っているということ。 とくに私の場合は「ちゃんとやってない」という気持ちがフツフツと湧いて出る。 docstring、README、long_descriptionやドキュメントが無いと、ことさら「悪い」という気持ちになる。

それはプログラミングをすると絶対付きまとってくる感情で、 自分の得た知見を多くの人々に回帰できていないような感情になる。

でもそれってどうなんだろう。 別に吐いて捨てたコードがあって何が悪いんだろう。 もちろん成果として求められる場合は説明も含めて成果であろうけど、 少なくとも好き勝手やってる「アウトプット」にそれが必要なんだろうか。

「情報として体系化されてない」状態を「悪い」と思ってしまうのは 1ユーザー、1フリーライダーとしての感覚が大きいんじゃないか。 「1フリーライダー」としての感覚を適応すると、そういった説明のない ソースコードには残念な気持ちにはなる。 もっと俺は楽したいのに、もっと俺は楽できるはずなのに、と思う。

でもそれは、自分でもわかってるけど甘い考えなんじゃないかな。 そのソースコードを参考にしたりパクったりすることで十分使うことはできる し、公開されてるだけでもありがたいものだ。 もともと書いた人間が説明してやる義理なんてないし、公開する習慣がある だけでも感動ものなんじゃないか。

そんなに説明がないことが気に入らないなら自分で理解してそれをすればいい。 これは単なる地ならしだけど、もちろんこれも賞賛されるべき情報だ。

ソースコードだけというのは体系化された情報ではない。 整備された「高速道路」ではないけど、でもこれも存在するアウトプット だと捉えたい。

思った

全体として無駄な時間が削減されているかということに注目したい。

荒いアウトプットは、技術的に成熟してない領域に近づくにつれて必要になっていくようにも 感じる。 どのみちそんなのは多くの人間が求めてる情報ではないので丁寧に整備しても見合わない

結局アウトプットとはなんなのだろう。 ORMやアクティブレコードだけがモデルを指さないように、 ブログ記事みたいな、ある程度体系化された情報だけがアウトプットを指さない と思いたい。

自分が得た情報を回帰する方法はたくさんあって、その情報にとって最も効率の いい方法を選択ればい良いだけの話なのかもしれないけどね。