目次: Python
Pythonの初歩と思われるバイト列処理で、既に挫折気味です…。
RubyやらLuaやらの、他の動的型言語はどうしているんだろう…。この手の問題が多発したら、私の弱い心は挫折してしまいそうです。
Python 3は文字列とバイト列を明確に区別しています。バイト列の表現には2種類あり、bytes型は読み取り専用のバイト列を表し、bytearray型は読み書き可能なバイト列を表します。それぞれ、組み込み関数bytes() とbytearray() で生成します。
Python 3からバイト列リテラルが追加され、bytes型を生成する際にbytes('abc', 'ASCII') から、b'abc' のように書けるようになったそうです。ふーん…。
Python 3.3.2(Windows), Python 3.2.3(Linux) >>> type(b'abc'[0]) <class 'int'> >>> type(b'abc'[0:1]) <class 'bytes'>
Python 3.3.2(Windows), Python 3.2.3(Linux) >>> type(bytearray(b'abc')[0]) <class 'int'> >>> type(bytearray(b'abc')[0:1]) <class 'bytearray'>
なおバイト列(bytesとbytearrayオブジェクト)の要素は0から255までを取る整数型(int)となります。従ってb'abc'[0] + 1の結果が98となるなど、要素に対する計算が可能です。
バイト列だけではなく、整数列や、浮動小数点列はないのか?という疑問にお答えするのが、array.array型です。この型により要素のバイト長が1以外の配列を扱えます。
オブジェクト生成の際array.array() の第一引数により、配列の要素の型が決定されます。指定可能な型の一覧は、Pythonのリファレンスをご参照ください。
Python 3.3.2(Windows), Python 3.2.3(Linux)
#### 長整数型(singed long, 1要素4バイト)の配列を作成
>>> import array
>>> a = array.array('l')
>>> a.itemsize
4
#### 要素の追加
>>> a.append(1)
>>> a.append(12345678)
>>> a
array('l', [1, 12345678])
#### 要素とスライスの型
>>> a[0]
1
>>> type(a[0])
<class 'int'>
>>> a[0:1]
array('l', [1])
>>> type(a[0:1])
<class 'array.array'>
#### signed long型の値域から外れる値は追加できない
>>> a.append(11111111111111111111111111111111111)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OverflowError: Python int too large to convert to C long
以上のbytes, bytearray, array.arrayの3つの型はいずれもバッファプロトコルという、内部のメモリをオブジェクトの外に見せる仕組みを持っています。
この仕組みにより、以下に述べるメモリビューを使ってオブジェクト内部のメモリをコピーすることなく読み書きすることができます。
オブジェクトの持つメモリをコピーすることなく読む(可能なら書く)ために使うのがmemoryview型です。
オブジェクトの持つメモリが何の配列に見えるか?は、見たいオブジェクトに依存します。signed longとして見せてくるオブジェクトもあるでしょうし、バイト列として見せてくるオブジェクトもあります。
オブジェクトが内部メモリをどう見せてくるにせよmemoryviewの仕様を見る限り、要素の型は配列の各要素の型になるはずです。しかし…、
Python 3.3.2(Windows) >>> type(memoryview(bytearray(b'abc'))[0]) <class 'int'> >>> type(memoryview(bytearray(b'abc'))[0:1]) <class 'memoryview'> Python 3.2.3(Linux) >>> type(memoryview(bytearray(b'abc'))[0]) <class 'bytes'> >>> type(memoryview(bytearray(b'abc'))[0:1]) <class 'memoryview'>
なぜかPython 3.2では要素の型が「bytes」になっています。おかげでmemoryview(...)[0] に対して加減乗除、ビット演算する個所が全滅です。
無理やりmemoryview(...)[0][0] として切り抜けることも不可能ではありませんが、今度はPython 3.3で動かなくなるので困りものです。
ちなみにメモリビューによってlong型の要素を参照した場合は、さらに具合が悪いです。
Python 3.2.3(Linux)
>>> import array
>>> a = array.array('l')
>>> a.append(0x01234567)
>>> a.append(0x79abcdef)
>>> a
array('l', [19088743, 2041302511])
>>> type(memoryview(a)[0])
<class 'bytes'>
>>> type(memoryview(a)[0:1])
<class 'memoryview'>
>>> memoryview(a)[0]
b'gE#x01'
なんと4要素のbytesが返ってきます…。これを一々intに組みなおすのも大変だし、値をコピーせずに参照できる、という利点が完全に死んでる気がします。
もしかしてPython 3.2と3.3でmemoryviewの仕様が変わったんでしょうか?
CやJavaならコンパイル時に「型が違うぜ!」って怒られて気づきますが、Pythonは実行時にクラッシュするまで何も言ってくれません。世の中のPython使いはこういう問題にどうやって対処しているのでしょう?
この記事にコメントする
Mercurialで下記のような集中式リポジトリ「風」の運用をしているとします。その運用ならSubversionでも良いんじゃないの?ってツッコミはさておき…。
このときリポジトリサーバ上で開発するという運用はまずしないので、マスターリポジトリの作業ディレクトリ(Working directory)に存在するファイルは誰も使いません。残しておいても害はありませんが、ストレージ容量を無駄に消費します。
イメージ沸きにくいと思うので、下記のリポジトリを使って説明します。
#### 適当なリポジトリを作成 #### $ hg init $ echo a > file_a $ echo b > file_b $ hg add file_a file_b $ hg status A file_a A file_b $ hg commit -m 'add files.' #### 以上のリポジトリをサーバ上に移し、マスターリポジトリとした ####
このように作成したマスターリポジトリの作業ディレクトリには、当たり前ですがfile_aとfile_bが含まれています。
これらのファイルをrmコマンドで強引に消しても構いませんが、Mercurialの作業ディレクトリのキャッシュ(.hg/dirstate)が残ったままになって、やはり容量が無駄です。
#### 作業ディレクトリ内のファイルを確認 #### $ ls file_a file_b #### 作業ディレクトリの状態を確認 → 結果: 変更点なし #### $ hg status #### 作業ディレクトリ内のファイルを強引に削除 #### $ rm file_a file_b #### 作業ディレクトリの状態を確認 → 結果: ファイルが存在しない状態 #### $ hg status ! file_a ! file_b #### 作業ディレクトリのキャッシュも残ったまま #### $ ls -la .hg/dirstate -rw-r--r-- 1 user users 86 Oct 3 01:09 .hg/dirstate #### ちなみにdirstateは1000ファイルくらいのリポジトリでも70KB程度で、 #### 大した容量ではないです。
何よりも邪魔なのはhg statusを実行すると、大量の「! filename」状態(リポジトリには存在するが、作業ディレクトリにはファイルが存在しない、という状態)が表示されることです。
そんなお悩みを解消するのが、hg update -C nullです。作業ディレクトリを綺麗さっぱり消してくれて、hg statusにも文句を言わせないのです。
#### 作業ディレクトリを削除 #### $ hg up -C null 0 files updated, 0 files merged, 0 files removed, 0 files unresolved #### 作業ディレクトリにファイルはない #### $ ls #### 作業ディレクトリの状態 → 結果: 変更点なし #### $ hg status #### 作業ディレクトリのキャッシュサイズも縮小 #### $ ls -la .hg/dirstate -rw-r--r-- 1 user users 40 Oct 3 01:15 .hg/dirstate
「ゴミ」が残っているのが気になる、または、気になっていた方はぜひお試しあれ。
この記事にコメントする
目次: Python
PyCharmがメジャーアップデートされ PyCharm 3 がリリースされました。
特筆すべきはIntelliJ IDEAに続き、PyCharmにもCommunity Editionが追加されたことです。つまり基本的な機能は「タダ」で使えるということです。ただ個人的にはショックでした…。
なぜならこのあいだ(2013年8月7日の日記参照)一念発起してPersonal Editionのライセンスを購入したばかりだからです。まさかこのタイミングでCommunity Editionがリリースされるとは、なんと間の悪い…。
この記事にコメントする
| < | 2013 | > | ||||
| << | < | 10 | > | >> | ||
| 日 | 月 | 火 | 水 | 木 | 金 | 土 |
| - | - | 1 | 2 | 3 | 4 | 5 |
| 6 | 7 | 8 | 9 | 10 | 11 | 12 |
| 13 | 14 | 15 | 16 | 17 | 18 | 19 |
| 20 | 21 | 22 | 23 | 24 | 25 | 26 |
| 27 | 28 | 29 | 30 | 31 | - | - |
wiki
Linux JM
Java API
2002年
2003年
2004年
2005年
2006年
2007年
2008年
2009年
2010年
2011年
2012年
2013年
2014年
2015年
2016年
2017年
2018年
2019年
2020年
2021年
2022年
2023年
2024年
2025年
過去日記について
アクセス統計
サーバ一覧
サイトの情報合計:
本日: