[Python] Python 2.5 Changes
Conditional Expression
# Conditional expression value = (B if A else C) # 問題点: Aが真でも B が 偽 と判断された場合 C を返す value = (A and B or C) # 利点: lambda式 中に条件分岐が書ける
PEP 343 - 'with' statement (./Lib/test/test_with.py, ./Lib/contextlib.py参照)
from __future__ import with_statement
from contextlib import closing, nexted
# 変数のスコープはブロック内ローカル ではない ので注意
f = None
with closing(file('test.txt', 'r')) as f:
print f.read()
print f.closed # True
class wrap_stream(object):
def __init__(self, create_func, *args, **kwds):
self.create = create_func
self.args = args
self.kwds = kwds
def __enter__(self):
self.thing = self.func(*self.args, **self.kwds)
return self.thing
def __exit__(self, *exc_info):
self.thing.close()
with wrap_stream(file, 'test.txt', 'r') as stream:
print stream.read()
- try/except/finally ... exceptとfinallyブロックが同時に記述できる。(try/finally/elseはまだ無理らしい)
- 例外クラスがnew-style classesを利用、例外クラスの階層が少し変更された。
TODO
- functools
[Python][Ruby] mini-pickle (solver for pythonchallenge level 5)
Few days, I was having fun with pythonchallenge.com as you do.
I like the idea of the challanges, I think any programmers could enjoy it.
but unfortunally. it requires some Python specific modules.
fmm...there are hints which hard to notice without python experience.
Here may be help for non-Python programers. ( but spoiler warning )
I've implemented those python's modules for several languages.
If you'd like to implement it by yourself. hints for the lv5: PEP 307
class Unpickler def initialize @mark, @memo, @stack = Object.new, {}, [] end def marker @stack.rindex @mark end def load(stream) loop do case stream.getc.chr when "I" @stack << stream.readline.chomp.to_i when "S" @stack << eval(stream.readline.chomp) when "t", "l" # e.g) ... [ 1,2,MARKER,3,4 ] => [ 1,2,[3,4] ] @stack[marker..-1] = [ @stack[marker+1..-1] ] when "(" @stack << @mark when "a" # e.g) ... [ [ ],1,2 ] => [ [ 1, 2] ] v = @stack.pop; @stack.last << v when "p" @memo[stream.readline.chomp] = @stack.last when "g" @stack << @memo[stream.readline.chomp] when "." return @stack.pop end end end end if $0 == __FILE__ and ARGV.length == 1 banner = ARGV.first puts Unpickler.new.load(open(banner)).map{|row|row.inject(""){|r,(k,v)|r+=k*v}} end
[Python] pickle でCODEオブジェクトをシリアライズ (yat another way)
from new import * import pickle, marshal, struct CODE='C' # opcode(CODE)が重複していないか確認する if (not pickle.Pickler.dispatch.has_key(code) and not pickle.Unpickler.dispatch.has_key(CODE)): def save_code(self, obj): """保存用メソッド""" assert type(obj) == code, "argument must be code object" tmp = marshal.dumps(obj) self.write(CODE) self.write(struct.pack("
注意: CモジュールのcPickleの方では、同じ方法で拡張できない。copy_reg辺りを参照
ユーザー定義クラス等、他のオブジェクトのシリアライズについての正式な拡張方法は、
マニュアルか PEP307 を参照。
■
登録してみた. http://rubyforge.org/projects/rupy/
RuPy Marshal
# marshal_dump.py ... データ作成の為のPython script import sys, marshal def main(filename="test.dump"): data = [ 10, 10.0, -10000, os.environ.get('USER',None), ['foo@example.org', 'bar@example.net'], 10000000000000000000000000000000000000, ] output = open(filename, "wb") marshal.dump(data, output) output.close() if __name__ == "__main__": main(sys.argv[1])
python marshal_dump.py a.dump
# marshal_load.rb require "python/marshal" include Python::Marshal p load( File.new(ARGV[0],'rb').read )
ruby marshal_load.rb foo.dump
# 注意) 辞書等、いくつかの型は未サポート.
RuPy interpreter
python ../utils/py2pyc.py ../samples/hello.py rupy hello.pyc
今のところ、
PRINT命令しかサポートしていない、Hello world 専用インタープリター。
RubyObject
classを宣言した時に、(スコープ内に)クラスが既に存在していれば、
既存のクラスを拡張しそれを返す。Rubyの様なclassの振舞を提供するメタクラス。
import inspect class RubyMetaClass(type): def __new__(self, classname, classbases, classdict): try: frame = inspect.currentframe() frame = frame.f_back if frame.f_locals.has_key(classname): old_class = frame.f_locals.get(classname) for name,func in classdict.items(): if inspect.isfunction(func): setattr(old_class, name, func) return old_class finally: del frame return type.__new__(self, classname, classbases, classdict) class RubyObject(object): __metaclass__ = RubyMetaClass
>>> class C: ... def foo(self): return "C.foo" ... >>> c = C() >>> print c.foo() C.foo >>> class C(RubyObject): ... def bar(self): return "C.bar" ... >>> print c.bar() C.bar
[REBOL][Prototype]
REBOL [] person: make object! [ name: none age: none ] ; プロトタイプを生成 tea: make person [ name: "Tea" age: 24 ] probe tea ; probe はオブジェクトをdumpして表示する関数。 ; プロトタイプなので更に派生する事も可能。 foo: make tea [ name: "foo" ] probe foo ; 定義済みのobjectを新たに拡張する事も出来る。 person: make person! [ ; コンストラクタに相当する関数を定義してみる。 new: func [new-name new-age] [ ; self はobject自身を指す。makeでクローンを生成して返す。 make self [ name: new-name age: new-age ] ] ] hina: person/new "Hina" 18 probe hina
REBOLの第一印象は、括弧なしLISP, コンマなしIo。
- Prototype based Object Oriented
- Email, Money, Date, URL が組み込み型。Quoteなしに、EmailやURLをスクリプト中に書ける。
- Seriesと呼ばれるデータ構造を持ち、REBOLスクリプト自身もそのデータ構造で表す事が出来る。(自己記述性)
- 評価順序
- write %output.file read %input.file が期待通りに解釈される。
- 数式を扱う場合に注意。>> 10 + 20 * 30 + 100 は 710でなく 1000 になる。
- ()で明示的に評価順序を指定すれば問題なし。
- 変数のスコープ。
- 関数宣言内で局所化する場合は明示的に/localで宣言する必要あり。
- object宣言内のブロックでは別スコープ。
- 引数の数が曖昧。()を使う事も出来るが省略も出来る為。
- メソッドを追加する場合にスコープの制限あり。(総称関数が実現できない...?)
- これってプロトタイプベースの利点が活かし切れていないのでは?
- ソースがない。(非オープンソース?、拡張したかったけどライセンスが...)