@blog.justoneplanet.info

日々勉強

Pythonの条件節

■比較の連鎖

Pythonでは以下のように比較を連続して記述できる。

a = 3
b = 5
c = 7
if(a < b < c):
    print('hoge');
#hoge

ちなみにPHPではできない。

$a = 3;
$b = 5;
$c = 7;
if($a < $b < $c){
    print('hoge');
}
//Parse error: syntax error, unexpected '&lt;'

■条件節の中の代入文

Pythonでは以下のように条件節で代入文を記述することはできない。

b = [0, 3, 5]
if((a = b[1]) > 0):
    print('hoge')
#SyntaxError: invalid syntax

これについては公式マニュアルで以下のように説明されている。

Python では、C 言語と違って、式の内部で代入を行えないので注意してください。 C 言語のプログラマは不満を呈するかもしれませんが、この仕様は、 C 言語 プログラムで遭遇する、式の中で == のつもりで = とタイプ してしまうといったありふれた問題を回避します。

ちなみにPHPではできる。

$b = array(0, 3, 5);
if(($a = $b[1]) > 0){
    print('hoge');
}
#hoge

Djangoをインストールする

以下のコマンドでインストールする。

wget http://www.djangoproject.com/download/1.2.3/tarball/
tar xzvf Django-1.2.3.tar.gz
cd Django-1.2.3
python setup.py install

以下のコマンドでインストールできたか確認する。

python
import django
print(django.VERSION)
#(1, 2, 3, 'final', 0)

■プロジェクト作成

以下のコマンドでプロジェクトを作成する。

django-admin.py startproject dj

■開発サーバ起動

以下のコマンドで開発サーバを起動する。

cd dj
chmod 0744 manage.py
./manage.py runserver

以下のようにポートを指定することもできる。

cd dj
chmod 0744 manage.py
python ./manage.py runserver 0.0.0.0:80

■設定ファイル

以下のコマンドで設定ファイルを編集する。

vi setting.py

試しに編集してみる。

タイムゾーン

以下の項目を

TIME_ZONE = 'America/Chicago'

以下のように変更する。

TIME_ZONE = 'Asia/Tokyo'

言語

以下の項目を

LANGUAGE_CODE = 'en-us'

以下のように変更する。

LANGUAGE_CODE = 'ja'

データストア

以下のように記述して設定する。

DATABASES = {
    'default': {
        'ENGINE': 'sqlite3',
        'NAME': os.path.dirname(__file__) + os.sep + 'dj.sqlite',
        'USER': '',
        'PASSWORD': '',
        'HOST': '',
        'PORT': '',
    }
}

MySQLならば以下のようになる。

DATABASES = {
    'default': {
        'ENGINE': 'mysql',
        'NAME': 'dbname',
        'USER': 'admin',
        'PASSWORD': 'hogehoge',
        'HOST': 'localhost',
        'PORT': '3306',
    }
}

■DBセットアップ

このまま初期状態を生成しようとするとエラーが出るはずだ。

sqlite

以下のようなエラーが表示される。

ImproperlyConfigured("Error loading %s: %s" % (module, exc))
django.core.exceptions.ImproperlyConfigured: Error loading pysqlite2 module: No module named pysqlite2

pythonからsqliteに接続するドライバが無いらしいので、以下のコマンドでインストールする。

wget http://pypi.python.org/packages/source/p/pysqlite/pysqlite-2.6.0.tar.gz
tar xzvf pysqlite-2.6.0.tar.gz
cd pysqlite-2.6.0
python setup.py install

MySQL

以下のようなエラーが表示される。

raise ImproperlyConfigured("Error loading MySQLdb module: %s" % e)
django.core.exceptions.ImproperlyConfigured: Error loading MySQLdb module: No module named MySQLdb

pythonからMySQLに接続するドライバが無いらしいので、以下のコマンドでインストールする。

setuptools

MySQL-pythonをインストールする際に必要なので、先にインストールする。

wget http://pypi.python.org/packages/source/s/setuptools/setuptools-0.6c11.tar.gz
tar xzvf setuptools-0.6c11.tar.gz
cd setuptools-0.6c11
python setup.py install
MySQL-python

以下のコマンドでMySQL-pythonをインストールする。

wget http://pypi.python.org/packages/source/M/MySQL-python/MySQL-python-1.2.3.tar.gz
tar xzvf MySQL-python-1.2.3.tar.gz
cd MySQL-python-1.2.3
python setup.py install

