入門Python3 を読む~Python3の基礎まとめ~前編
- 作者: Bill Lubanovic,斎藤康毅,長尾高弘
- 出版社/メーカー: オライリージャパン
- 発売日: 2015/12/01
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (1件) を見る
一旦Pythonの復習をしようと思い、この本を借りてきた。
情報の整理のために、少しまとめておく。一部サンプルコードは本とは異なります。
分かりやすい本だったので、いつか買うかもしれない。
(ネットに書かれているもので)基本的な文法はここが分かりやすかった。
記事を二つに分けます。
基本的なことは前編で。(1章から6章)
テクニック的なものは後編で。(7章から12章)
(追記)
今さらPython3 (1) - 決意表明? - Deutschina's Tech Diary
こちらの記事である程度まとめてあったので、こっちを見るのがいいかもしれません。
2章 数値、文字列、変数
・[start:end:step]によるスライス(オフセットとは、基準からの距離のこと)
[:] 先頭から末尾まで [start:] startオフセットから末尾まで [:end] 先頭からend-1オフセットまで [start:end] startオフセットからend-1オフセットまで [start:end:step] stepごとに、startオフセットからend-1オフセットまで
・split()による分割
todos = 'aaa bbb,ccc ddd' todos.split(',') ['aaa bbb', 'ccc ddd'] todos.split() ['aaa', 'bbb,ccc', 'ddd']
・join()による結合
todos = ['aaa', 'bbb,ccc', 'ddd'] todos_string = ', '.join(todos) print(todos_string) aaa, bbb,ccc, ddd
3章 リスト、タプル、辞書、集合
・リスト 要素の変更(追加、削除、書き換え)が可能。
#リストの作成 empty_list = [] empty_list [] another_empty_list = list() another_empty_list [] list = ['a', 'b', 'c', 'd'] #指定したオフセットの要素の追加・削除 list.insert(1, 'x') list ['a', 'x', 'b', 'c', 'd'] del list[1] list ['a', 'b', 'c', 'd'] #pop()でオフセットを指定して要素を取り出して、削除(キューを作ることが出来る) list.pop() 'd' list ['a', 'b', 'c'] list.pop(1) 'b' list ['a', 'c'] #=による代入とcopy()によるコピー a = [1, 2, 3] a [1, 2, 3] b = a b [1, 2, 3] a[0] = 'x' a ['x', 1, 2] b ['x', 1, 2] a = [1, 2, 3] b = a.copy() c = list(a) d = a[:] a[0] = 'x' a ['x', 1, 2] b [1, 2, 3] c [1, 2, 3] d [1, 2, 3]
・タプル 要素の変更(追加、削除、書き換え)が不可能 リストに比べて消費スペースが小さい 辞書のキーになることができる
#タプルの作成 empty_tuple = () one_tuple = 'x', two_tuple = 'x', 'y' two_tuple = ('x', 'y') #タプルのアンパック a = 'x' b = 'y' c, d = a, b c 'x' d 'y'
・辞書
#辞書の作成 empty_dict = {} #リストの辞書への変換 lol = [['a', 'b'], ['c', 'd']] dict(lol) {'a':'d', 'c':'d'} #すべての要素の削除 one_dict = {'a':'b', 'c':'d'} one_dict.clear() {} #キー、要素、ペアの取得 keys() values() items() によって取得できるキー、要素、ペアの戻り値は特別なビューで返される。 戻り値を通常のリスト値にするには、list()関数を用いる
・集合 数学で使うあの集合
#集合の作成 a = {1, 2, 3, 4, 5} b = {2, 3, 6, 7, 8} a.union(b) # a | b 和集合 a.intersection(b) # a & b 共通集合 a.difference(b) # a - b 差集合 a.symmetric_difference(b) # a ^ b 対称的差集合 a.issubset(b) # a <= b 部分集合 # a < b 真部分集合 a.issuperset(b) # a >= b 上位集合(bの集合のすべての要素がaの集合の要素になっている。部分集合の逆) # a > b 真上位集合
この章は知識として抜けている箇所が多かった。
4章 コード構造
・行の継続は、行末にバックスラッシュをつける
・elseによるbreakのチェック(例はwhileループだが、forループでも一緒)
numbers = [1, 3, 5] position = 0 while position < len(numbers): number = numbers[position] if number % 2 == 0: print('Found even number', number) break position += 1 else: #breakが呼びだされていない print('No even number found') No even number found
この使い方は今まで知らなかった……。
ようは、ループ終了時にbreakが呼び出されていなかった場合の処理が書けるということだろう。
・zip()を使った複数シーケンスの反復処理
a = [1, 2, 3] b = ['a', 'b', 'c'] for i, j in zip(a, b): print(i, j) 1 a 2 b 3 c
・リスト内包表記
[expression for item in iterable] number_list = [number for number in range(1,6)] number_list [1, 2, 3, 4, 5] [expression for item in iterable if condition] number_list = [number for number in range(1,6) if number % 2 == 1] number_list [1, 3, 5]
・辞書包括表記
{key_item: value_item for item in iterable} word = 'letters' letter_counts = {letter: word.count(letter) for letter in word} letter_counts {'e': 2, 'l': 1, 'r': 1, 's': 1, 't': 2} #上記では、tとeを2回計算しているので word = 'letters' letter_counts = {letter: word.count(letter) for letter in set(word)} letter_counts
・集合内包表記
[item for item in iterable] a_set = {number for number in range(1,6) if number % 3 == 1} a_set {1, 4}
・ジェネレータ内包表記
タプルは内包表記をもたない。()を用いた内包表記は、ジェネレータ内包表記と呼ばれる。ジェネレータは、イテレータに値を渡す役割がある。
ジェネレータは一度しか実行することしかできない。
number_thing = (number for number in range(1,6)) for number in number_thing : print(number) 1 2 3 4 5 #リスト関数で呼び出せばリスト内包表記のように使えるが、ジェネレータは一度しか実行できないので number_thing = (number for number in range(1,6)) for number in number_thing : print(number) number_list = list(number_thing) number_list 1 2 3 4 5 []
・関数
デフォルト引数値の指定
def buggy(arg, result=[]): result.append(arg) print(result) buggy('a') buggy('b') ['a'] ['a', 'b'] def works(arg): result = [] result.append(arg) return result works('a') works('b') ['a'] ['b']
*による位置引数のタプル化
def print_args(*args): print('Positional argument tuple:', args) print_args(3, 2, 1, 'wait', 'uh...') Positional argument tuple: (3, 2, 1, 'wait', 'uh...')
**によるキーワード引数の辞書化
def print_kwargs(**kwargs): print('Keyword argument:', kwargs) print_kwargs(wine='merlot', entree='mutton', dessert='macaroon') Keyword argument: {'dessert': 'macaroon', 'wine': 'merlot', 'entree': 'mutton'}
docstring 関数のドキュメントの作成
def echo(anything): ''' test test test test ''' pass help(echo) Help on function echo in module __main__: echo(anything) test test test test
オブジェクトとしての関数 *argsと**kwargsの利用
def sum_args(*args): return sum(args) def run_with_positinal_args(func, *args): return func(*args) run_with_positinal_args(sum_args, 1, 2, 3, 4) 10
関数内関数
def outer(a, b): def inner(c, d): return c + d return inner(a, b) outer(4, 7) 11
def outer(a, b): def inner(c): return a + b + c return inner c = outer(1,2) c(3) 6
cが定義された時のa. bの値をouterは保持していて、さらにinnerはa, bにアクセスすることができる。
クロージャは、今まで意識使えてなかったですね。
クロージャの使い方はここに詳しく載っていた。
理解が不完全なので個別に記事を作るかも。
ジェネレータ関数
def my_range(first=0, last=10, step=1): number = first while number < last: yield number number += step ranger = my_range(1, 5) for x in ranger: print(x) 1 2 3 4
yieldはイテレータに渡す戻り値?を指定しているイメージなのかな。
デコレータ
入力として関数を1つ関数を1つ取って、別の関数を返す関数。
def test(func): def new_function(*args, **kwargs): print("test") result = func(*args, **kwargs) return result return new_function @test def add_number(a, b): return a + b add_number(1, 2) test 3
ここが分かりやすかった。
・名前空間とスコープ
locals()
ローカル名前空間の内容を示す辞書を返す
globals()
グローバル名前空間の内容を示す辞書を返す
・エラー処理
class TestClass(Exception): pass try: raise TestClass('error') except TestClass as e: print(e) error
エラー処理も独自に記事を書くかもです。
5章 モジュール、パッケージ、プログラム
・パッケージ
--main.py
--packege_sources--module1.py
--modele2.py
__init__.py
main.pyの中身
from packege_sources import module1, module2 ...
・標準ライブラリ
ここにまとまっている。
Python 標準ライブラリ — Python 3.5.2 ドキュメント
6章 オブジェクトとクラス
・クラスの定義
class TestClass(): def __init__(self, name): self.name = name a = TestClass('test') a.name 'test'
a = TestClass('test')
1.TestClassクラスの定義を探しだす
2.メモリ内に新しいオブジェクトのインスタンスを作成する
3.新しくつくったオブジェクトをself、引数の'test'をnameとして渡して、オブジェクトのinitメソッドを呼び出す(initはインスタンス作成後に呼び出される)
4.nameの値をオブジェクトに格納する
5.あの新たしいオブジェクトを返し、aという名前を付ける
a.name
オブジェクトのname属性を呼び出す
・super
class Person(): def __init__(self, name): self.name = name class MailPerson(Person): def __init__(self, name, email): super().__init__(name) self.email = email unknown = MailPerson('unknown', 'unknown')
unknown = MailPerson('unknown', 'unknown')
1.上記1~3を行う
2.super()が親クラスのPersonの定義を取り出す
3.super().init = Person.init()
・プロパティによる属性値の取得・設定
オブジェクトの非公開属性の値を読み書きできるようにセッターとゲッターメソッドを書くことが、オブジェクト指向言語の中にはある。
pythonはすべての属性とメソッドが公開されているので、セッターとゲッターを書く必要はないが、プロパティを用いて、セッターとゲッターを書くことが出来る。
ちなみに、非公開属性は先頭に__をつける。
class Test(): def __init__(self, input_name): self.__name = input_name def get_name(self): print('inside the getter') return self.__name def set_name(self, input_name): print('inside the setter') self.__name = input_name name = property(get_name, set_name) a = Test('test') print(a.name) a.name = 'Test' print(a.name) inside the getter test inside the setter inside the getter Test
デコレータで定義することも出来る
class Test(): def __init__(self, input_name): self.__name = input_name #ゲッターメソッド前に付ける @property def name(self): print('inside the getter') return self.__name #セッターメソッド前に付ける @name.setter def name(self, input_name): print('inside the setter') self.__name = input_name
・クラスメソッド
クラス単位でのセット、ゲットが可能になる。
class Test(): count = 0 def __init__(self): Test.count += 1 def exclaim(self): print("I'm an A") @classmethod def kids(cls): print('A has', cls.count, "object") a = Test() b = Test() c = Test() Test.kids() A has 3 object
Test.count += 1
クラスとしてのcountを参照している
cls.count
この時の引数はクラス自体。
・静的メソッド
クラスにもオブジェクトにも影響を与えないメソッド。
class Test(): @staticmethod def a(): print('test') Test.a() test
引数は取らない。オブジェクトを作らずに実行することだできる。
・ダックタイピング
同じ振る舞いをするものは、継承関係以外のオブジェクト同士でも同じようにみなして書くことが出来る
class Test(): def __init__(self, one, two): self.one = one self.two = two def a(self): return self.one def b(self): return self.two + '_' class Test1(Test): def b(self): return self.two + '?' class Test2(Test): def b(self): return self.two + '!' class Tests(): def a(self): return 'd' def b(self): return 'D_?!' a = Test('a', 'A') b = Test1('b', 'B') c = Test2('c', 'C') d = Tests() def a_b(obj): print(obj.a(), obj.b()) a_b(a) a_b(b) a_b(c) a_b(d) a A_ b B? c C! d D_?!
・特殊メソッド
ここに載ってる。
3. データモデル — Python 3.3.6 ドキュメント
特殊メソッド名 - Dive Into Python 3 日本語版
クラスをどんどん継承していくのではなく、has-aの関係をつくる。
class Test(): def __init__(self, one): self.one = one class Test1(): def __init__(self, two): self.two = two class Tests(): def __init__(self, test, test1): self.test = test self.test1 = test1 def show(self): print(self.test.one, self.test1.two) a = Test('a') b = Test1('b') c = Tests(a, b) c.show() a b
継承とどう使い分ければ良いのかイマイチ分からない。
・名前付きタプル
イミュータブルなオブジェクトとして振る舞える。
from collections import namedtuple Test = namedtuple('Test', 'a b') test1 = Test('A', 'B') test1 Test(a='A', b='B') test1.a 'A' test1.b 'B'
詳しくはここが分かりやすかった。