2014年9月25日木曜日

[Python] どうでもいいClosure

最近Closureについての記事を見かけることが多いので、まとめる。
ref(えいご) ref(にほん語)

  1. closureの基本
  2. Closure = function + environment
    これをOOPの文脈で置き換えると
    Class = Method + member(attributes)
    Closureのほうはあくまで関数が主役。
    次のPythonのコードは典型的なClosureの応用
    def fibonacci_factory():
      memo = {}
      def fibonacci(n):
        if n in memo: return memo[n]
        if n < 1: return 1
        memo[n] = fibonacci(n-1) + fibonacci(n-2)
        return memo[n]
      return fibonacci
    
    ファクトリの呼び出しにより、fibonacci関数が作成され関数は内部的に memo というローカル変数への参照を保持し続ける。
    pythonでは、__closure__ attribute を用いて内包している環境を見る事ができる。
    f = fibonacci_factory()
    f(100) # -> 927372692193078999176
    print(f.__closure__) # -> tuple of cell object
    print(f.__closure__[0].cell_contents) # -> function oject of f itself
    print(f.__closure__[1].cell_contents) # -> might be a dictionary
    
    環境が、cell object のタプルとして保存されているのをみることができる。
    もう一度ファクトリを呼び出すと異なる環境を保持するfibonacci関数が作成される。
    g = fibonacci_factory()
    id(g.__closure__[0]) == id(f.__closure__[0]) # -> false
    
    f と g では各々別々のメモ辞書を持ってるのが分かる。
    別の例として、呼び出す毎に内部変数が1ずつ増えていくカウンターを考える

    def counter_factory():
      x = 0
      def _counter():
        nonlocal x  
        x += 1
        print(x)
      return _counter
    
    上の nonlocal せんっげんはpython3から新しく追加されたもので、これを付けないと、下の様なエラーになる。
    counter_factory()()
    ---------------------------------------------------------------------------
    UnboundLocalError                         Traceback (most recent call last)
     in ()
    ----> 1 counter_factory()()
    
     in _counter()
          2   x = 0
          3   def _counter():
    ----> 4     x += 1
          5     print(x)
          6   return _counter
    
    UnboundLocalError: local variable 'x' referenced before assignment
    
    ファクトリ内部関数での x へのアサインメントは上手くいかない。というのはスコープ外の変数への代入だからである。
    従って、x は一つ上のスコープの変数なんですよ、という宣言が必要になる。
    ちなみに、attribute を用いる事でnonlocal宣言を回避して、クロージャっぽいものを作る事もできる。
    def counter_factory():
      def _counter():
        _counter.x += 1
        print(_counter.x)
      _counter.x = 0
      return _counter
    
  3. Closureとアクセサ
  4. 次に、クラスオブジェクト的な操作を模倣することを考える
    例えば、オブジェクトであればアクセサやらプロパティを用いて、内部で保持している変数(attributes)を変更できる。
    同じ事をクロージャでやってみたいが、__closure__ attribute は tuple なので直接変更できない。
    上で用いた nonlocalせんっげん を使って、アクセサ関数を作って一緒に返してやればよい

    def counter_factory():
      x = 0
      def _counter():
        nonlocal x  
        x += 1
        print(x)
      def set_count(new_x):
        nonlocal x
        x = new_x
      def get_count():
        return x
      return (_counter, set_count, get_count)
    
    get_countには nonlocal は必要ない。単に参照するだけだからである
    正直こういった使い方は邪道な気がする

  5. クロージャとクラス変数

  6. 一部の環境を他のクロージャと共有したい場合があるでありそう
    クラスであれば、単にクラス変数を用いれば実現できるが、クロージャだとどうなるだろう?
    そのときはファクトリのファクトリを作って、共有したい変数を第一レベルに置いて各々の関数で保持したい変数を第二レベルにおけばよい。
    大まかな作りは次のようになるはず
    def factory_factory(x):
      share_var = ... # some collections
      def _factory(y):
        each_vars = ... # some other collections
        def __process(z):
          someprocesses
        return __process
      return _factory
    
    こうしてやると、x, share_var は全体で共有することになって、y, each_vars は各々で保持する
    応用として、二つのカウント値を持ったカウンタを作る。
    一つは全体で共有するカウント値で、もう一つは各々別々に持つカウント値である
    def counter_fact_fact():
      whole_count = 0
      def _counter_fact():
        _count = 0
        def __counter():
          nonlocal _count, whole_count
          _count += 1
          whole_count += 1
          return (_count, whole_count)
        return __counter
      return _counter_fact
    
    アンダーバーが多くて醜い(^q^)
    実際に呼び出して使ってみると、ちゃんと動いくうぃ(^q^)
    cf = counter_fact_fact()
    f = cf()
    g = cf()
    f() # -> (1, 1)
    g() # -> (1, 2)
    f() # -> (2, 3)
    g() # -> (2, 4)
    
  7. まとめ
  • 単なるメモ化程度ならばクロージャは便利だし、デコレータと組み合わせると色々な操作がシンプルに書ける
  • 継承をclosureで実装するにはどうすればいいだろうか?
  • 基本的にpythonはOOPLなので、無理せずクラスを作った方が良い場合が殆どだろう
  • どのようにしてクラスオブジェクトとクロージャを使い分けてやればいいのか明確な判断基準が欲しいところ
  • ブログかくのめんどい(^q^)

