default eye-catch image.

Dictionary

Dictionaryの基本 いわゆるKey-Valueのことを\"Mapping\"と呼ぶ。 PythonのDictionaryはハッシュで実現されている。 キーにはハッシュ可能オブジェクトを指定可能。ハッシュ可能=更新不可、という意味ではない。 例えばオブジェクトのインスタンスのように中身が変わっても枠が変わらなければOK。 rgbs = { (255,0,0): \'red\', (0,255,0): \'green\', (0,0,255): \'blue\' キーは重複不可。同じキーを登録すると前のKeyValueが上書きされる。 kv = { \'hoge\': 100, \'fuga\': 200 } print(kv) # {\'hoge\': 100, \'fuga\': 200} kv[\'hoge\'] = 300 print(kv) # {\'hoge\': 300, \'fuga\': 200} DictionaryのCRUD d = {\'hoge\':100,\'fuga\':200} # Create print(d[\'hoge\']) # Read d[\'hoge\'] = 300 # Update del d[\'hoge\'] # Delete d2 = dict([(1,\'hoge\'),(2,\'fuga\')]) print(d2) # {1: \'hoge\', 2: \'fuga\'} d3 = dict(hoge1=\'hoge1\',hoge2=\'hoge2\',hoge3=\'hoge3\') print(d3) # {\'hoge1\': \'hoge1\', \'hoge2\': \'hoge2\', \'hoge3\': \'hoge3\'} 辞書内包 List,Tupleと同様に内包式を書ける。 s = [\"Hoge1\",\"Hoge2\",\"Hoge3\"] k1 = {} for v in s: k1[v] = v.lower() k2 ={v.lower() for v in s} Operator Dictionaryに対する演算。 d = {\"hoge\":100} print(\'hoge\' in d) # True print(\'fuga\' not in d) # True print(len(d)) # 1 iteration中に別のkeyへのアクセスは不可 こういうことは避けるべきだけれども、実際にやるとRuntimeエラー。 d = {\'hoge1\':100,\'hoge2\':200,\'hoge3\':300} for key in d: d[\'hoge4\'] = 500 # RuntimeError: dictionary changed size during iteration ViewObject キーの集合、値の集合を参照するためのデータ構造。 Viewというからには、Dictionary内に含まれる実体を参照している。 ViewObjectは集合演算をサポートしている。 d = {\'hoge1\':100,\'hoge2\':200,\'hoge3\':300} view1 = d.keys() for key in view1: print(key) # hoge1 hoge2 hoge3 del d[\'hoge2\'] for key in view1: print(key) # hoge1 hoge3 view_x = view1 - [\'hoge1\',\'hoge2\'] print(view_x) # {\'hoge3\'} view2 = d.values() for value in view2: print(value) # 100 200 300

default eye-catch image.

String

Stringの基本 他の型をStringに変換する。 a = 100 b = 3.14 c = str(a) + \'/\' + str(b) print(c) # 100/3.14 スライスで参照できる。 a = \"hogehoge\" print(a[3:5]) # eh Stringのmethod達 Stringは更新不能。method達は自分自身を破壊しない。 戻り値として新しいStringオブジェクトが戻るのみ。 大文字小文字,数値アルファベットの判定はUnicode標準に従う。 # coding: utf-8 # Your code here! print(\"Hogehoge\".capitalize()) # Hogehoge print(\"AiUeO\".casefold()) # aiueo print(\"hoge\".center(10,\'-\')) # ---hoge--- print(\"hogehoge\".count(\'h\')) # 2 print(\"hogehoge\".encode()) # b\'hogehoge\' print(\"hogehoge\".endswith(\'hoge\')) # True print(\"hoge\".find(\"ge\")) # 2 print(\"{0} is {1}\".format(\"hoge\",\"fuga\")) # hoge is fuga print(\"hogehoge\".index(\"geh\")) print(\"hoge\".isalnum()) # True print(\"1234\".isalnum()) # True print(\"()\".isalnum()) # False print(\"hoge\".isalpha()) # True print(\"1234\".isalpha()) # False print(\"1234\".isdecimal()) # True print(\"12ab\".isdecimal()) # False print(\"hoge\".isidentifier()) # True print(\"3ab\".isidentifier()) # Flase print(\"Hoge\".islower()) # False print(\"hoge\".islower()) # True print(\"1234\".isnumeric()) # True print(\"12ab\".isnumeric()) # False print(\"t\".isprintable()) # False print(\"hoge \".isspace()) # False print(\" \".isspace()) # True print(\"hoge\".istitle()) # False print(\"This Is My Hoge\".istitle()) # True print(\"--\".join([\'1\',\'2\',\'3\',\'4\'])) # 1--2--3--4 print(\"\".join([\'spam\',\'ham\',\'egg\'])) # spamhamegg print(\"hoge\".ljust(10,\'*\')) # hoge****** print(\"This is hoge\".lower()) # this is hoge print(\" hoge \".lstrip()) # hoge print(\"hoge1 hoge2 hoge3\".replace(\"hoge1\",\"fuga1\")) # fuga1 hoge2 hoge3 print(\"12345678\".rfind(\'6\')) # 5 print(\"12345678\".rindex(\'6\')) # 5 print(\"hoge\".rjust(10,\'*\')) # ******hoge print(\"hoge/fuga\".rpartition(\'/\')) # (\'hoge\', \'/\', \'fuga\') print(\"hoge*fuga\".rpartition(\'/\')) # (\'\', \'\', \'hoge*fuga\') print(\"hoge fuga hoge\".rsplit()) # [\'hoge\', \'fuga\', \'hoge\'] print(\"hoge \".rstrip()) # hoge print(\"hoget\".rstrip()) # hoge print(\"hoge hoge hoge\".split()) # [\'hoge\', \'hoge\', \'hoge\'] print(\"hoge1rhoge2nhoge3rn\".splitlines()) # [\'hoge1\', \'hoge2\', \'hoge3\'] print(\"hoge1rhoge2nhoge3rn\".splitlines(keepends=True)) # [\'hoge1r\', \'hoge2n\', \'hoge3rn\'] print(\"aiueokakikukeko\".startswith(\"aiueo\")) # True print(\" hoge \".strip()) # hoge print(\"AiUeO\".swapcase()) # aIuEo print(\"hoge hoge hoge\".title()) # Hoge Hoge Hoge print(\"hogehgoehgoe\".upper()) # HOGEHGOEHGOE print(\"hoge\".zfill(10)) # 000000hoge print(\"-foo\".zfill(10)) # -000000foo

default eye-catch image.

Collection…Sequence,Slice,List,Tupple

