Hatena::Groupfukuoka-py

uchikoshi22.py

 | 

2011-09-11

妥当な日付かどうかチェックする

17:00


GAEでdatastoreにputする前に日付が正しい値かどうかチェックしたくて、妥当な日付かどうかチェックする関数を調べてみました。


from datetime import date

def validate_date(y, m, d):
  try:
    date(int(y), int(m), int(d))
    return True
  excpet ValueEror:
    return False

次の方法ではうまくいきません。


from datetime import date

def validate_date(y, m, d):
  if date(int(y), int(m), int(d)):
    return True
  else:
    return False

日付が正しくなければdate関数はValueErrorを返します。

ValueErrorはBooleanではないので、誤った日付のときにFalseを返せず、if文で判定する前にエラーが発生するので最初のソースのように例外処理を行う必要があります。

リスト内包表記のおさらい

16:42

次のリスト内包表記を説明するためにPython初心者の読める冗長なコードにしてみました。


?単純な内包表記

>>> spam = [1,2,3,4,5]
>>> eggs = [x*2 for x in spam]
>>> spam
[1, 2, 3, 4, 5]
>>> eggs
[2, 4, 6, 8, 10]
>>>
# 上の内包表記と等価のlambda式
>>> eggs = map(lambda x: x*2, spam)
>>> eggs
[2, 4, 6, 8, 10]

?解説用の冗長なコード

>>> spam = [1,2,3,4,5]
>>> eggs = []
>>> count = 0
>>> while len(spam) > count:
...     x = spam[count]
...     eggs.append(x*2)
...     count += 1
...
>>> eggs
[2, 4, 6, 8, 10]

リスト内包表記やlambda式(+map関数)を使えるようになると便利なんですが、慣れるまで頭が右往左往していたので、久しぶりに整理してみました。

lambdaの最初の一歩

16:41

lambdaのイメージがすぐわからなくなってしまうので、一旦整理。

lambda式はdefステートメントと同様、関数関数オブジェクト)の作成に使用する手段の一つです。

(初めてのPythonの369ページ)

構文: lambda 引数: 式


ということで、

与えられた引数の2倍の値を戻す関数をlambda式とdefステートメントでつくります


?defステートメント

def double(spam):
  return spam * 2

?lambda式

lambda x: x * 2

defステートメントを使って呼び出すときは、関数名に引数を与えれることで戻り値を得ます。

>>> def double(spam):
...   return spam * 2
...
>>> double(2)
4
>>> double(10)
20


lambda式は関数名がないので、呼び出すときは一旦変数に代入してから呼び出すことでdefステートメントと同じような使い方ができます。


>>> lambda x: x * 2
<function <lambda> at 0xb77db56c>
>>> double = lambda x: x*2
>>> double(2)
4
>>> double(8)
16
>>>

自分ではlambda式のイメージが湧いたんですがどうでしょうか?

多次元リストのソート

13:51

多次元リストを手軽にソートする方法を練習してみました。


①まず、ソートする対象になるリストを作ります。

>>> list = [ [2, "d", "1100"], [7, "z", "10"], [0, "t"] ]
>>> list
[[2, 'd', '1100'], [7, 'z', '10'], [0, 't']]

②内側のリストの1個目の要素をもとにソートするだけであれば次のように簡単にソートできます。

>>> list.sort()
>>> list
[[0, 't'], [2, 'd', '1100'], [7, 'z', '10']]

③これが2番目以降の要素をもとにソートしようとするとほんのちょっとだけ面倒になります。

>>> list.sort(lambda x, y: cmp(x[1], y[1]))
>>> list
[[2, 'd', '1100'], [0, 't'], [7, 'z', '10']]

④注意点として、ソート対象にする内側のリストの中に、1つでもソート対象となる要素のない短いリストがあれば次のようにエラーになります。

>>> list.sort(lambda x, y: cmp(x[2], y[2]))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 1, in <lambda>
IndexError: list index out of range

⑤最後に、cmp関数を使った場合、文字列としてソートしてしまします。


数値としてソートする場合は、cmpの中のオブジェクトをint関数で囲んであげる必要があります。


※2行目と5行目を見比べてください。


>>> list = [[2,"d", "1100"],[7,"z","10"],[0,"t","120"]]
>>> list.sort(lambda x, y: cmp(x[2], y[2]))
>>> list
[[7, 'z', '10'], [2, 'd', '1100'], [0, 't', '120']]
>>> list.sort(lambda x, y: cmp(int(x[2]), int(y[2])))
>>> list
[[7, 'z', '10'], [0, 't', '120'], [2, 'd', '1100']]

Ubuntuのpyexiv2で画像Exif情報を読み取り

13:45

Ubuntu10.04で画像のExif情報を操作したい場合、いくつか方法がありますが、今回はpyexiv2を試してみました。


Ubuntu10.04環境では、パッケージが用意されているので、コマンド一発でインストールができます。

