Python 基本 – クラス

Python で基本的なクラスの使用方法です。

  • クラスの作成
    • 空のクラス
    • インスタンス化
    • 変数の定義
    • 関数の定義
    • プライベートな変数・関数
  • コンストラクタ

クラスの作成

空のクラス

なにも行わない空のクラスを作成するには、以下の用にします

class EmptyClass:
    pass

インスタンス化

作成したクラスをインスタンス化するには、関数を変数に代入するように行います。

empty = EmptyClass()

変数の定義

クラスに変数を定義することが出来ます。いわゆるプロパティです。

class WordClass:
    geeting = 'hello'

インスタンス化してアクセスするには .(ドット・ピリオド) でアクセスします。

word = WordClass()
word.greeting

出力結果は以下になります。

'hello'

関数の定義

クラスに関数を定義することが出来ます。いわゆるメソッドです。作成方法は通常の関数と同様に、def を使用します。

class GreetingClass:
    def sayHello(self):
        print 'hello'  # Python 2
        print('hello') # Python 3 ~

クラス内関数の第一引数には、自分自身を表すオブジェクトが代入されています。 名前はなんでも良いのですが、Python では通例的(?)に self が使われるようです。

※Python 2 では 上の print。Python 3 では下のプリント文を使用します。

メソッドを実行するには、インスタンス名の後に.(ドット・ピリオド)、その後に通常の関数を実行するようにします。

word = GreetingClass()
word.sayHello()

出力結果は以下の用になります。

hello

プライベートな変数・関数の作成

外から完全にアクセスできない、プライベートな変数・関数を作成することが出来ないようです。代わりに、変数・関数の先頭に _(アンダーバー)を付けることで、これはプライベートなものですよ!と認識(コードを読む人が)出来るようにします。

また _(アンダーバー)を2つ付けた場合、簡単なマングリング(難号化)が行われて、_クラス名 が先頭に付加されます。(仕様的には、__で始まり__で終わらないものに対してマングリングが行われます)

class PrivateClass:
    _privateVar = 'private'
    __mangledVar = 'mangled'

上記のクラスの変数にアクセスすると以下の用になります。

pri = PrivateClass()
pri._privateVar
pri._PrivateClass__mangledVar

コンソールでの出力結果は以下になります。

'private'
'mangled'

コンストラクタ

Python のクラスで、インスタンス化したときに初期化を行う、”コンストラクタ” を定義するには __init__ という名前で関数を定義します。

class initClass:
    def __init__(self):
        print('init...')


init = initClass()  # init が出力されます

Python 3.3.3 のコンパイル&インストール

今更ですが、Python3系がなかったので 3.3.3 をソースコードからインストールしてみます。
環境は debian 7.1 となります。

ソースコードのダウンロード

まずはソースコードをダウンロードします。

wget www.python.org/ftp/python/3.3.3/Python-3.3.3.tar.xz

ダウンロードしたファイルを解凍します。

tar Jxvf Python-3.3.3.tar.xz

コンパイル&インストール

初めにコンパイルの設定を行います。

cd Python-3.3.3
./configure --prefix=/usr/local/python --enable-shared

私の環境では gcc がなかったので以下のエラーが出ました。