エラー1

インストールの途中で以下のようなエラーが発生するかもしれない。

_mysql.c:2444: error: '_mysql_ConnectionObject' has no member named 'open'
error: command 'gcc' failed with exit status 1
対策

以下のコマンドでmysql-develをインストールする。

yum --enablerepo=remi,epel install mysql-devel.x86_64

■アプリケーション生成

以下のコマンドでアプリケーション(の一部)を生成する。

./manage.py startapp article

以下のコマンドを実行してsetting.pyにも反映させる。

vi setting.py

以下の部分を

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
)

以下のように変更する。

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'dj.article',
)

■モデル

以下のコマンドでモデルを編集する。

cd article
vi model.py

編集前は以下のように記述されている。

from django.db import models

# Create your models here.

例えば以下のようにモデル部分を記述する。

# -*- coding: utf-8 -*-
from django.db import models

# Create your models here.
class Article(models.Model):
    id      = models.AutoField(primary_key = True)
    title   = models.CharField(max_length = 256)
    content = models.TextField()
    date    = models.DateField()
    class Meta:
        db_table = 'article'# table name

■コマンドラインから操作

なんでも生成したクラスを使ってデータの挿入ができるらしいぞ!

./manage.py shell

以下を入力する。

from article.models import Article
article = Article()
article.title = 'hogehoge'
article.content = 'this is a hoge pen'
article.date = '2010-10-10'
article.save()

なんと直感的なデータ挿入でござんしょう!

■テンプレートの生成

以下のコマンドを入力し設定ファイルを編集する。

vi setting.py

以下のように記述しテンプレートファイルの格納場所を指定する。

TEMPLATE_DIRS = (
    '/var/www/vhosts/domain/subdomains/dj/templates',
)

/var/www/vhosts/domain/subdomains/dj/templates/page/article.html

以下のようにテンプレートファイルを記述する。

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>{{article.title}}</title>
<head>

<body>
<h2>{{article.title}}</h2>
<nav class="date">{{article.date}}</nav>
<article>
{{article.content}}
</article>
</body>
</html>

分かると思うけど、{{}}の部分は変数が展開されるところですな。アサインした変数は自動でエスケープされるが、その処理を無効化したい場合は以下のように記述する。

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>{{article.title}}</title>
<head>

<body>
<h2>{{article.title}}</h2>
<nav class="date">{{article.date}}</nav>
<article>
{{article.content|safe}}
</article>
</body>
</html>

これでHTMLを含んだコンテンツを反映することができる。但し、XSSには注意すること。

■URLディスパッチャの設定

vi urls.py

以下のように記述する。

urlpatterns = patterns('',
    (r'^article/(?P<id>[0-9]+)/$', 'dj.article.views.article'),
)

■ビュー関数

以下のコマンドでビュー関数を付加する。

vi article/views.py

以下のように記述する。

from django.http import HttpResponse
from django.template import Context, loader
from models import Article

# Create your views here.
def article(request, id):
    article = Article.objects.get(id = id)
    tpl     = loader.get_template('page/article.html')
    context = Context({'article' : article})
    return HttpResponse(tpl.render(context))

もう直感的にガシガシくる感じだね!

■確認

以下のコマンドを入力して開発サーバを起動しブラウザで確認する。

./manage.py runserver 192.168.1.123:8080

Pythonで文字列の変数を展開する

以下のようにして文字列内の変数を展開する。

a = 'This'
b = 'pen'
print "%(a)s is a %(b)s" % locals()
#This is a pen

以下のように書いたほうが分かりやすい気がする。

print "%(a)s is a %(b)s" % {"a" : "This", "b" : "pen"}
#This is a pen

Pythonでは本来出来ないものなので、この辺はPHPの方が気持ちいいね。

Pythonでモジュールを使う

モジュールは Python の定義や文が入ったファイル。 ファイル名はモジュール名に接尾語 ,py がついたものになる。 モジュールの中では、モジュール名をグローバル変数 __name__ で取得できる。

■クラスのモジュール

/dog.py

まずはモジュールを定義する。

class Dog:
    name = ''
    def __init__(self, name):
        self.name = name
    def cry(self):
        print(self.name)

モジュールだからといって特に変わった記述をする必要はない。

/index.py

以下のようにして上述のモジュールを使用する事ができる。