Sequence,Slice 初めてPythonを触ると地味に取っつきにくい構文が現れるけども。 序数によるアクセスの他、範囲を指定してリストを得られる。 負の序数を指定すると後ろから数える。負のスライスも可 スライスの開始位置、終了位置はSequenceの前の方->後の方の順に書く。 長さがゼロ、またはマイナスの場合、空のリストを返す。 L = [0,1,2,3,4] a = L[1:3] print(a) # [1,2] b = L[-1:-3] print(b) # [2,3] k = K[3:1] print(k) # [] 増分値を指定することもできる。 L = [0,1,2,3,4] c = L[0:5:2] print(c) # [0,2] スライス自体もオブジェクト L = [0,1,2,3,4] s = slice(0,3) d = L[s] print(d) # [0,1,2] s2 = slice(0,None,1) print(L[s2]) # [0,1,2,3,4] スライスを構成する3要素は省略できる。 増分値に負を与えると逆順になるのを利用して要素を反転できる。 L = [0,1,2,3,4] print(L[::]) # = L[0:4:1] = [0,1,2,3,4] print(L[:]) # = L[0:4:1] = [0,1,2,3,4] print(L[::2]) # = L[0:4:2] = [0,2] print(L[::-1]) # = [4,3,2,1,0] スライスを指定して代入できる。 L = [0,1,2,3,4] L[1,4] = [\'hoge\',\'fuga\'] print(L) # [0,\'hoge\',\'fuga\',4] スライスを指定して削除できる。リストから削除するだけで要素自体を破棄しない。 L = [0,1,2,3,4] del L[0,2] print(L) # [3,4] 算術演算子、比較演算子、メンバーシップ演算子が用意されている。 Q = [1,2] * 3 print(Q) # [1,2,1,2,1,2] R1 = [1,2] R2 = [3,4] RX = R1 < R2 print(RX) # True P = [0,1,2,3,4] PX = 7 in P print(PX) # False PXX = 15 not in P print(PXX) # True Sequenceの長さはlen()で取得。 L = [0,1,2,3,4] print(len(L)) # 5 List リストの基本的な使い方は以下。 L1 = [0,1,2,3,4,5] L2 = [] for E in L1: L2.append(E) print(L2) # [0,1,2,3,4,5] 上記は以下のように1回で書ける。リスト内包とか言うらしい。 L1 = [0,1,2,3,4,5] L2 = [value for value in L1] print(L2) # [0,1,2,3,4,5] リスト内包には条件をつけられる。例えば偶数だけを集めるのは以下。 L1 = [0,1,2,3,4,5] L2 = [value for value in L1 if value % 2 == 0] # [0,2,4] iteratableを分解できる。 L = [(\'a\',1),(\'b\',2),(\'c\',3)] L1 = [c*i for c,i in L] print(L1) # [\'a\', \'bb\', \'ccc\'] iteratableの分解時に要素をリストで受けられる。 以下、タプルの第2要素以降をリストで受けて総和を求めて第1要素に掛けている。 L = [(1,2),(3,4,5),(6,7,8,9)] L1 = [car*sum(cdr) for car,*cdr in L] print(L1) # [2, 27, 144] リスト内包を入れ子にすることもできる。 years = [2013,2014] months = [1,2,3,4,5,6,7,8,9,10,11,12] dest1 = [] for year in years: for month in months: dest1.append((year,month)) print(dest1) dest2 = [(year,month) for year in years for month in months] print(dest2) Listオブジェクトの代表的なメソッド達。 L1 = [0,1,2,3,4] L1.append(5) print(L1) # [0,1,2,3,4,5] L2 = L1.copy() print(id(L1)) # 140415098962824 print(id(L2)) # 140415098984840 L2.clear() print(L2) # [] print(L1.count(2)) # 1 L3 = [\'a\',\'b\',\'c\'] L1.extend(L3) print(L1) # [0, 1, 2, 3, 4, 5, \'a\', \'b\', \'c\'] L4 = L1.index(0) print(L4) # 0 L1.insert(4,\'hoge\') print(L1) # [0, 1, 2, 3, \'hoge\', 4, 5, \'a\', \'b\', \'c\'] p = L1.pop(3) print(p) # 3 print(L1) # [0, 1, 2, \'hoge\', 4, 5, \'a\', \'b\', \'c\'] L1.remove(4) print(L1) # [0, 1, 2, \'hoge\', 5, \'a\', \'b\', \'c\'] L1.reverse() print(L1) # [\'c\', \'b\', \'a\', 5, \'hoge\', 2, 1, 0] Tuple 更新不能なリスト。要素を列挙するだけでTupleを作れる。更新できない以外はListと変わらない感じ。 \"更新できない\"という特徴があるため、辞書のキーとして使うことができる。 リストは要素としてそれぞれ独立した値が設定されることを想定。 タプルは全体で1つの要素になることを想定。タプルは「複数の要素から構成される値」。 \"更新できない\"という特徴は、メモリ割り当て時に動的確保を想定しなくて良いため、 リストよりもタプルの方がメモリ使用量を削減できるし、GCの負荷軽減に寄与する。 t1 = (1,2,3) print(t1) # (1,2,3) t2 = 3,4,5 print(t2) # (3, 4, 5) t3 = 1, print(t3) # (1,)