configure: error: no acceptable C compiler found in $PATH
See `config.log' for more details

なので、GCC コンパイラをインストールします

aptitude install gcc

もう一度設定し直します。

./configure --prefix=/usr/local/python --enable-shared

コンパイルを行います。

make

…make もなかったので make をインストールします。

aptitude install make

再びコンパイルをします。

make

インストールします。

make install

これで python 3.3.3 が /usr/local/python 以下にインストールされました。
次に、インストールした共有のライブラリをシステムに認識させる必要があります。
/etc/ld.so.conf に /usr/local/python/lib を追記するのですが、debian だと、ld.so.conf の他に ld.so.conf.d ディレクトリがあり、ld.so.conf ファイルはそのディレクトリの中身を include しているようです…
そこに個別でファイルを設けてその中に記述してね!っていう意味だと思うので、 python3.3.3.conf ファイルを作成してその中に記述します。

cd /etc/ld.so.conf.d
echo "/usr/local/python/lib" >> python3.3.3.conf

設定ファイルが完了したら ldconfig を実行します。

ldconfig

これで準備は完了です。綺麗に動作するか確認しましょう

/usr/local/python/bin/python3 -V
Python 3.3.3

Python 3.3.3 と出力されれればインストールは完了となります。

使いやすいようにシンボリックリンクを貼っておきます。

cd /usr/local/bin
ln -s ../python/bin/python3

これで python3 でコマンドを実行出来るようになります。

参考

http://librabuch.jp/2013/01/python33-install/

Python 基本 – リスト(配列)

リストは様々なタイプのデーターをまとめて一つのグループにするために利用されます。
違う種類のデータを同時に格納することが出来ますが、通常は同じタイプを使用します。

基本形

整数

>>> numbers = [100, 200, 300, 400, 500]
>>> numbers
[100, 200, 300, 400, 500]

文字列

>>> string = ['string']

リストの中にリスト

リストは入れ子にすることが出来ます。

>>> images = [['image.jpg', [100, 100]], ['image2.jpg', [150, 100]]]

データの取得

リスト内のデータを取得するにはインデックスを指定します。
戻り値はインデックスにあるデータになります

>>> numbers = [100, 200, 300]
>>> numbers[2]
300

インデックスは 0 から始まります。

>>> numbers = [100, 200, 300]
>>> numbers[0]
100
>>> numbers[1]
200
>>> numbers[2]
300

負数を指定すると後ろからの値を指定出来ます

>>> numbers = [100, 200, 300]
>>> numbers[-1]
300
>>> numbers[-2]
200
>>> numbers[-3]
100

リストの中のリストにアクセスするには [添字] を続けて書きます。

>>> images = [['image.jpg', [100, 100]], ['image2.jpg', [150, 100]]]
>>> images[1][0]
'image2.jpg'

スライス

インデックスを : (コロン)で区切るとリストをスライス(切り取り)をすることが出来ます。
戻り値は指定した範囲のリストになります

>>> numbers = [100, 200, 300]
>>> numbers[0:2]
[100, 200]
>>> numbers[1:3]
[200, 300]

添字は省略することが出来ます。初めを省略すると、初めの値から始まります(0を指定したことと同じですかね)
最後を省略すると一番最後の値を指定していることになります。

>>> numbers = [100, 200, 300]
>>> numbers[:2]
[100, 200]
>>> numbers[1:]
[200, 300]

スライスにリストを代入するとその範囲に新たに値を追加することが出来ます。

>>> numbers = [100, 200, 300]
>>> numbers[1:3] = [150, 200, 250, 300]
>>> numbers
[100, 150, 200, 250, 300]

指定の範囲を削除することも出来ます。

>>> numbers = [150, 200, 250, 300]
>>> numbers[:2] = []
[250, 300]

どちらも省略することも出来ます。これはリストのコピーを作成しているのと同じことになります。

>>> numbers[:]
[100, 200, 300]

全ての削除も可能です

>>> numbers[:] = []
>>> numbers
[]

長さを取得

リストの長さを取得するには組み込み関数の len() を使用します

>>> alphabets = ['a', 'b', 'c', 'd', 'e']
>>> len(alphabets)
5

結合

リストには + 演算子を使用することが出来て、リスト同士を結合させることが出来ます。リスト自体に変更は加えません。

>>> numbers = [100, 200, 300]
>>> numbers + [400, 500, 600]
[100, 200, 300, 400, 500, 600]

繰り返し連結

* 演算子を利用することも出来ます。+ はリスト同士を結合して新たなリストを返しますが、
リスト * i
はリストを i の分繰り返した新たなリストを返します。

>>> numbers = [1, 10, 100]
>>> numbers * 3
[1, 10, 100, 1, 10, 100, 1, 10, 100]

追加(append, extend, insert)

+ 演算子はリストを合わせた新しいリストを作成しますが、リスト自体に追加したい場合もあると思います。リストのリストの最後に新たにリストを値を追加するには append() を使用します。

>>> numbers = [100, 200, 300]
>>> numbers.append(400)
>>> numbers
[100, 200, 300, 400]

以下の表現も同様の意味になります。

numbers[len(numbers):] = [400]

別のリストを追加するには extend() を使用します

>>> numbers = [100, 200, 300]
>>> numbers.extend([400, 500, 600])
[100, 200, 300, 400, 500, 600]

以下の表現も同様の意味になります。

numbers[len(numbers):] = [400, 500, 600]

指定した位置に新しく要素を挿入するには insert(i, x) を使用します。
i にインデックス、x に挿入するデータを指定します。i の値の直前に挿入が行われます。

>>> numbers = [100, 200, 300]
>>> numbers.insert(1, 150)
>>> numbers
[100, 150, 200, 300]

削除(remove, del文)

中身の要素を指定して削除するには remove(値) を使用します。 remove は初めに見つかった要素のみを削除します。

>>> numbers = [100, 200, 300, 100, 200, 300]
>>> numbers.remove(200)
>>> numbers
[100, 300, 100, 200, 300]

remove は削除する値を指定しましたが、削除したいインデックスを指定するには del 文を使用します。

>>> numbers = [100, 200, 300, 100, 200, 300]
>>> del numbers[1]
>>> numbers
[100, 300, 100, 200, 300]

del 文はスライスでも使用できます。

>>> numbers = [100, 200, 300]
>>> del numbers[:2]
>>> numbers
[300]

中身だけを全て削除することもできます。

>>> numbers = [100, 200, 300]
>>> del numbers[:]
>>> numbers
[]

変数自体を削除することも出来ます。この場合は、変数に何かが代入されるまではアクセスするとエラーがでます。

>>> numbers = [100, 200, 300]
>>> del numbers
>>> numbers
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'numbers' is not defined

検索(index)

リストのインデックスを値から取得出来ます。初めに見つかったインデックスのみを返します。

>>> numbers = [100, 200, 300, 100, 200, 300]
>>> numbers.index(200)

取り出し: pop([i])

リストの中から指定した値を取り出します。リストから取り出された値は削除されます。i(index) に何も指定しない場合は、リストの末尾の要素を削除して返します。

>>> numbers = [100, 200, 300, 100, 200, 300]
>>> numbers.pop()
300
>>> numbers.pop(2)
300
>>> numbers
[100, 200, 100, 200]

出現回数(count)

指定したリスト内の要素の出現回数をカウントするには count(x) を使用します。

>>> information = ['i', 'n', 'f', 'o', 'r', 'm', 'a', 't', 'i', 'o', 'n']
>>> information.count('i')
2

並び替え(sort)

要素の並び替えを行うには sort() を使用します。数字であれば小さい順、文字列であれば文字コードの並び順でソートが行われます。(In place)

>>> numbers = [1, 33, 35, 6, 763, 10]
>>> numbers.sort()
>>> numbers
[1, 6, 10, 33, 35, 763]

逆順(reverse)

要素の並びを逆順にするには reverse() を使用します。
小技として、sort() で並べ替えると”昇順”になるのですが、sort() の後に reverse() を掛けると”降順”になります。

>>> numbers = [1, 6, 10, 33, 35, 763]
>>> numbers.reverse()
>>> numbers
[763, 35, 33, 10, 6, 1]

リストの内包表記

ループを回した結果をリストにする場合に簡単に表記する方法が内包表記です。
例えば 0 ~ 8 までの偶数のリストを作成したい場合、普通に書くと以下の用になります。

>>> evenNumbers = []
>>> for x in range(0, 10, 2):
...     evenNumbers.append(x)
...
>>> evenNumbers
[0, 2, 4, 6, 8]

これを内包表記に変更すると以下の用になります。

>>> evenNumbers = [x for x in range(0, 10, 2)]
>>> evenNumbers
[0, 2, 4, 6, 8]

初めの x がリストの各要素に代入される結果になり、そこで演算することも可能です。それぞれの半分にした値にする場合、以下の用になります。

>>> numbers = [x*0.5 for x in range(0, 10, 2)]
>>> numbers
[0.0, 1.0, 2.0, 3.0, 4.0]

参考

http://docs.python.jp/3.3/tutorial/introduction.html
http://docs.python.jp/3.3/tutorial/datastructures.html

簡易Webサーバーの作成(CGIHTTPServer)

Python の基礎もあまり出来ていませんが、CGIHTTPServer なるものを利用してとりあえず動くものを作成してみようかと思います。
SimpleHTTPServer というものもありますが、CGIHTTPServer は CGI も動くということなのでこちらをを使用します。

サーバースクリプトの作成

サーバーとしての機能を提供する為のスクリプトを作成します。

import CGIHTTPServer
CGIHTTPServer.test()

これだけです。簡単ですね。上記のコードだけで Web サーバーとしての動作をひと通りしてくれます。
ちなみにスクリプトを作成しなくても以下のコマンドを実行するだけで動作してくれます。

python -m CGIHTTPServer

CGIHTTPServer は、実行した時のカレントディレクトリをドキュメントルートとして、ポートは 8000 を、HOST に 0.0.0.0(localhost, 127.0.0.1 ?) として動作するようです。

この時点で http://localhost:8000/ にアクセスすると実行したディレクトリのリストが表示されます。
CGIHTTPServer_01

index.html の設置

実行したディレクトリに index.html を作成して設置します。


<html>
<head>
    <meta charset="utf-8">
    <title>CGIHTTPServer</title>
</head>
<body>
    <h1>CGIHTTPServer のテスト</h1>
</body>

この状態で再び http://localhost:8000/ にアクセスすると以下の状態になり index.html が綺麗に表示出来ているのが確認出来ると思います。
CGIHTTPServer_02

CGIの作成

静的な html ファイルの表示ができたので CGI のスクリプトを作成してみます。

CGIHTTPServer は /cgi-bin ディレクトリ以下にあるファイルを CGI として実行する設定のようなので初めに cgi-bin ディレクトリを作成します。
そしてその中に simplecgi.py というファイルを作成します。

#!/usr/bin/env python

print 'Content-type: text/html\n'
print 'Simple Python CGI.'

そして http://localhost:8000/cgi-bin/simplecgi.py にアクセスすると Simple Python CGI. が表示されると思います。
CGIHTTPServer_03

これで CGI を作成することが出来ました。後は必要な処理を Python のスクリプトで書いていくことが出来ます。

Python 基本

Python の基本機能です。Python というよりもプログラミング言語に最低限必要な機能一覧です。

コメント文字

# コメントアウトをするには #シャープ を使います。
# これはコメントアウトになります

ブールの表記

True False になります。

変数

PHP の $ 等の必要な文字列はなく、普通に使えます。

# variable という変数に 文字列 'variable' を代入
variable = 'variable'

文字列(ACSII文字)

文字列は ”” (ダブルクォーテーション) または ” (シングルクォーテーション)で囲みます。

'Single Quote'
"Double Quote"

文字列(日本語:マルチバイト)

日本語を扱うにはそのままだと以下の様なエラーが発生します。

UnicodeDecodeError: 'cp932' codec can't decode byte 0x9e in position 209: illegal multibyte sequence

文字コードを指定してあげると問題なく処理出来るようになります。文字コードを指定するにはファイルの先頭に # coding: UTF-8 を追加してあげます。
UTF-8 以外にも Shift_JIS や EUC-JP も指定出来ます。

# coding: UTF-8
'日本語(マルチバイト)を記述してもエラーが発生しなくなります。'

標準出力に出力

標準出力に出力するにはprint()を使用します。

print('hello world')  # hello world と出力されます

リスト(配列)

ディクショナリ(連想配列/hash/map)

ディクショナリの使い方は {‘key’: ‘value’} を利用します。
アクセスするには添字を利用します。a['key']

d = {'key': 'value'}
d['key']  # value が返ります

代入(上書き)

上書きをするには 添字 に代入を行います。

d = {'key': 'value'}
d['key'] = 'VALUE'
d['key']  # VALUE が返ります

追加

追加するには新たなキーになる添字に代入を行います

d = {'key': 'value'}
d['key2'] = 'value2'  # {'key': 'value', 'key2': 'value2} になります

削除

削除するには del dic[添字] を使用します

d = {'key': 'value', 'key2': 'value2'}
del d['key']  # {'key': 'value'} となります

演算子

大体の言語と同じようです

+ - / * %  # 計算
== != < > <= >=  # 比較

などなど…

IF(条件分岐)

if の書き方は以下のようになります。

if 条件:
    # 条件 = True の処理
elif 条件2:
    # 条件2 = True の処理
else:
    # 上記の条件以外の場合の処理

FOR(ループ)

for の書き方は以下の用になります。

for i in range(100):
    # 0 から 99 までループ

リストをループすることが出来ます

fruit = ['apple', 'banana', 'cake']
for f in fruit:
    # 全要素のループ

ディクショナリの場合

dic = {'apple': 'ringo', 'cake': 'ke-ki'}
for key, value in dic.items():
    # key と value 全要素のループ

関数

関数を定義するには以下のようにします

def 関数名(引数):
    # 処理
    return  # 戻り値を指定します

モジュールのインポート(include)

外部のモジュールをインポートするには import 文を使用します

import os
os.getcwd()  # カレントディレクトに取得

クラス

これぐらいで大体のことは出来ますかね…

Python の学習記録 – 目次

Python の学習を初めようと思います。忘れないように記録として残しておくことにしました。
一つの目標として、Python で Web サーバーを作成してメモ帳のようなものを動かしてみようかなと思っています。
SimpleHTTPServer というものがあるのですがそれを利用しない予定です。WSGI アプリケーションを作成してみようかと思います。

  • Python 基本

    Python でのプログラミングに最低限必要だと思われる基本的なこと

  • 簡易Webサーバーの作成(CGIHTTPServer)

    Python に初めから組み込まれているモジュールCGIHTTPServerモジュールを利用して簡易Webサーバーを作成しました。
    (慣れることを目標に…)

Apache をポート番号でサイトを振り分ける(DocumentRoot を変更)

公開サーバーの運用時には必要ないと思いますが、今回は開発用のサーバーでポート毎に DocumentRoot を設定すると円滑に行くかなと思ったので、ポート毎に別の DocumentRoot を割り当てるように Apache を設定してみました。

今回は Apache の mod_vhost_alias を使用することにします。

NameVirtualHost のディレクティブに全てのポートを利用するように設定

/etc/httpd/conf/httpd.conf (CentOS 6.3)

NameVirtualHost *:*

バーチャルホストの設定

以下を一番下に追加します。
/etc/httpd/conf/httpd.conf (CentOS 6.3)

<VirtualHost *:*>
	ServerAdmin [email protected]
	ServerAlias *
	VirtualDocumentRoot /var/www/html/%p

	<Directory /var/www/html/*>
		Options All
		AllowOverride All
	</Directory>
</VirtualHost>
%p
アクセスしたポート番号に変換されます

この状態で
http://ホスト:81/index.html
にアクセスすると
/var/www/html/81/index.html
が読みこまれます。

これで振り分けられるようですが何故か DocumentIndex が効かないようで localhost:81 としても読まれるファイルは何故か /var/www/html/80/index.html になってしまうようです…何かが間違ってそうです

問題点

この設定で CakePHP を動かそうとすると無限リダイレクトが発生して正常にアクセス出来ないようです。その場合は ルート /app/ /app/webroot/ .htaccess の <IfModule mod_rewrite.c> の中に RewriteBase / を追加します。
参考:
http://stackoverflow.com/questions/10392258/cakephp-and-virtualdocumentroot-issue
http://bakery.cakephp.org/articles/tim_m/2007/09/20/500-errors-with-1and1-hosting-apache-1-x

ここまでの状態で、アクセスは可能になっているようですが私の環境では


Forbidden
You don't have permission to access /app/webroot/ on this server.

というエラーが出てきました。直接 /app/webroot にはアクセス出来るのでパーミッションは問題なさそうです。
しばらく調べていると以下の情報がありました。

http://www.lost-in-code.com/server-management/403-forbidden-you-dont-have-permission-to-access-on-this-server/

どうやら DirectoryIndex に index.php を追加すれば動くらしいです。
VirtualDocumentRoot を使用する前は問題なく CakePHP が動いていたので問題ないんじゃないかな?と思いつつもとりあえず設定してみると…動きました…

今まで動いていたのはなぜでしょうか…
まあ動いたので問題なさそうです。

AWS で sudo の設定を間違えると管理者になれなくなる

AWS 自体のことはあまりわからないのですが、デフォルトで ec2-user というのがあるようです。このアカウントは sudo でパスワードを入力しなくても実行出来るようになっています。

今回行ったのは apache グループに全てのコマンドで sudo 出来るようにする設定です。

sudo visudo

でファイルの一番下に以下を追加しました。

%apache ALL=(ALL) ALL
%apache
設定するユーザー名(% を初めにつけるとグループ名)
ALL
ホストの設定(通常ALL)
=(ALL)
使用できるユーザー権限(ALLなら全て)
ALL
使用可能なコマンド(複数指定は,(カンマ)を使用する)

上記の行を追加した状態で保存しました。

そして改めて sudo を実行すると


[[email protected] ~]$ sudo ls
[sudo] password for ec2-user: 

とパスワードを求められるようになりました…
ec2-user のパスワードは設定していないのでわかりません。

なので、管理者権限での操作が一切出来なくなりました…

apache グループに設定したはずなのになぜ ec2-user の設定が変更されたのかわけがわかりませんでした。
ふとグループを確認してみると、


[[email protected] ~]$ groups
ec2-user wheel apache

………apache…

ec2-user は apache グループに所属していました…
恐らく、ファイルの一番下に上記の一行を追加したために、NOPASSWORD が設定されている項目を上書きしてしまいパスワードを求められる用になったようです…

色々調べましたが…解決方法は見当たりませんでしたww

削除しかなくなりました。 sudo の設定をする前はユーザーのグループも確認するようにします。。。