2014年9月22日月曜日

John,

海外アニメを見てたら、
we need to go after johns.
って表現が出てきた。
Johnって誰やねん、と思ってWikiで調べたら売春婦の客の事を指すらしい(以下引用)
The clients of prostitutes are also known as johns or tricks in North America and punters in the British Isles. These slang terms are used among both prostitutes and law enforcement for persons who solicit prostitutes.[13] The term john may have originated from the frequent customer practice of giving one's name as "John", a common name in English-speaking countries, in an effort to maintain anonymity.
(引用終わり) 北米におけるポピュラーな名前だからとか、日本だとたかしとかそんな感じだろうか。

さっき某掲示板を見ていたら pastes.org とかいうスニペットの共有サイトに、色々な人の個人情報があげられているというのが話題になっていた。
ドメイン指定して、知りたい言葉で検索するとあれこれ出てくる。
例:発送のお知らせ site:pastie.org
これで知った情報を使って他人のアカウントに入ると不正アクセス禁止法違反なので注意しましょう。

2014年7月28日月曜日

test for mathjax $$ \partial_t u(t,x) = \partial_x^2 u(t, x) $$ mathjaxは重いとか色々言われているわけですけど、実際に使って見るとたしかに重い。 しかし特に難しい設定やインストールなしにきれいに数式が表示されるというのは素晴らしい。

2014年7月27日日曜日

[R] あーあーあーあ

最近はデータ分析やらが流行なので私の学科でもそういう多変量解析を実際にやってみる講義もあったりする。
まあせっかくなので単位の足しにするために出席してたりしたのだが、
 R Programmingはあまりやらなかったので現状使いこなすのが難しい。

 というわけでもう少し体系的にRを勉強する事にした。
 とはいっても自分でドキュメントを読むのとかダルすぎる。
 ネットで情報を漁るのも時間がかかりすぎる。

Courseraにあるコースが結構お手軽。 英語だけど字幕があればなんとかなるレベル。


・Rの コードをblogに埋め込もうと思ったがいい感じのスクリプトがなかったのでgistを使う。
 1.gistに飛ぶ
2.コードを貼付ける
3.create public gistを押すと埋め込み用のタグがでてくるのではっつける
すると以下のようにいい感じになる。

2014年7月21日月曜日

日々の生活を漫然と過ごしているとどうしようもない気分になってくる。 せっかくなのでここに私が勉強した事などのメモを逐次残していく。 日記に書くという手もあるが公開し人の目に触れられる形で残しておく方が私としても頑張って記録を残す気になるというものなのではないかと期待している。 恐らく殆どの場合、閲覧するのは私自身と言う事になるであろう。

2014年3月11日火曜日

this is python code test
#This is a test
for i in range(100):

    print 'Hello World'

    print i
This is a syntax highlighting test.

class Myclass(object):
  __init__(self, x):
    brabra....