default eye-catch image.

Reference,unpack,同時代入,変数の削除,3項演算子

Reference 変数はオブジェクトの参照。ということなので、オブジェクトのidを確認してみる。 hoge = [1,2,3,4] fuga = hoge print(hoge) # [1,2,3,4] print(fuga) # [1,2,3,4] print(id(hoge)) # 4359573320 print(id(fuga)) # 4359573320 hoge.append(5) print(hoge) # [1,2,3,4,5] print(fuga) # [1,2,3,4,5] 代入したときにどうなるか。新しい箱が作られてそちらを指すようになる。 foo = 1 bar = foo print(foo) # 1 print(bar) # 1 print(id(foo)) # 4359573320 print(id(bar)) # 4359573320 foo = 2 print(foo) # 2 print(bar) # 1 print(id(foo)) # 4476302432 print(id(bar)) # 4359573320 Unpack,同時代入 代入の右辺にiterableを置き、左辺に複数の変数を置くと、 左辺の各変数にiterableの各要素が代入される。 数が合わないとエラー。 foo = [1,2,3,4,5] a1,a2,a3,a4,a5 = foo print(a1) # 1 print(a2) # 2 print(a3) # 3 print(a4) # 4 print(a5) # 5 左辺にリストを置けるが、Unpackの評価においてリストも分解される。 c1,[c2,c3],c4 = [1,[2,3],4] print(c1) # 1 print(c2) # 2 print(c3) # 3 print(c4) # 4 リストでなくても同時代入は可能。 d1,d2 = 100,200 print(d1) # 100 print(d2) # 200 左辺と右辺の個数が合わないケース。通常は下記の通りエラーになる。 ただし左辺に*があるとよしなにやってくれる。 bar = [1,2,3] b1,b2 = bar # ValueError: too many values to unpack (expected 2) e1,*e2 = bar print(e1) # 1 print(e2) # [2,3] *f1,f2 = bar print(f1) # [1,2] print(f2) # 3 オブジェクトの削除 オブジェクトは明示的に削除できる。 foobar = 1024 print(id(foobar)) # 4348092368 del(foobar) print(id(foobar)) # NameError: name \'foobar\' is not defined 3項演算子 ?ではなくif..elseで書く。 a if b else c の場合、bが真ならa,偽ならc。 片方だけ評価される(short circuit)。 a = 100 b = 200 y = True x = a if y else b z = a if not y else b print(x) # 100 print(z) # 200

default eye-catch image.

PythonでUpcast/Downcast出来ない件と多態性のサンプル

継承・カプセル化・多態性 オブジェクト指向の必須要素はこれ。継承、カプセル化・多態性。 異種リストを書けば全部試せるので試してみる。 多態性実現のためにオブジェクトのUpcast/Downcastを調べようとしたら存在しない!。 結論として、PythonにおいてはオブジェクトのUpcast/Downcastは出来ない。 動的型付けなんで、Upcastは勝手に上位クラスだと思って触れば良いのだけど、 形だけでも上位クラスにキャストしておいた方が可読性は上がると思うので残念。 abstractメソッドを定義するだけでパッケージを要求するとか切ない。 from abc import ABCMeta, abstractmethod # 抽象基底クラス class Base: __attr = 100 @abstractmethod def hoge(self): pass class Derived1(Base): __attr = 200 def hoge(self): print(self.__attr) class Derived2(Base): __attr = 300 def hoge(self): print(self.__attr) vals = [Derived1(), Derived2()] for val in vals: val.hoge() なお、Downcastについては、以下のようにしている例がある。 class SubDerived2(Derived1): __attr = 500 def hoge(self): print(self.__attr) def myfunc(self): print(\"myfunc is called\") derived = Derived2() derived.__class__ = SubDerived2 derived.myfunc() 確かに、Upcastは動的型付けの範囲内だが、実現可能でDowncastは何らかの指示が必要で、 必要な方にだけ手段が用意されているのは合理的な気もする。 関数 defで定義する。最初の行に書いた文字列リテラルはdocstring。PHPDoc的なやつだろうか。 関数のスコープからローカル->グローバル->ビルトインの順にシンボルを参照できる。 関数スコープから外のスコープのシンボルは書けない。(global指定して初めて書ける)。 フィボナッチ数列。 def fib(n): \"\"\"Print a Fibonacci series up to n.\"\"\" a,b = 0,1 while a < n: print(a,end=' ') a,b=b,a+b print() fib(100) # 0 1 1 2 3 5 8 13 21 34 55 89 キーワード引数も使える。 def myfunc(hoge,fuga=1): print(hoge) print(fuga)

