モジュールと名前空間とclassのImport

Pythonには標準モジュールがある。使い方は一般的。

#Simple XML-RPC Serverの例
import xmlrpclib
from xmlrpclib
import Fault
import SocketServer
import BaseHTTPServer
import sys
import os

ここでのポイントはfrom。FROMを使うとローカルの名前空間にロードされる。

from xmlrpclib
import Fault

def xmlrpclib() :
    """...

とかくと上書きしてしまうので注意。


インポートされるライブラリパスは、環境変数に依存する。

カレントディレクトリ->PYTHONPATH(PATH書式)->インストールパス

ファイル名が、モジュール名になり、Pythonでの名前空間を表す。

#hoge.py
def foo():
   print "foo"
#sample.py
import hoge
hoge.foo()

ファイル名の代わりにディレクトリを使えば、名前空間をネストできる。

クラスに関しても同じようにインポートする。ただし、Javaのような「クラス名=モジュール名」の対応が100%成立すると限らない。

一方で、PHPのように、適当なファイル名でモジュールを作成する、いい加減さでうまくいくようなモノでもない。
Perlの use strict;をイメージするとよいかな。

PHPでのインポート

<?php
require_once "Smarty.class.php";
require_once "Zend.php";

$smarty = new Smarty;
$zend   = new Zend;
  • ファイル名とクラス名が一致しなく、銘々規則はいい加減でいい。手軽に使えるので便利
  • 一方で、大人数で開発するときに、似た名前のファイルが増殖し、頭を抱える原因になる。

JavaScriptの場合、確固たる手法はない。

<script type="text/javascript" src="./js.cgi?type=initA&user=B" >
</script>

<script type="text/javascript">

document.write("<script...");//Scriptタグを書き出す
eval( xmlHttpResult );//xmlHttpの結果をevalする
</script>
  • scriptタグの利用
    • リクエスト毎に異なるJSファイルを動的生成
    • document.writeを利用
  • evalの利用
    • xmlhttpやiframeの利用
      • JSON形式
      • JSONP形式 getXXX( ); などがある。
    • document.onload()にBindする。

バイトコードコンパイル

Pythonインタプリタは、ソース中間言語コンパイルしてくれる。全て自動で。余り深く考える必要はない。(今のところ)

  • 中間言語コンパイルされたソースは*.pycでソースと同じフォルダに作成される
  • 中間言語コンパイルされたと言っても、処理速度の最適化は行っていない*1
  • 中間言語コンパイルされたソースはロードが早くなる。*2
  • 最適化するときは -OO や-O フラグをつけて実行する
    • 2.4での現状はassertを除去する。
    • 2.4での現状は__doc__(docstring)を除去する程度
    • 余り高速化は望めない
    • ただし、バイトコードなのでソースを隠蔽するのに使えるよ

PHPのZend_Optimizer程ではないが、APCのキャッシュ機構に近いことは出来るよ。ってこと。

*1:Javaだとjavac.exeが中間言語コンパイル時に、かなりのソース最適化を行う。Stringやループ処理。等々。

*2:たぶんsyntax checkをスルーするからだと思う

制御構造

Pythonの特徴

    • do{}while() が無い
        • do〜while好きは処理を工夫する
    • switch がない
        • elifを使う
    • else if と書かない
        • elif を使う
        • else は使える
#C言語を母とする言語によく見られる
while( ( c = input.getChar() ) != null ){
    out.print( c );
}
for ( var i =0;i<array.length();i++ ){
   out.print( i + "="+array[i] + "\n"  );
}
#この形式はPythonではエラーになる(はず :あとで詳しく調べる )

では、どうするか? foreach文を使う。

for a in array :
    print a

#enumerate()関数を使う
for key , val in enumerate( array ):
    print key , "=", val

配列処理は、key=>val の対応が重要なのでループ変数よりIteratorの方が実用性が高い。だからこれで十分だ。
どうしても int = i ; が良いなら仕方がない

for i in range(1, len(array)):
    print i , "=", array[i]

と書けばいい。

while を使うStackの例

#stack = [0...99]

#Pythonでは
while len(stack) > 0:
    print stack.pop()

配列の扱い

PythonのプログラミングはJavaScriptに似ている。文法はまるで似ていないが。発想が似てる。

配列の動的インクリメント

Javascriptのばあい
var hoge;
hoge[hoge.length] = "test1";
hoge[hoge.length] = "test2";
hoge[hoge.length] = "test3";
//hoge = { 0: "test1", 2:"test2", 3:"test3" }

Pythonの場合。

##配列のマージを利用する
hoge[len(hoge):] = ["test1"]
hoge[len(hoge):] = ["test2"]
hoge[len(hoge):] = ["test3"]
##hoge = { 0: "test1", 2:"test2", 3:"test3" }

##Appendメソッドを使う
hoge.append( "test1" )
hoge.append( "test2" )
hoge.append( "test3" )
##hoge = { 0: "test1", 2:"test2", 3:"test3" }

もちろん、append()関数を使ってもいい。ただ、JavaScriptでも配列にappendすることよりも言語構造で処理することが多いので、こっちの書式がよく使われるのかな?。PHPPerlでもappend()しないなぁ。

##注意) 配列のマージはappendより処理が重いよ。マニュアルによると、append推奨らしい。


ちなみにPHPの場合はとっても楽ちん

<?php

hoge[]= "test1";
hoge[]= "test2";
hoge[]= "test3";
//hoge = a:3:{i:0;s:5:"test1";i:1;s:5:"test2";i:2;s:5:"test3";}

PHPだと「appendしる」みたいなことは書いていなく、これが自然な記述ってこと。楽だねぇ。オブジェクトがIteratorインタフェース実装してればどこで使っても問題ないみたい。

 Javaだと、Collectionインタフェース実装したクラスにキャストして・・・それから・・・云々・・死ねる。Eclipseが発展してきた理由がわかる。補完無しだと腱鞘炎だ。

 PHPのserialize関数はJSONっぽい文字列を返してくれるが、若干仕様が異なるのでそのままJavaScriptでevalは出来ない。まぁJSONを返すパッケージがあるのでそれを使えばいいさ。

モジュールをパッケージ化する

今度は、パッケージの作成方法

まず、パッケージとはモジュールの集合体。Pythonにおいて、以下のことが成立する

ディレクトリ構造 = パッケージ階層
ファイル名       = モジュール名

じゃぁパッケージ全体の設定はどうするんだ? __init_.py ファイルを設置する。(省略可)

#ディレクトリ構造
./Amazon
   +- __init_.py
   +- AWS_Actount.py
   /products
       + __init__.py
       +-- /Book
       |     +-- __init__.py
       +--/Video
             +-- __init__.py

などと__init__.pyが沢山出来ますよ。__init__.pyがあることでディレクトリがパッケージとして認知される。

パッケージ内の特定モジュールをLoadする。

これはJavaと同じ発想で良い。

//Java
import java.io.*;
import java.util.Hashtable;
import java.util.Properties;

#Python
import Amazon.products
import Video from Amazon

ここで、注釈: import X from のこと

//Javaだと
import java.io.*;
import java.util.Hashtable;
import java.util.Properties;

java.utilを何度も書く。これが面倒だろ?
Pythonでは、Fromを使うことでSimpleにしている
javaを題材に例を作ると

#python

import java.io.* 
from java.util import Hashtable, Properties 
#    ^^^^^^^^^        ^^^^^^^^^^^^^^^^^^^^^
#    共通部分                タプル

このシンプルな記法がPythonの特徴さ。

パッケージの銘々規則

変数名や関数名と同じ。ファイル名は[名前.py]と書く。 正規表現で書くと

           [a-Z][a-Z0-9_]* 
    または [a-zA-Z][a-zA-Z_0-9]*
    または (\l\s)(\w)

windowscase insensitiveだぞ?

Windows は大文字小文字を区別しないので、[名前.py]では不便なことが出てきそうですね?Windows95系には、ファイル名の文字数制限がある。*1

安全のために、パッケージの初期ロード(__init__.py)に内包するモジュール名を定義しておく。__all__ 変数を使う。

# ./sample/__init__.py
__all__ = ["hoge", "FOO", "Bar"]

と書いておけば

from sample import *;

と全指定したときに __all__の中身で指定した「大文字小文字」でパッケージが読み込まれる。ファイル名を無視するようだ。

*1:win98を現役で使ってる開発者なんていないだろうけど

標準モジュール

Pythonには豊富な標準モジュールがある。Pythonインストール時にまとめてインストールされる。いくつかの、特殊モジュールはPythonインタプリタに組み込まれているが、通常はモジュールとして提供される。

sys 覚えておくべきモジュール

sys.path はPythonで利用するパスを管理する

#モジュールのパスを追加する
import sys
sys.path.append("/home/veryberyy_cafe/libs/")

dir() パッケージの中身を調べる

dir(name) を用いるとそのモジュールで利用している、変数名を調べられる

import sys

print dir(sys) #
#
#['__displayhook__', '__doc__', '__excepthook__', '__name__', '__stderr__', '__stdin__', '_
#_stdout__', '_current_frames', '_getframe', 'api_version', 'argv', 'builtin_module_names',
# 'byteorder', 'call_tracing', 'callstats', 'copyright', 'displayhook', 'dllhandle', 'exc_c
#lear', 'exc_info', 'exc_type', 'excepthook', 'exec_prefix', 'executable', 'exit', 'getchec
#kinterval', 'getdefaultencoding', 'getfilesystemencoding', 'getrecursionlimit', 'getrefcou
#nt', 'getwindowsversion', 'hexversion', 'last_type', 'last_value', 'maxint', 'maxunicode',
# 'meta_path', 'modules', 'path', 'path_hooks', 'path_importer_cache', 'platform', 'prefix'
#, 'ps1', 'ps2', 'setcheckinterval', 'setprofile', 'setrecursionlimit', 'settrace', 'stderr
#', 'stdin', 'stdout', 'subversion', 'version', 'version_info', 'warnoptions', 'winver']

print dir()
# ['__builtins__', '__doc__', '__name__', 'sys']

"." や ".." を使った、パッケージの相互参照

親子のときは、簡単にImportできるんだけど、従兄弟くらいになると面倒だ。

パッケージ構造 = ディレクトリ構造 だとすれば [..] (親) や [.](カレント) のような記述は出来ますか?

出来ます。ただしPython 2.5以降

# "." がたくさん出てくるので 注意
from ..      import google
from .       import book.function
from ..Video import show

なんにつかうの? filter(), map(), reduce()

正直何に使うんだろう?と一瞬わからなかった。こいつら。filter, map, reduce。理解すると便利なので覚えよう。

  • 配列のそれぞれに対して、Callbackしてくれる関数群。
  • PHPだとarray_walk()。
  • 機能は__iter__()とGenerator使えば実現できる
def f(x): return x%2 == 0 #偶数かどうか調べる

print filter( f, range(1,10) )

# [ 2,4,6,8,]

JavaScript (prototype.js) ならこうなる

<script type="text/javascript" src="prototype.js" ></script>
<script type="text/javascript">

    var hoge = $R( 1,10, true );
    hoge = hoge.findAll( function(v){ return v%2==0; } );
    document.write(hoge);

    //hoge = 2,4,6,8

</script>


覚え方、配列にフィルタを掛ける。だから filter() ここは試験に出ますぉ


ちなみにPHPならこんなことになる

<?php

$hoge = range(1,9);
$hoge = array_filter( $hoge, create_function( '&$v, $i', 'return !($v&1);' ) );

var_dump($hoge);

$hoge = array_filter() が特徴的かな。

PHPは結果を代入することが多い、代入忘れがエラーの元に。ちなみにfilter()も結果を変数に代入が必要だよ。JavaScriptは代入不要。これは、Arrayの親クラスEnumerableが代入をやってくれてるから。

map()

prototype.jsだと、Enumerable.each() に相当する。Iteratorだとわかれば後は簡単。

#pow
seq = range( 1,10 );
seq = map( lambda x : x*x, seq )
print seq

reduce()

これは、PythonのドキュメントよりPHPのarray_reduce()のdocの説明がわかりやすい。

array_reduce() applies iteratively the function function to the elements of the array input, so as to reduce the array to a single value. If the optional initial is available, it will be used at the beginning of the process, or as a final result in case the array is empty. If the array is empty and initial is not passed, array_reduce() returns NULL.


array_reduce() は、配列 input の各要素に function 関数を繰り返し適用し、 配列を一つの値に減らします.オプション intial が利用可能な場合、処理の最初で使用されたり、 配列が空の場合の最終結果として使用されます。 配列が空で initial が渡されなかった場合は、 array_reduce() は NULL を返します。


phpマニュアルより

使用例。

#階乗
seq = range( 1,10 );
print map( lambda x,y : x*y, seq )
#[1, 4, 9, 16, 25, 36, 49, 64, 81]

条件分岐に使える 例外処理

私は、Javaでtry 〜 catch を条件分岐の代わりに使うのは非推奨と習った。富豪プログラミングの立場では推奨かもしれない。

Pythonでは条件分岐に使えと言わんばかりの使用になっている

Pythonの [try 〜 catch]

  • try:
  • except A:
  • except :
  • else:
  • finally:

のセット。

try:
    #statements 
except NameErorr, var : #Exceptionに与えられた文字列も同時に取得できる
    print var
except ( IOError, RuntimeError ):#複数のExceptionをまとめてCatch
    print 
except : #全部のExceptionをCatch
    print 
else :  #例外なしで無事通過したとき
    print "ok"
finally: #全ての後処理                  
    print "end"

例外を投げる

throw Exceptionと書きたいところだが、raise とかく

raise Excetion , "エラーです"
raise Exception("エラーです")

なぜ2番目の書き方がゆるされるか? ExceptionがClassだから。

ExceptionがClassということは、ユーザー定義のExceptionを利用できる

class SampleExcepion(Exception): #Exceptionを継承
    def __init__(self, value):
        self.value = value
    def __str__(self):
        return repr(self.value)

try:
   #statements
   raise SampleExcepion("foooo")
except SampleExcepion, e :
  print e.value

##output
# 'foooo'

with 構文のサポート

ECMAScriptには with 文というモノがある

withを使えば、名前空間を変えることが出来る デフォルトの名前空間は window

#type="text/javascript"

with( window.document.location ){
   alert("test");//関数が見つからないエラーになる
   window.alert("test");//実行される
   href="http://www.yahoo.co.jp";//実行される
}

これと同じではないが、Pythonには withがある。

withを使うことで、finallyの処理が華麗になる。

#with構文
with open("myfile.txt") as f:
    try:
        for l in f:
          print l
    except:
        print "some error occured"
    finally:
        f.close()

Javaなどでtry -catch - finally を使おうとすると変数のスコープで苦労する。

その問題を解決してくれるのがwith.withこの使い方はJavaScriptにも応用すると便利だよ。*1

*1:JavaScriptを実行するブラウザがwithをサポートしているか調べておくこと。ちなみにWSHでは使うことが出来た

なぜPythonを始めるか?

  • PHPPEARがいまいち。
  • PerlCPANMSDN並の巨大ダンジョンで困った。
      • 俺の中でCPANMSDNはラストダンジョンとエキストラダンジョン
      • 宝箱いっぱいなのでたまに冒険に出かける
    • 日常的に使いたくない
  • Pythonアイコンがかっこいい。Rubyのアイコンはダサイ。
  • Ruby処理系はやっぱ遅い気がする。
  • なんだかんだ言ってPHPはWEBワールド限定。。。
  • Perlは記号が多くて嫌い。

Pythonの特徴的なところ。

  • { } は使わない
  • インデントが { } の代わり
  • 新しいインデントの開始時には : を使う
  • print 関数だけは [,] でつなげばいい。*1
  • for x in a が使える*2
  • 文字列の繰り返しに "-" * 50 が使える
  • 配列の定義方法
  • 配列の扱いが特徴的
    • a[0:] 最初から
    • a[0:3] a[0], a[1], a[2]
    • a[0:10:-1] [9,8,7,6,5,4,3,2,1,0]
  • 変数にまとめて代入できる
    • a, b = 1,2
      • 配列も、これを使える
      • a[0:2] = ["1", "2"]
      • a[0], a[1] = "1", "2" と解釈する
        • perlPHPのeachを使わなくて良い
    • タプルと呼ばれる


Pythonのいけてないところ

  • 日本語ユーザーが少ない。
  • ドキュメントが貧弱
  • ドキュメントの日本語訳がもさい
  • 本が売ってない
  • 誤字多すぎ

Pythonの良いところ


とにかく、日本でPythonが流行してくれないことには。どうしようもない問題。国内だとRubyに確実に負けてます。個人的にはRubyブームは一過性じゃないかなと。

現在勉強した項目

*1:Pythonではprint は関数でない。reurnと同じく予約語です。

*2:for x in aの形式しか使えない

PythonのLambda

lambda で関数への参照を返せる

def f(n):
    """lambdaサンプル"""
    return lambda x : x + n

JavaScriptだとこんな感じかな?

var f = function(n){
    return function(x){ return n+x;  }
}


JavaScriptの関数をイメージすると理解しやすかった。

関数の引数は配列で渡す

ここがちょっと特徴的か?

関数のデフォルト値

def f( i,  foo = "bar" ):
        print foo
        print i

f(10)
#
# bar
# 10

関数のデフォルト値2

def f( i, foo="bar", hoo="book" ):
        print i
        print foo
        print hoo

f( 100, hoo="comic" )

#100
#bar
#comic

デフォルト指定があれば引数は省略可。省略する引数にnullを入れなくて良い。

必要な要素だけ名前指定で書けばいい。

PHP なら null で埋める。

PHPよりPythonの方が便利かも

<?php
public function f( $i, $foo = "var", $hoo = "comic" ){
    echo $i;
    echo $foo;
    echo $hoo
}

f( 100, null, "comic" );
?>

nullも省略して func( $i , , , ,); と書いても良いけれど。わかりにくくなるのでNULLつかってる。

Javascriptでもだいたい同じ。

JavaScriptはちょっと手続きが多いかな。

<script type="text/javascript">
var f = function( i, foo, hoo){
      i   = i;
      foo = foo || "var";
      hoo = hoo || "book";
      document.writeln(i);
      document.writeln(foo);
      document.writeln(hoo);
}

f( 100, null, "comic" );
</script>

Javaだと・・・タイプ量が・・考えたくない(w

関数のデフォルト値3

デフォルト値と可変引数を使うと、さぼれる。

Pythonだと楽で良いかな。JavaScriptだとfunciton.argmentオブジェクトを使う。

def f( i,  *foo, **a ):
        for x in foo :print x
        print i

f(10, "hoge", "moe", "tun")
# hoge
# moe
# tun
# 10

Javaで言う、可変引数。PHPならfunc_get_arg()などのリフレクション関数(?)で参照し利用する。

関数のデフォルト値4

さっきの例は、呼び出し時に使うことも出来る

a = [1,100]
range( *a);
# 1,2,3.....100

配列は関数の呼び出し時に展開される。これは便利。連想配列で、データを渡しやすい。データのパッケージ化のためのEnumやClass書かなくてすみそう。

tupleとlist

タプル。配列の一種。


ここらでPython配列まとめ。

Python配列には2種類ある

  • A 可変長
  • B 固定長
  • 固定長な配列
    • C言語っぽい配列
    • 文字列(string)
    • tuple
    • Set

と分類されてる。


何が違うか?変数の作り方を見れば一目瞭然だろう。

#List
list  = ["abc", "def", "ghi"]
#Tuple
tuple = ( "abc", "def", "ghi")
#Dictionary
dic   = {"abc": "123", "def": "456", "ghi" : "789"}
#Set
sets  = set(["sony", "apple", "sharp", "apple", "sharp", "sony"])
#sets=['sony','apple','sharp']

で、タプルは、オブジェクトというより言語構造に近い。

#タプルを使った例
a = 1,2,3
x,y,z = a
#こんなモノもタプルです

#引数がタプルで、戻り値もタプルな例
def f(x,y,z):
    return x,y,z

print f(*a)
#(1,2,3)

a,b,c = f(1,2,3)
#a =1, b=2, c=3


関数に使うと便利だと思うよ。rubyも、この形式取り入れてますよね。
関数の定義に使うので、配列形式というより、言語構造だと思う。

Set ユニーク値

配列の値に重複を許さない。配列のキーとして使うのかな。

#set()の例
print set([1,2,3,4,4,3,2,1])#1,2,3,4

a = set("google") #o,l,e,g
b = set("yahoo")  #y,a,o,h
print a - b #e,l,g
print b - a #y,a,h

Dictionary 辞書式配列

一般的に連想配列と呼ばれるモノ。JSON形式。あえて説明の必要はないと思うが。JavaでもDictionaryクラス(Hashtable, Properties)になる。

#Dictionary
dic = {}             # {}
dic["a"] = "apple"   # {'a':'apple'}
dic["c"] = "cupple"  # {'a':'apple', 'c':'cupple'}
del dic["a"]         # {'a':'apple'}
dic["p"] = "people"  # {'a':'apple', 'p':'people'}
dic["s"] = "sample"  # {'a':'apple', 'p':'people', 's':'sample'}
dic.keys()           # ['a', 'p', 's']
"a" in dic           # True
dic.has_key("s")     # True

Dictionary配列は関数を使って増やすことも出来る

#関数を用いた例
dict(j="jingle", "t"="tinkle")
dict([("s", "simple"), ("a", "ample")])

リストを文章で理解させる

filter()を使わず、map()を使わず、値をチェックする。そんな方法。

かなり特徴的

配列から、偶数を取り出し、各要素を2乗する処理。

さっきのmap()とfilter()を使うとこうなる
def f(x): return x%2 == 0

seq = filter( f, range(1,10) )
seq = map( lambda x : x*x, seq )
print seq

これを、英文で書いても、Pythonは理解してくれますよ。ってことらしい。

seq = range(1,10)
print [ x*x for x in seq if x%2==0 ] # x*x の x は seq にある要素で 偶数のもの

配列の値のチェックとか、条件分岐くらいPythonが理解してくれますよ ってこと。

 配列が英文っぽく書けますよってことがポイントらしい。


 英文が 
          (x) for x in array if x is something

 これが日本語なら、           
          この配列の要素 は (x) 、array の各要素xで x が something のもの

ってことか。


配列の中をもうちょっと英文っぽくすると。。。

 this array is consits of (x) for x in array if x is something.


filterやlambdaを使わわない、だからコードとコメントが減って楽になる。「ソースに語らせる」と良いソースコードが書けるよってことだろうね。


英文のドキュメントには List Comprehension (Pythonが配列表現を理解する)と書いてある。


英文風に書けるので便利でしょ? ってことらしい。

英語が使えない俺には便利がさがいまいち理解できない。

#空白が含まれる配列を受け取った、どうしよう
fruit = [" apple   " , "  orange", "banana", "mango  "]
#Pythonが解決します
fruit = [ name.strip() for name in fruit ]

この場合、『 [ ]の中身は、(name.strip()) で、name は fruit の中身 』 とPythonが解釈します

ってことらしい。


この機能、たぶん使わない。 だってJavaScriptPerlPHP書いてる人がソース見ても何のことかわからん。Pythonユーザーからすると、「それは読めばわかるだろ。」ってことだろうなぁ。

Pythonこれだけは覚えとく

PythonのString (逆順は-1から)
Pythonの配列  (配列から配列を簡単に取り出せる[1:2])
Pythonの関数  (デフォルト値は柔軟)
PythonのLambda (関数は遅延出来る
Pythonの可変引数 (配列が引数でもちゃん分解してくれる)



JavaScript はデフォルト値などの処理が手間
 →それPythonならSimpleに書けるよ。
Perlだとプログラミングスタイルが千差万別
 →それPythonなら統一して書けるよ
PHP予約語と関数多すぎ
 →それPythonならオブジェクトで書けるよ

配列のループにEnumerateとIterate

配列をforループで順次取り出すには配列毎に便利なメソッドが用意されている

Sequenceの場合

a = "goooooooooooogle"
for x,y in enumerate( a ):
    print x, " = ", y

Dictionaryの場合

a = {"Perl","Larry","Python":"Guido", "ruby":"Matz"]
for x,y in a.iteritems():
    print x, ":", y


他に、sorted,reversed で整理も出来る。

配列の比較

配列は、比較できる。前から順番に調べていき、違いが見つかったらそこでストップする。そこから後ろは評価されない。前から二つずつ値を取り出して調べる。

(1, 2, 3)              < (1, 2, 4)
[1, 2, 3]              < [1, 2, 4]
'ABC' < 'C' < 'Pascal' < 'Python'
(1, 2, 3, 4)           < (1, 2, 4)
(1, 2)                 < (1, 2, -1)
(1, 2, 3)             == (1.0, 2.0, 3.0)
(1, 2, ('aa', 'ab'))   < (1, 2, ('abc', 'a'), 4)

配列の型を超えて比較可能。