import dog

pochi = dog.Dog('pochi')
pochi.cry()

ちなみに以下のようにしてしまうと、Dogクラスにアクセスできなくなってしまうので注意が必要だ。

import dog

dog = 'pochi'
pochi = dog.Dog('pochi')
pochi.cry()

また、以下のようにしても使用する事ができる。この場合、モジュール名dogがローカルのシンボルテーブル内では定義されない。

from dog import Dog

pochi = Dog('pochi')
pochi.cry()

更に、以下のように*を使用することもできる。この場合、アンダーバーで始まる名前以外を全てインポートすることができる。

from dog import *

pochi = Dog('pochi')
pochi.cry()

■関数のモジュール

/hoge.py

モジュールファイルに関数が記述されていることもあるはずだ。

str = 'fuga'
def fuga():
    return str

/index.py

以下のようにしてhogeモジュールを使用することができる。また、モジュール内のグローバル変数にアクセスすることもできる。

import hoge

hoge.str = 'piyo'
value = hoge.fuga()
print(value)# piyo

■モジュール検索パス

以下のようにインポートする場合を考える。

import hoge

上述の場合、モジュールは以下のパスから検索される。

  • カレントディレクトリ内のhoge.py
  • sys.pathリストのディレクトリ内のhoge.py

モジュールを定義するときは標準モジュールと名前が被らないようにしないと!

■パッケージ

/Hoge/__init__.py

パッケージの各ディレクトリに必要なファイル。ファイルの中身は空で良い。

/Hoge/dog.py

パッケージ内のモジュールについては以下のようにする。特に変わったところはない。

class Dog:
    __name = ''
    def __init__(self, name):
        self.__name = name
    def cry(self):
        print(self.__name + ', bow!')

/index.py

パッケージ内のモジュールは以下のようにして使用する。

from Hoge import dog

pochi = dog.Dog('pochi')
pochi.cry()

また、以下のようにして使用することもできる。

import Hoge.dog

pochi = Hoge.dog.Dog('pochi')
pochi.cry()

Pythonにおける型変換

Pythonにおける文字列の結合はPHPやJavaScriptとは違うので気を付けないといけない。

■文字列と数値の結合

Pythonでは以下のように文字列と数値を結合することはできない。

"hoge" + 2000
#TypeError: cannot concatenate 'str' and 'int' objects

正しい記述

"hoge" + str(2000)
#hoge2000

PHPやJavaScriptでは以下のように文字列と数字の結合ができる。

PHP

print('hoge' . 2000);// hoge2000

JavaScript

document.write("hoge" + 2000);// hoge2000

■比較時の型変換

Pythonは比較時に数字のような文字列が数字に変換されたりはしない。

if(2000 == "2000"):
    print('hoge');
elif(2000 != "2000"):
    print("fuga")
#fuga

従って、PHPやJavaScriptにおける===などの型まで比較する演算子が、Pythonには存在しない。

Pythonでクラスを定義する

Pythonでclassを定義するには以下のように記述する。

class Dog:
    name = ''
    def __init__(self, name):
        self.name = name
    def cry(self):
        print(self.name)

dog = Dog('pochi')
dog.cry()#pochi

■継承

Pythonでclassを継承するには以下のように記述する。

class Animal:
    name = ''
    def __init__(self, name):
        self.name = name

class Dog(Animal):
    talk = 'bow!'
    def cry(self):
        print('this is ' + self.name + '! ' + self.talk)

class Cat(Animal):
    talk = 'mew!'
    def cry(self):
        print('this is ' + self.name + '! ' + self.talk)

dog = Dog('pochi')
dog.cry()#this is pochi! bow!
cat = Cat('doraemon')
cat.cry()#this is doraemon! mew!

■多重継承

Pythonは多重継承をサポートした言語である。自分の中では初めての多重継承((o(^-^)o))。以下のような記述になる。

class Robot:
    color = ''
    def __init__(self, color):
        self.color = color

class Cat:
    name = ''
    def __init__(self, name):
        self.name = name
    def cry(self):
        print('mew!')

class Doraemon(Robot, Cat):
    name = 'Doraemon'
    def intro(self):
        print('My name is ' + self.name + '(' + self.color + ')!')

doraemon = Doraemon('blue')
doraemon.intro()#My name is Doraemon(blue)!
doraemon.cry()#mew!
doraemon.name#Draemon