default eye-catch image.

インデントとブロック,比較と、比較の連接,辞書オブジェクト,リストとタプル,if … elif … else,for,while,iteratableオブジェクト

他言語からの流入組が最小工数でPythonを学ぶシリーズです。 Python文法詳解を読みながらアウトプットしていきます。 [arst_toc tag=\"h4\"] いくら何でも公式を上から順番に読むのは時間がかかり過ぎるし、 550ページとかある本なんて読みたくないので、なるべく薄くて枠だけ書いてある本が良いなと。 Python文法詳解posted with amazlet at 19.05.25石本 敦夫 オライリージャパン 売り上げランキング: 432,601Amazon.co.jpで詳細を見る インデントとブロック ブロックはbeginや { などの予約語ではなく、インデントを使う。 公式は以下。 [clink implicit=\"false\" url=\"https://docs.python.org/2.0/ref/indentation.html\" imgurl=\"https://www.python.org/static/img/python-logo@2x.png\" title=\"2.1.7 Indentation\" excerpt=\"Leading whitespace (spaces and tabs) at the beginning of a logical line is used to compute the indentation level of the line, which in turn is used to determine the grouping of statements.\"] 公式に面白い例が載ってた。 見た目上、インデントが無茶苦茶だけれども文法的には合理性がある例。 要するにインデントとインデント解除のconsistencyがあればOK。 def perm(l): # Compute the list of all permutations of l if len(l) <= 1: return [l] r = [] for i in range(len(l)): s = l[:i] + l[i+1:] p = perm(s) for x in p: r.append(l[i:i+1] + x) return r コーデイング規約によると、お作法としてスペースの個数は4個。だそうだ。 タブではなくスペースでインデントするなんて信じられない...。 エディタにタブ=スペース4個の設定を追加しないと。 言語仕様上の制約はインデントのconsistencyだけなので、 実際のインデント数はプロジェクトによるとのこと。ほうほう。 ただ、スペースとタブの混在禁止はこの際ハッキリさせましょう、という流れ。 比較と、比較の連接 比較演算子について公式は以下。 [clink implicit=\"false\" url=\"https://docs.python.org/ja/3/library/stdtypes.html#comparisons\" imgurl=\"https://www.python.org/static/img/python-logo@2x.png\" title=\"2.1.7 Indentation\" title=\"比較\" excerpt=\"Python には 8 種の比較演算があります。比較演算の優先順位は全て同じです (ブール演算より高い優先順位です)。比較は任意に連鎖できます; \"] 比較演算子を連接できる。PHPとRubyには無い感じ。 a=50 # 通常 if (0 < a) and (a < 100): print("OK") else: print("NG") # 連接 if 0 < a < 100: print("OK") else: print("NG") 辞書オブジェクト KeyValue型。本家は以下。Keyは変更不能で一意でなければならない、と書いてある。 [clink implicit=\"false\" url=\"https://docs.python.org/ja/3/tutorial/datastructures.html#dictionaries\" imgurl=\"https://www.python.org/static/img/python-logo@2x.png\" title=\"5.5. 辞書型 (dictionary)\" excerpt=\"もう一つ、有用な型が Python に組み込まれています。それは 辞書 (dictionary)です。辞書は他の言語にも 連想記憶 (associated memory) や 連想配列 (associative array) という名前で存在することがあります。ある範囲の数でインデクス化されているシーケンスと異なり、辞書は キー (key) でインデクス化されています。\"] a = {1:\'one\',2:\'two\'} print(a) # {1:\'one\',2:\'two\'} # 代入 print(a[1]) # \'one\' a[1] = \'壱\' print(a[1]) # \'壱\' # 削除 del a[1] print(a[1]) # エラー キーを文字列にして連想配列みたくできる。 連想配列のキーにできるかどうかは、その型が更新可能であるかどうか? b = {\'hoge1\':\'fuga1\',\'hoge2\':\'fuga2\'} print(b) # {\'hoge1\':\'fuga1\',\'hoge2\':\'fuga2\'} リストとタプル 似て非なる配列的データ構造、リストとタプル。 リストの方は更新可能。タプルは更新不能。 任意の型を要素としてとれるので、配列ではなくリスト。 L1 = [1,2,3,4,5] print(L1) # [1,2,3,4,5] L2 = (1,2,3,4,5) print(L2) # (1,2,3,4,5) L1[0] = \'hoge\' print(L1) # [\'hoge\', 2, 3, 4, 5] L2[0] = 100 # TypeError: \'tuple\' object does not support item assignment 序数を使ってシーケンシャルアクセスできる。 ary = [1,5,3,4,9] print(ary[3]) # 4 str = \'abcdef\' print(str[1]) # b 負の序数を使うと後ろから数える。 ary = [1,5,3,4,9] print(ary[-1]) # 4 レンジも使える。 ary = [1,5,3,4,9] print(ary[1:3]) # [5,3,4] print(ary[-3:-1]) # [5,3,4] print(ary[:3]) # [1,5,3] レンジ指定で要素を更新できる。 ary = [1,5,3,4,9] ary[2:3] = [100,200] print(ary)# [1, 5, 100, 200, 4, 9] if ... elif ... else elseif が elif。 論理式が偽になるのは\"数値の0\"、空のコレクション、Noneオブジェクト。それ以外は真。 a = 50 if 0 < a < 35: print("OK") elif 35 <= a < 100: print("So much") else: print("NG") for,while forループとwhileループがある。iteratableオブジェクトを指定できる。 whileループについて。 str = \"aiueo\" stop = len(str) i=0 while i < stop: print(str[i]) i += 1 # a # i # u # e # o forループについて。 str = \'abcde\' for c in str: print(c) # a # b # c # d # e # continue, break str = \'abcde\' for c in str: if c == \'c\': continue if c == \'e\': break print(c) # a # b # d whileループ、forループの終了時に実行するブロックをelseで定義できる。 breakで中断した場合は実行されない。 str = \'abcde\' for c in str: print(c) else: print(\'ループ終了\') # a # b # c # d # e # ループ終了 iteratableオブジェクト よくあるパターン。要素の順序を走査するためのインターフェースを実装したオブジェクト。 本家によるとこんな感じ。 [clink implicit=\"false\" url=\"https://docs.python.org/ja/3/glossary.html#term-iterable\" imgurl=\"https://www.python.org/static/img/python-logo@2x.png\" title=\"iterable\" excerpt=\"(反復可能オブジェクト) 要素を一度に 1 つずつ返せるオブジェクトです。 反復可能オブジェクトの例には、(list, str, tuple といった) 全てのシーケンス型や、 dict や ファイルオブジェクト といった幾つかの非シーケンス型、 あるいは Sequence 意味論を実装した __iter__() メソッドか __getitem__() メソッドを持つ任意のクラスのインスタンスが含まれます。\"]