全「???48」を生成してみる
課題1
- 大文字のアルファベット3文字 + '48' の全パターンのリストを作る
解答 その1
単純にループの入れ子で
# まず大文字のアルファベットのリストを作る al = [chr(a) for a in range(65, 91)] # 全パターンのジェネレータ def akb(): for a1 in al: for a2 in al: for a3 in al: yield a1 + a2 + a3 + '48' # リストで取得 allptns = [p for p in akb()] allptns.index('AKB48') #=> 本家は261番目に出てきた
解答 その2
リスト内包表記の入れ子
# al は大文字アルファベットのリスト # 全パターンのリスト allPtns = [a1 + a2 + a3 + '48' for a1 in al for a2 in al for a3 in al]
解答その3
アルファベットの桁数を指定できるようにしてみる
# al は大文字アルファベットのリスト # 2個のリストを組み合わせる関数 getprd = lambda list1, list2 : [a1 + a2 for a1 in list1 for a2 in list2] # 全パターンのリストを生成する関数 def akb(num): temp = [''] def _akb(tl, n): if n == 0: return getprd(tl, ['48']) else: return _akb(getprd(tl, al), n - 1) return _akb(temp, num) allPtns = akb(3)
なんかいまいちだなー。もっとかっこよい解答求む。
課題2
課題1に制限を加える
アルファベット3文字は別々のアルファベットを使う(AAAとかAABはダメ)
解答
課題1の解答3のリストを組み合わせる関数(getprd)を以下に修正すれば対応できる。
# 2個のリストを組み合わせる関数(重複省く) getprd = lambda list1, list2 : [a1 + a2 for a1 in list1for a2 in list2 if a2 not in a1]
課題2の場合は本家は216番目に出てきた。
やってみた感想
ループとか関数とか考えながら書けるので、初めてのプログラミング言語に取り組むときはHello Worldよりこの課題やると楽しそう。
別解
ちなみに標準モジュールのitertoolsを使えば以下のように書ける。
至れり尽くせり!
import itertools # al は大文字アルファベットのリスト # 課題1 allptns1 = [''.join(a) + '48' for a in itertools.product(al, al, al)] # 課題2 allptns2 = [''.join(a) + '48' for a in itertools.permutations(al, 3)]
EXIFタグで写真の情報を見てみる
自分がデジカメで撮った写真のEXIFタグ情報を見てみようかと思い立った。大量に集めれば何か撮影の傾向が見えるかも?
とりあえずPythonでEXIF情報を取得してみよう。
1.EXIF情報を取得するモジュール
EXIF.py プロジェクト日本語トップページ - SourceForge.JP
2008年8月のリリース以後、更新されていないので2010年に策定されたExif2.3に対応したデジカメだとうまく情報がとれないかもしれない。
Exif規格に7年ぶりの新バージョンExif 2.3 - PhotoXP
自分のデジカメは2011年1月発売のOLYMPUS PEN Lite E-PL2。まあ試してみてダメだったら考えよう。
2.EXIFを読み込み!
EXIFモジュールのprocess_file関数使用する。
> from EXIF import process_file > fp = r'd:\sample.jpg' # EXIFタグを読みたい画像ファイルパス > f = open(fp, 'rb') > exifDic = process_file(f)
process_fileは以下の名前付き引数が指定できる。
名前 | 既定値 | 説明 |
stop_tag | 'UNDEF' | 出現した場合に読み込みを切り上げるタグ名を指定する |
details | True | メーカーが独自に使っているMakerNoteタグを読み込むかどうか。 |
strict | False | タグ読み込み時にエラーが発生した場合に実行を停止するかどうか。 |
debug | False | タグ読み込み時にデバッグレベルの情報を出力するかどうか |
戻り値はタグ名がkeyでEXIF.IFD_Tagのインスタンスをvalueとする辞書型となる。
> ifdTag = exifDic['Image Model'] #IFD_Tagのインスタンス > dir(ifdTag) ['__doc__', '__init__', '__module__', '__repr__', '__str__', 'field_length', 'field_offset', 'field_type', 'printable', 'tag', 'values']
E-PL2のタグはdetailsにFalseを指定すると読み込むことができた。
3.サンプル画像を読み込む!
以下の関数で、フォルダ内のjpgファイルのEXIFタグ情報を一度に読めるようにする。
ExifReader.py #cording:utf-8 import EXIF import os import glob # 読み込みたくないタグは以下に指定する excludetags = ['JPEGThumbnail','TIFFThumbnail'] def getTagValueDict(filePath): f = open(filePath, 'rb') exifTags = EXIF.process_file(f, details=False, strict=False) f.close() exifKeys = [key for key in exifTags.keys() if key not in excludetags] exifDict = {} for exifKey in exifKeys: exifDict[exifKey] = exifTags[exifKey].printable return exifDict def getTagValueDicts(root, pattern='*.jpg'): files = glob.glob(os.path.join(root, pattern)) exifDicts = {} for file in files: tags = getTagValueDict(file) exifDicts[os.path.basename(file)] = tags return exifDicts
EXIF.py プロジェクト日本語トップページ - SourceForge.JPではサンプル画像もダウンロードできるので読み込ませてみる。
デジカメで撮った画像である以下を対象とする。
Canon_40D.jpg Canon_DIGITAL_IXUS_400.jpg Fujifilm_FinePix6900ZOOM.jpg Fujifilm_FinePix_E500.jpg Kodak_CX7530.jpg Konica_Minolta_DiMAGE_Z3.jpg Nikon_COOLPIX_P1.jpg Nikon_D70.jpg Olympus_C8080WZ.jpg Panasonic_DMC-FZ30.jpg PC040163.JPG Pentax_K10D.jpg Ricoh_Caplio_RR330.jpg Samsung_Digimax_i50_MP3.jpg Sony_HDR-HC3.jpg WWL_(Polaroid)_ION230.jpg
さらにE-PL2で撮った画像を一枚対象に含める。
全機種で使われているタグを調べてみる
> from ExifReader import getTagValueDicts,getTagValueDict > rootPath = r'D:\Exif_test_images' # サンプル画像のフォルダ > exifTagsDict = getTagValueDicts(rootPath) > tagSets = [tagnames for dic in exifTagsDict.values() for tagnames in dic.keys()] > distinctTags = reduce(lambda x,y: x.intersection(y) ,tagSets) > distinctTags set(['EXIF Flash', 'Image ExifOffset', 'Image Model', 'EXIF ColorSpace', 'EXIF DateTimeOriginal', 'Image XResolution', 'Image Make', 'Image DateTime', 'Image YResolution', 'EXIF FNumber', 'EXIF ExifImageLength', 'Image ResolutionUnit', 'EXIF ExifImageWidth'])
サンプル画像のExifバージョンを調べる
> versions = [str(v) for tags in exifTagsDict.values() for t,v in tags.iteritems() if t=="EXIF ExifVersion"] > set(['0220', '0221', '0210'])
ちなみにE-PL2で撮った画像の結果は以下
> d = getTagValueDict(epl2FilePath) > tagNames = sorted(d.keys()) > for t in tagNames: v = d[t] print t,':'v EXIF ColorSpace : sRGB EXIF ComponentsConfiguration : YCbCr EXIF Contrast : Normal EXIF CustomRendered : Normal EXIF DateTimeDigitized : 2011:12:04 12:18:44 EXIF DateTimeOriginal : 2011:12:04 12:18:44 EXIF DigitalZoomRatio : 1 EXIF ExifImageLength : 4032 EXIF ExifImageWidth : 3024 EXIF ExifVersion : 0221 EXIF ExposureBiasValue : 0 EXIF ExposureMode : Auto Exposure EXIF ExposureProgram : Program Normal EXIF ExposureTime : 1/500 EXIF FNumber : 71/10 EXIF FileSource : Digital Camera EXIF Flash : Auto Off EXIF FlashPixVersion : 0100 EXIF FocalLength : 17 EXIF GainControl : None EXIF ISOSpeedRatings : 200 EXIF InteroperabilityOffset : 17202 EXIF LightSource : Unknown EXIF MaxApertureValue : 761/256 EXIF MeteringMode : Pattern EXIF Padding : [] EXIF Saturation : Normal EXIF SceneCaptureType : Standard EXIF Sharpness : Normal EXIF Tag 0xEA1D : 1872 EXIF WhiteBalance : Auto Image Artist : Image Copyright : Image DateTime : 2011:12:31 21:47:17 Image ExifOffset : 2538 Image ImageDescription : OLYMPUS DIGITAL CAMERA Image Make : OLYMPUS IMAGING CORP. Image Model : E-PL2 Image Orientation : Horizontal (normal) Image Padding : [] Image PrintIM : [80, 114, 105, 110, 116, 73, 77, 0, 48, 51, 48, 48, 0, 0, 37, 0, 1, 0, 20, 0, ... ] Image ResolutionUnit : Pixels/Inch Image Software : Microsoft Windows Photo Viewer 6.1.7600.16385 Image XResolution : 314 Image YCbCrPositioning : Co-sited Image YResolution : 314 Thumbnail Compression : JPEG (old-style) Thumbnail JPEGInterchangeFormat : 17864 Thumbnail JPEGInterchangeFormatLength : 5873 Thumbnail ResolutionUnit : Pixels/Inch Thumbnail XResolution : 72 Thumbnail YResolution : 72
Qt Console でラグジュアリーな IPython
気付いてはいたんですよ、PythonのScriptsフォルダにipython-qtconsole.exeがいるのを。
ダブルクリックしても起動しないんで無視してました。
ところが、↓の記事を見て、使ってみたらとてもいいものだった!!
かっこ良くなったipython 0.11のqtconsoleを試す。: YATSTUKE BLOG
というわけでQt Console版のIPythonを使ってみる。(ほぼ元記事と内容がかぶっちゃいましたが……)
1.インストール
以下の環境を想定
OS | Windows7 (x86) |
Python | 2.7.2 |
IPython | 0.12 |
(1) PyQt4 のインストール
↓からPyQt-Py2.7-x86-gpl-4.9-1.exeを入手してインストール。
Riverbank | Software | PyQt | PyQt4 Download
とりあえずインストールタイプを"MINIMAL"にしてQt Runtimeのみ入れれば良い。
(2) pyzmq のインストール
pip install pyzmq でうまく入らなかったので早々にあきらめて↓からpyzmq-2.1.11.win32-py2.7.msiを入手して実行。
Downloads · zeromq/pyzmq · GitHub
Windows はインストーラが用意されている場合が多いのがいいね。
(3) pygments のインストール
pip install pygments でインストール。バージョン1.4が入った。
これでリッチなQt Console 生活を始める準備が整った。
2.使い方
Python インストールフォルダ配下のScriptsフォルダにあるipython-qtconsole.exeを起動。
とりあえず色々入力してみよう。
- 入力するとimportやdefなどの予約後やモジュール名・メソッド名などが自動的にシンタックスハイライトされる!
- 括弧にカーソルを合わせると対応する括弧が強調表示される!
- コマンドライン引数で --pylab=inline を指定するとMatplotlibのプロットがコンソールないに表示される!
- コピー・カット・貼り付けがCtrl + c、Ctrl + x、 Ctrl + v !
- 画面の入力・出力した内容をhtmlファイルとして保存できる!
- Tabキーでの候補表示でプロンプトが改行しない!
- Ctrl + Enter で複数行の入力が可能!(履歴も複数行で出てくる)
- タブでコンソールを複数開ける!
- 同じセッションで開くことも、新しいセッションで開くこともできる!
- 入力・出力内容をhtml/xhtml形式でエクスポートできる!(グラフも!)
- 全てのマジック関数がメニュー上から実行できる!
- なにげにチートシートを表示できるのがいいかも!
3.フォントの変え方
デフォルトの文字がちょっと小さいと感じるなど、フォントの設定を変更したい場合は以下の通り。
(2) profile の修正
(1)により以下にprofileフォルダが作成される。
C:\Users\<現在のユーザ名>\.ipython\profile_<プロフィール名> ※ XPだとDocument and Settings配下だったと思われ。
ipython_qtconsole_config.py を開いて以下の修正を行う。
213行目 # c.IPythonWidget.font_size = 0 ↓コメントアウトを外して任意のサイズ値を指定 c.IPythonWidget.font_size = 12 273行目 # c.IPythonWidget.font_family = u'' ↓コメントアウトを外して任意のフォント名を指定 c.IPythonWidget.font_family = u'MS Gothic'
(3) オプション引数指定
ipython-qtconsole.exe にオプション引数"--profile=<プロフィール名>"を指定して起動する。
4.まとめ
Windowsでの対話シェルはIPythonのQtConsoleが最もリッチでよさそう。
でも私の環境だと、import行でTab補完するとIPythonのカーネルから応答がなくなるけど。何でですかね。誰か助けて。