ドラえもんクラスを作って考えてみることにした。まず、ドラえもんはロボットなので以下のようなRobotクラスを作る。

class Robot:
    color = ''
    def __init__(self, color):
        self.color = color

ドラえもんはネコ型なのでCatクラスも継承するはずなので、以下のように定義する。

class Cat:
    name = ''
    def __init__(self, name):
        self.name = name
    def cry(self):
        print('mew!')

以下のようにドラえもんは量産型なのでクラス化して、RobotクラスとCatクラスを継承する、

class Doraemon(Robot, Cat):
    name = 'Doraemon'
    def intro(self):
        print('My name is ' + self.name + '(' + self.color + ')!')

以下のように、Draemonクラスをインスタンス化して使ってみるする。

doraemon = Doraemon('blue')
doraemon.intro()#My name is Doraemon(blue)!
doraemon.cry()#mew
doraemon.name#Draemon

上述のDaraemonクラスにはコンストラクタが存在しない。このような場合の解決規則は、(継承を記述した部分で)左から右へ探索し解決される。多重継承は非常に注意して使わないと分かりにくくなる。従って多重継承をサポートしない言語が多いということがある。

■プライベート変数

name変数は外から変更できないほうが良い。従って以下のようにアンダースコアを2つ続けて書くことでプライベートにする。

class Dog:
    __name    = ''
    __counter = 0
    def __init__(self, name):
        self.__name = name
    def cry(self):
        print('This is ' + self.__name + '(' + str(self.__counter) + ')')
        self.__count()
    def __count(self):
        self.__counter = self.__counter + 1

dog = Dog('pochi')
dog.cry()#This is pochi(0)
dog.__name#error
dog.__count()#error
dog.cry()#This is pochi(1)

上述の通り、プライベートになり外からアクセスすることが出来なくなる。しかし、Pythonはプライベート変数に外から強引にアクセスすることもできる言語仕様だ。

class Dog:
    __name    = ''
    __counter = 0
    def __init__(self, name):
        self.__name = name
    def cry(self):
        print('This is ' + self.__name + '(' + str(self.__counter) + ')')
        self.__count()
    def __count(self):
        self.__counter = self.__counter + 1

dog = Dog('pochi')
dog.cry()#This is pochi(0)
dog._Dog__name#pochi
dog._Dog__count()
dog.cry()#This is pochi(2)

■クラスの入れ子

Javaと同じようにPythonではクラスを入れ子にすることができる。ちなみにPHPではできない。

class Hoge:
    class Hoge1:
        def __init__(self):
            print 'hoge1'
    class Hoge2:
        def __init__(self):
            print 'hoge2'

hoge  = Hoge()
hoge1 = hoge.Hoge1()# hoge1
hoge2 = hoge.Hoge2()#hoge2

最近心変わりがあって行末にセミコロンを打つのをやめた。(o→ܫ←o)

numpyをインストールする

■環境

Cent OS 5.5 x86_64

前準備

以下のコマンドを実行し、python-develをインストールしておく。

yum install python-devel

■コマンド

以下のコマンドでnumpyがインストールされる。

wget http://sourceforge.net/projects/numpy/files/NumPy/1.5.0/numpy-1.5.0.tar.gz/download
tar xvzf numpy-1.5.0.tar.gz
cd numpy-1.5.0
python setup.py build
python setup.py install

Pythonのリストを触ってみる

list = ['hoge', 'huga', 'baka']
list[0]
#hoge

スライスもできる★

list[0:2]
#['hoge', 'huga']

リストの長さは以下のようにして取得できる。

len(list)
#3

for文を使って以下のように処理できる。

for i in list:
    print i, len(i)
#hoge 4
#huga 4
#baka 4

Pythonの文字列

Pythonでは以下のように文字列を切り出す事ができる。

str = "prepost"
str[:3]#'pre'
str[3:]#'post'
str[:-4]#'pre'
str[-4:]#'post'
str[2:4]#'ep'

C 言語の文字列と違い、Python の文字列は変更できない。JavaScriptと同じだ。

■文字列の結合

文字列は以下のように+演算子で結合する事ができる。

'str' + 'ing'
#'string'

文字列リテラルの場合は以下のように演算子を書かなくても連結できる。

'str' 'ing'
#'string'

しかし以下のようにするとエラーになる。

'str'.strip() 'ing'