Pythonでもっと遊んでもう少し学んだので、前回の続きとして書きます。
関係ないですけど、Python使いのことはPythonistaって言うんですね。
めざせPythonista!!
配列系
要素アクセス
普通の
items = ["A", "B", "C", "D", "E"]
item = items[1] # インデックス1の要素を取得
print(item) # B
最近学んだ
items = ["A", "B", "C", "D", "E"]
item = items[-1] # 最後のの要素を取得
# item = items[len(items) - 1] # こんなことしなくてもいい
print(item) # E
-2を指定したら後ろから2番目"D"が取れる
配列コピー
前回も書いたけどこんな感じ。
items = ["A", "B", "C", "D", "E"]
items2 = items[1:3] # index 1から2を抽出したlist生成
print(items2) # ['B', 'C']
items3 = items[1:] # index 1から後ろ全部を抽出したlist生成
print(items3) # ['B', 'C', 'D', 'E']
items4 = items[:3] # index 3からより前全部を抽出したlist生成
print(items4) # ['A', 'B', 'C']
さらに、飛び飛びでとることもできる。
items = ["A", "B", "C", "D", "E", "F", "G"]
items6 = items[::2] # 1つ飛ばしで抽出したlist生成
print(items6) # ['A', 'C', 'E', 'G']
items7 = items[::-1] # 逆順のlist生成
print(items7) # ['G', 'F', 'E', 'D', 'C', 'B', 'A']
items8 = items[-1:3:-1] # 逆順でindex範囲を指定するなら開始を後ろにする。(逆にすると要素が取れない)
print(items8) # ['G', 'F', 'E']
for文
当然だが[::]
を使って配列のループが色々できる
items = ["A", "B", "C", "D", "E", "F", "G"]
for item in items[1:]:
print(item) # B,C,D,E,F,Gを順番にprint
print("---")
for item in items[::-1]:
print(item) # G,F,E,D,C,B,Aを順番にprint
print("---")
for item in items[::3]:
print(item) # A,D,Gを順番にprint
for文でindexもとる
やり方があった。
items = ["A", "B", "C", "D", "E"]
for i, value in enumerate(items):
print(str(i) + ":"+ value)
結果
0:A
1:B
2:C
3:D
4:E
リストの内包表記
(for文とは別物かも)
http://docs.python.jp/3.5/tutorial/datastructures.html#list-comprehensions
配列の中身を操作して別の配列を作りたいとき
items = ["a", "B", "c", "D", "e"]
# 大文字にしたlistを作る
items2 = []
for item in items:
items2.append(item.upper())
print(items2) # ['A', 'B', 'C', 'D', 'E']
て書きそうなところ、items2を作るループの処理は、下記のように書ける。
items2 = [item.upper() for item in items]
ちなみにmapを利用すると、下記のように書ける。
items2 = list(map(str.upper, items))
さらに、
items = ["a", "B", "c", "D", "e"]
# 大文字だけのlistを作る
items2 = []
for item in items:
if item.upper() == item:
items2.append(item)
print(items2) # ['B', 'D']
て書きそうなところ、items2を作るループの処理は、下記のように書ける。
items2 = [item for item in items if item.upper() == item]
結合
個人的に結構感動するPythonの配列結合
なんと+
演算子だけでできた。
item1 = ["A", "B", "C"]
item2 = ["D", "E"]
item3 = item1 + item2
print(item3) # ['A', 'B', 'C', 'D', 'E']
(extendと違って別のlistが作られる)
予想できるが当然、加算代入も可能
item1 = ["A", "B", "C"]
item2 = ["D", "E"]
item1 += item2
# item1.extend(item2)と結果は同じ
print(item1) # ['A', 'B', 'C', 'D', 'E']
そして個人的に全く理解できないのがある。
item1 = ["A", "B", "C"]
item2 = ["D", "E"]
item1[:0] = item2
print(item1) # ['D', 'E', 'A', 'B', 'C']
上記のように書くと頭に結合できる。
慣れない僕はさすがに理解できないので当分は、
item1 = item2 + item1
と書くと思う。
文字列操作
join
(前回書いておくべきだった内容かも)
s = ":".join(["A", "B", "C", "D", "E"])
print(s) # "A:B:C:D:E"
繰り返し
これも個人的に結構感動してる方法。
なんと*
演算子だけでできた。(これ知るまでループ書いてた)
s = "あ" * 5
print(s) # あああああ
lambda式
こう書く。lambda式の書き方自体は、今となってはJavaとあまり変わらない。
func = lambda x: x.upper()
print(func("a")) # A
条件文
in
配列に含まれるかどうかを判定(したり)する。(dictだとまた動作が違う)
orで繋がなくていい便利なやつ。
http://docs.python.jp/3.5/reference/expressions.html#membership-test-operations
帰属検査演算という名前らしい。
SQLのINみたいな?神殿マークの言語でもできたなぁという個人的思い出。
if 2 in [1, 2, 3]: # True
print("2がある")
if 4 not in [1, 2, 3]: # True
print("4はない")
yield
http://docs.python.jp/3.5/reference/expressions.html#yieldexpr
http://docs.python.jp/3.5/reference/simple_stmts.html#the-yield-statement
yieldが何なのかの説明はできないので下記を参考
https://ja.wikipedia.org/wiki/ジェネレータ_(プログラミング)
JavaでいうIteratorを、簡単に作る仕組みと勝手に理解した。
def yield_sample():
for i in [1, 2, 3]:
yield i
gen = yield_sample()
print(next(gen)) # 1
print(next(gen)) # 2
print(next(gen)) # 3
print(next(gen)) # StopIteration
for i in yield_sample(): # for文で回せる
print(i) # 1、2、3を順番に出力
次がyieldの面白いところ
def yield_sample2():
print("つぎは1")
yield 1
print("つぎは2")
yield 2
print("つぎは3")
yield 3
print("つぎはない")
for i in yield_sample2():
print(i) # 1、2、3を順番に出力するが、、、
結果はこう
つぎは1
1
つぎは2
2
つぎは3
3
つぎはない
yieldで作成したジェネレータをlistにしたい場合はこう
def yield_sample():
for i in [1, 2, 3]:
yield i
l = list(yield_sample())
print(l) # [1, 2, 3]
ファイル操作系
ググったほうが早いかも。いくつかやり方がある印象を受けた。
どの方法が最も良いのかまではわからない。
ファイル操作系全部は書かないけど、自分が使ったものだけ書いておく。
読み込み
f = codecs.open(path, "r", "utf-8")
ret = f.read()
f.close()
書き込み
f = codecs.open(path,"w", "utf-8")
f.write(value)
f.close()
ファイル存在
if os.path.exists(path):
フォルダ掘る
os.makedirs(dirPath)
親フォルダ名取得
os.path.dirname(path)
ディレクトリからファイルのリストアップ
for root, _, files in os.walk(dirPath):
for fileName in files:
path = os.path.join(root, fileName)
yield path
例外処理
except
Javaでいうcatchブロック
def error_throw():
"" + 1
try:
error_throw()
print("ここにはこない")
except: # すべてのエラーでここに来る
print("エラー")
catch的なやつ
try:
error_throw()
print("ここにはこない")
except Exception as e: # エラーObjectを取得
print(type(e))
print(e)
結果
<class 'TypeError'>
Can't convert 'int' object to str implicitly
Exceptionの型別にもかける
try:
error_throw()
print("ここにはこない")
except ValueError:
print("ValueErrorは発生しないのでここにはこない")
except TypeError:
print("TypeErrorが発生するのでここにくる")
trace
Javaでいうstacktraceてきなやつ
import traceback
try:
error_throw()
except :
print(traceback.format_exc())
クロージャ
できない。ざんねん。Javaと似たイメージでできない。
def new_counter():
count = 0
def func():
count += 1
return count
return func
c = new_counter()
print(c())
print(c())
print(c())
エラー
UnboundLocalError: local variable 'count' referenced before assignment
下記のように書けばそれっぽいことができる。。。(Javaみたい)
def new_counter():
count = [0]
def func():
count[0] += 1
return count[0]
return func
c = new_counter()
print(c())
print(c())
print(c())
テスト
作成
Eclipseから「新規」→「Pydevモジュール」→名前を付けて「完了」→
「モジュール:Unittest」を選択して「OK」で出来たものをみればなんとなく書き方がわかると思う。
実行
「実行」→「Pythonユニットテスト」で実行できる。
サンプル
import unittest
class Test(unittest.TestCase):
def testName(self):
self.assertEqual(1, 2, "サンプル")
if __name__ == "__main__":
#import sys;sys.argv = ['', 'Test.testName']
unittest.main()
結果
F
======================================================================
FAIL: testName (__main__.Test)
----------------------------------------------------------------------
Traceback (most recent call last):
File "C:\hogehoge\testsample.py", line 13, in testName
self.assertEqual(1, 2, "サンプル")
AssertionError: 1 != 2 : サンプル
----------------------------------------------------------------------
Ran 1 test in 0.016s
FAILED (failures=1)
テストの動的追加
下記を参考にしました。
http://hirokazumiyaji.hatenablog.com/entry/2015/07/16/134238
下記サンプルはディレクトリにあるファイル分のテストを登録するサンプルです。
import unittest
import os
class Test(unittest.TestCase):
# 空のテストクラス
pass
def setup_testsuite():
"""
ディレクトリのファイルをリストアップしてテストを登録
"""
root = os.getcwd()
test_files_dir = os.path.join(root, "files") # このpyファイルの隣にあるfilesフォルダの中のファイルをターゲットにする
def listup():
for root, _, files in os.walk(test_files_dir):
for file_name in files:
if os.path.splitext(file_name)[1].lower() == ".txt":# 拡張子で絞り込み
yield file_name, os.path.join(root, file_name)
for file_name, path in listup():
def create_test_func(file_name, path):
def test_func(self):
"""
テストの実態
"""
print("test start: " + file_name)
# selfはTestなのでassertEqualは下記のように呼ぶ
# self.assertEqual(first, second, msg)
return test_func
test_name = "test_{}".format(file_name)
setattr(Test, test_name, create_test_func(file_name, path)) #登録
# テストの登録を実行
setup_testsuite()
if __name__ == "__main__":
# import sys;sys.argv = ['', 'Test.testName']
unittest.main()