$ sudo apt-get install python-pyexiv2

インストールは簡単ですが、ここから注意が必要です。


pyexiv2のチュートリアル通りにやろうとすると、ImageMetadataメソッドを使うとき、ImageMetadataをインポートするときにエラーが出ます。




>>> metadata = pyexiv2.ImageMetadata('test.jpg')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'ImageMetadata'
>>>
>>> from pyexiv2 import ImageMetadata
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: cannot import name ImageMetadata

そこで、pyexiv2のhelp (help(pyexiv2)で見れます)の中を見てみると、ImageMetadataの記述がどこにもないんですが、ImageMetadataを使わないでExifタグの一覧を表示する方法が書かれています。


Ubuntu上でうまくいかなかったチュートリアルの方法(WindowsXP上ではエラーはでませんでした)と、うまくいったhelpに書かれている手順の両方をメモしておきます。



// チュートリアルの手順 (ubuntuでは失敗しました)

>>> import pyexiv2
>>> metadata = pyexiv2.ImageMetadata('test.jpg')
>>> metadata.read()

// helpの手順 (ubuntuでも実行できました)
>>> import pyexiv2
>>> image = pyexiv2.Image('test/smiley.jpg')
>>> image.readMetadata()
>>> print image.exifKeys()


これでようやくスタートラインに立てました。


現在、画像のExif情報を扱う簡単な(アプリと呼ぶほど大きくもない)スクリプトを書いています。

Pythonのopen()関数の注意点

11:24

Pythonでファイルを作成しようと思って検索すると以下のようなosモジュールを使ったコードをよく見かけることになると思います。


import os
f = os.open('spam.txt', 'w')
f.write('')
f.close()

ところが、実際にこのコードを実行しようとすると、2行目の段階で次のエラーメッセージに直面します。

Traceback (most recent call last):

File "<stdin>", line 1, in <module>



このエラーが出ないようにしてPythonでファイルを作成するために2つの方法を紹介します。


  1. 組み込み関数のopen()を使う
  2. osモジュールの正しい使い方を覚える


1. 組み込み関数のopen()を使う

Pythonには組み込み関数のopen()があります。osモジュールの方がより詳細なファイルアクセスができますが、組み込み関数のopen()の方が簡単かつ、実行結果も早い(みたい)です。


組み込み関数open()を使ってファイルの新規作成をするには

# spam.txtとうファイルを作って、eggsという文字列を書き込みます。
>>> f = open('spam.txt', 'w')
>>> f.write('eggs')
>>> f.close()

もっと詳しいことを知りたいときは↓

http://docs.python.org/library/functions.html#open




2. osモジュールの正しい使い方を覚える

ここでは簡単にコードだけ紹介します。

詳細は↓のドキュメントをご確認ください。



>>> import os
>>> f = os.open('eggs.txt', os.O_CREAT)
>>> f = os.open('eggs.txt', os.O_RDWR)
>>> os.write(f, 'spam')
4
>>> os.close(f)

5行目に表示される数字の4ですが、これはos.write()で実際にファイルに書き込まれたデータのバイト数を返して表示しています。


osモジュールを使う注意点として、


import osをfrom os import *と書いてしまうと、組み込み関数のopen()よりもosモジュールのopen()が優先されて組み込み関数のopen()が使えなくなるので、組み込み関数のopen()を使う時はfrom os import *とは書かないようにしましょう。

HinesHines2011/10/06 20:32Kudos to you! I hadn't thoguht of that!

weoivpweoivp2011/10/07 02:38qTOAir <a href="http://nwsrnizbsrnp.com/">nwsrnizbsrnp</a>

paiyypwvpaiyypwv2011/10/07 21:09JTrjhm , [url=http://gaqcbloiwcic.com/]gaqcbloiwcic[/url], [link=http://szrplnghtifb.com/]szrplnghtifb[/link], http://pumzstfmdbjx.com/

sumtnxsumtnx2011/10/11 00:00Pg0z8x <a href="http://haocmyvcmyab.com/">haocmyvcmyab</a>

xccloupfatxccloupfat2011/10/12 22:14WUVaf9 , [url=http://vsdcxztdnfnw.com/]vsdcxztdnfnw[/url], [link=http://qgmnnximnmek.com/]qgmnnximnmek[/link], http://rztzkpwelkvo.com/

IoryIory2012/08/21 14:43Yup, that sohuld defo do the trick!

qhczvtwokpqqhczvtwokpq2012/08/22 12:47FLbvjo <a href="http://hlhmoevhtelv.com/">hlhmoevhtelv</a>

ndwyeskdkhndwyeskdkh2012/08/25 01:55P7Tams , [url=http://qwkxjwjmizib.com/]qwkxjwjmizib[/url], [link=http://bapdceiwwbaw.com/]bapdceiwwbaw[/link], http://sraioevuykwc.com/

 |