- 追加された行はこの色です。
- 削除された行はこの色です。
#contents
** Pythonを使ってみよう [#peb4c9dd]
- 概要
-- シンプルで習得がしやすいオブジェクト指向言語
-- データ解析、機械学習
- 公式サイト
-- https://www.python.org/
- 環境
-- Vagrant ローカル開発環境 (CentOS 6.7)
** Python 3 インストール [#j4dacc82]
- CentOS 6 標準では Python 2 がインストールされているため pyenv を利用して Python 3 をインストール
- epel リポジトリをダウンロード
$ wget https://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
- epel リポジトリをインストール
$ sudo rpm -Uvh epel-release-6-8.noarch.rpm
- Ansible インストール
$ sudo yum -y install ansible
$ ansible --version
ansible 2.3.0.0
- git, patch をインストール
$ sudo yum -y install git
$ sudo yum install patch
- Playbook 作成
$ vi playbook.yml
---
- hosts: localhost
connection: local
sudo: yes
vars:
- python_version: 3.5.2
tasks:
- name: disable iptables
service: name=iptables state=stopped enabled=no
- name: install libselinux-python
yum: name=libselinux-python state=latest
- name: remove localtime
file: path=/etc/localtime state=absent
- name: change timezone
file: src=/usr/share/zoneinfo/Asia/Tokyo dest=/etc/localtime state=link force=yes mode=0644
- name: change locale
lineinfile: >-
dest=/etc/sysconfig/i18n
state=present
regexp=^LANG=
line='LANG="ja_JP.UTF-8"'
- name: install dependencies
yum: name={{item}} state=present
with_items:
- gcc
- openssl
- openssl-devel
- rpm-build
- gcc-c++
- bzip2
- bzip2-devel
- libtool
- zlib
- zlib-devel
- httpd-devel
- openssl-devel
- curl-devel
- ncurses-devel
- gdbm-devel
- readline
- readline-devel
- sqlite
- sqlite-devel
- libyaml-devel
- libffi-devel
- bison
- name: check pyenv installed
command: test -x /home/vagrant/.pyenv
register: pyenv_present
ignore_errors: yes
become: no
- name: git clone pyenv
git: repo=https://github.com/yyuu/pyenv.git dest=/home/vagrant/.pyenv
when: pyenv_present.rc != 0
become: no
- name: check pyvirtual installed
command: test -x /home/vagrant/.pyenv/plugins/pyenv-virtualenv
register: pyvirtual_present
ignore_errors: yes
become: no
- name: git clone pyenv-virtual
git: repo=https://github.com/yyuu/pyenv-virtualenv.git dest=/home/vagrant/.pyenv/plugins/pyenv-virtualenv
when: pyvirtual_present != 0
become: no
- name: update pyenv
command: git pull --rebase chdir=/home/vagrant/.pyenv
become: no
- name: update pyenv-virtualenv
command: git pull --rebase chdir=/home/vagrant/.pyenv/plugins/pyenv-virtualenv
become: no
- name: check python installed
shell: /bin/bash -lc "pyenv versions | grep {{python_version}}"
register: python_installed
ignore_errors: yes
become: no
- name: install python
shell: /bin/bash -lc "pyenv install {{python_version}} && pyenv rehash && pyenv global {{python_version}}"
when: python_installed.rc != 0
become: no
- Playbook 実行
$ ansible-playbook playbook.yml
- &color(red){※}; エラーとなるため下記を手動で実施 (to be automated)
$ vi .bashrc
export PYENV_ROOT="${HOME}/.pyenv"
if [ -d "${PYENV_ROOT}" ]; then
export PATH=${PYENV_ROOT}/bin:$PATH
eval "$(pyenv init -)"
fi
$ source ~/.bashrc
- Playbook 再実行
$ ansible-playbook playbook.yml
- Python バージョン確認
$ python -V
Python 3.5.2
- 作業ディレクトリ
$ pwd
/home/vagrant/python3_lessons
** はじめてのPythonプログラム [#x1a702dc]
- インタラクティブモード
$ python
Python 3.5.2 (default, May 20 2017, 02:46:30)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-18)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> 3 + 2
5
>>> exit()
- スクリプト作成 (myapp.py)
# coding: utf-8
print("Hello World")
- 実行結果
$ python myapp.py
Hello World
- コメント
# coding: utf-8
"""
Comment
Comment
Comment
"""
# Comment
print("Hello World")
- Python 2 と Python 3 の違い
-- Python 2 では print に括弧は不要だが Python 3 では必須
-- Python 2 では日本語コメントを記載する場合に # coding: utf-8 を明記したが Python 3 では必須ではない
** 定数について [#s903f012]
- 値を再代入できない
- Python では言語仕様として定数はサポートされていない
- 変数名を全て大文字にすると慣習的に定数とみなすことが多いので値の変更は避ける
ADMIN_EMAIL = "yuji@example.com"
** データの演算について [#z883940a]
- 変数に他の変数を代入
y = 4
# y = y + 12
y += 12
print(y) # 16
- 論理計算
print(True and False) # False
print(True or False) # True
print(not True) # False
** 文字列に値を埋め込んでみよう [#sadcc680]
- % を利用した記法
name = "yuji"
score = 52.8
print("name: %s, score: %f" % (name, score))
- 実行結果
$ python myapp.py
name: yuji, score: 52.800000
- % を利用した記法 (桁数指定、行揃い指定)
name = "yuji"
score = 52.8
print("name: %-10s, score: %10.2f" % (name, score))
- 実行結果
$ python myapp.py
name: yuji , score: 52.80
- {} を利用した記法
name = "yuji"
score = 52.8
print("name: {0}, score: {1}".format(name, score))
- 実行結果
$ python myapp.py
name: yuji, score: 52.8
- {} を利用した記法 (桁数指定、行揃い指定)
name = "yuji"
score = 52.8
print("name: {0:>10s}, score: {1:<10.2f}".format(name, score))
- 実行結果
$ python myapp.py
name: yuji, score: 52.80
** ifで条件分岐をしてみよう [#p91e87f8]
- ユーザーからの入力を受け付けて if 文で条件分岐 &color(red){※}; ユーザー入力は文字列が返るので数値に変換が必要
score = int(input("score ? "))
if score > 80:
print("Great!")
elif score > 60:
print("Good!")
else:
print("so so ...")
- 実行結果
$ python myapp.py
score ? 90
Great!
- 条件演算子を使った記法 (if else)
score = int(input("score ? "))
print("Great!" if score > 80 else "so so ...")
- &color(red){※}; Python ではインデントに半角スペース4つを利用
** 関数の返り値を使ってみよう [#qa75b13b]
- 返り値を指定した関数
def say_hi():
return "hi"
print("hello") # return 後の記述のため処理されない
msg = say_hi()
print(msg)
- 実行結果
$ python myapp.py
hi
- pass の利用 &color(red){※}; 返り値は None という特殊な値
def say_hi():
pass
msg = say_hi()
print(msg)
- 実行結果
$ python myapp.py
None
** 変数のスコープを理解しよう [#ka60680e]
- ローカル変数: 関数内で定義された変数
- グローバル変数: 関数の外で定義された変数
-- 関数内から参照は可能だが書き換えは不可
- 関数内でグローバル変数を書き換える方法 (明示的にグローバル変数を定義)
msg = "hello" # グローバル変数
def say_hi():
global msg
msg = "hello global"
print(msg)
say_hi()
print(msg)
** クラス変数を使ってみよう [#v2f54ead]
class User:
# クラス変数
count = 0
def __init__(self, name):
User.count += 1
self.name = name
print(User.count) # 0
tom = User("tom")
bob = User("bob")
print(User.count) # 2
print(tom.count) # 2
- 実行結果
$ python myapp.py
0
2
2
** メソッドを使ってみよう [#cbef8a74]
- メソッド: クラスに定義した関数
- コンストラクタもメソッドの一つ
- インスタンスメソッドとクラスメソッド
class User:
count = 0
def __init__(self, name):
User.count += 1
self.name = name
# インスタンスメソッド
def say_hi(self):
print("hi {0}".format(self.name))
# クラスメソッド
@classmethod
def show_info(cls):
print("{0} instances".format(cls.count))
tom = User("tom")
bob = User("bob")
tom.say_hi()
bob.say_hi()
User.show_info()
- 実行結果
$ python myapp.py
hi tom
hi bob
2 instances
** アクセス制限をしてみよう [#x4a6b95e]
- Python では public や private 等のアクセス修飾子はなく慣習的な記法が存在する
- クラス外からアクセスを禁止したい場合には慣習的に変数名の先頭にアンダースコア「_」を付ける
class User:
def __init__(self, name):
self._name = name
def say_hi(self):
print("hi {0}".format(self._name))
tom = User("tom")
print(tom._name)
tom.say_hi()
- 実行結果
$ python myapp.py
tom
hi tom
- 更に厳密に制限したい場合には変数名の先頭にアンダースコアを2つ「__」付ける
class User:
def __init__(self, name):
self.__name = name
def say_hi(self):
print("hi {0}".format(self.__name))
tom = User("tom")
print(tom._name)
# print(tom._User__name) # 左記だとアクセス可能という抜け道あり
tom.say_hi()
- 実行結果
$ python myapp.py
Traceback (most recent call last):
File "myapp.py", line 18, in <module>
print(tom._name)
AttributeError: 'User' object has no attribute '_name'
** クラスを継承してみよう [#k0c88893]
- クラスの継承 (User -> AdminUser)
class User:
def __init__(self, name):
self.name = name
def say_hi(self):
print("hi {0}".format(self.name))
class AdminUser(User):
def __init__(self, name, age):
super().__init__(name)
self.age = age
def say_hello(self):
print("hello {0} ({1})".format(self.name, self.age))
bob = AdminUser("bob", 23)
print(bob.name)
bob.say_hi()
bob.say_hello()
- 実行結果
$ python myapp.py
bob
hi bob
hello bob (23)
- クラスの継承 (オーバーライド)
class User:
def __init__(self, name):
self.name = name
def say_hi(self):
print("hi {0}".format(self.name))
class AdminUser(User):
def __init__(self, name, age):
super().__init__(name)
self.age = age
def say_hello(self):
print("hello {0} ({1})".format(self.name, self.age))
# override
def say_hi(self):
print("[admin] hi {0}".format(self.name))
bob = AdminUser("bob", 23)
print(bob.name)
bob.say_hi()
bob.say_hello()
- 実行結果
$ python myapp.py
bob
[admin] hi bob
hello bob (23)
** クラスの多重継承をしてみよう [#p48508e6]
- Python では親クラスを複数持つことが可能
- Class A, B を継承した Class C を作成
class A:
def say_a(self):
print("A!")
class B:
def say_b(self):
print("B!")
class C(A, B):
pass
c = C()
c.say_a()
c.say_b()
- 実行結果
$ python myapp.py
A!
B!
- 親クラスに同名のメソッドが存在する場合は先に継承した親クラスのメソッドが実行される
class A:
def say_a(self):
print("A!")
def say_hi(self):
print("hi! from A!")
class B:
def say_b(self):
print("B!")
def say_hi(self):
print("hi! from B!")
class C(B, A):
pass
c = C()
c.say_hi()
- 実行結果
$ python myapp.py
hi! from B!
** モジュールでファイル分割してみよう [#y599f84d]
- モジュール: ファイルを分割するための仕組み
- user.py を作成し User 関連のコードを分割
class User:
def __init__(self, name):
self.name = name
def say_hi(self):
print("hi {0}".format(self.name))
class AdminUser(User):
def __init__(self, name, age):
super().__init__(name)
self.age = age
def say_hello(self):
print("hello {0} ({1})".format(self.name, self.age))
def say_hi(self):
print("[admin] hi {0}".format(self.name))
print("hello")
- myapp.py にて user.py をインポート &color(red){※}; import で読み込んだ瞬間に user.py が実行されるので注意
import user
bob = user.AdminUser("bob", 23)
print(bob.name)
bob.say_hi()
bob.say_hello()
- 実行結果
$ python myapp.py
hello
bob
[admin] hi bob
hello bob (23)
- モジュールから指定したクラスや関数のみを import することも可能
- myapp.py (AdminUser, User クラスを個別にインポート)
from user import AdminUser, User
bob = AdminUser("bob", 23)
tom = User("tom")
print(bob.name)
bob.say_hi()
bob.say_hello()
- user.py
class User:
def __init__(self, name):
self.name = name
def say_hi(self):
print("hi {0}".format(self.name))
class AdminUser(User):
def __init__(self, name, age):
super().__init__(name)
self.age = age
def say_hello(self):
print("hello {0} ({1})".format(self.name, self.age))
def say_hi(self):
print("[admin] hi {0}".format(self.name))
# print("hello")
- 実行結果
$ python myapp.py
bob
[admin] hi bob
hello bob (23)
** パッケージでモジュールを管理しよう [#p7a80104]
- パッケージ: モジュールをフォルダにまとめたもの
- パッケージを Python で認識させるにはフォルダの中に特殊なファイル "__init__.py" が必要
- ディレクトリ構造 (mypackage 配下に user.py を移動)
/home/vagrant/python3_lessons
|--myapp.py
|--mypackage
| |--__init__.py
| |--user.py
- myapp.py
import mypackage.user
bob = mypackage.user.AdminUser("bob", 23)
print(bob.name)
bob.say_hi()
bob.say_hello()
- 実行結果
$ python myapp.py
bob
[admin] hi bob
hello bob (23)
- myapp.py (パッケージ名に別名を付ける)
import mypackage.user as mymodule
bob = mymodule.AdminUser("bob", 23)
print(bob.name)
bob.say_hi()
bob.say_hello()
- myapp.py (AdminUser のみインポート)
from mypackage.user import AdminUser
bob = AdminUser("bob", 23)
print(bob.name)
bob.say_hi()
bob.say_hello()