Hatena::Groupfukuoka-py

taketin.py RSSフィード

2012-01-04

初めてのPython 20章 パッケージインポート 21章 モジュールに関連する高度なテクニック

23:54 | 初めてのPython 20章 パッケージインポート 21章 モジュールに関連する高度なテクニック - taketin.py を含むブックマーク はてなブックマーク - 初めてのPython 20章 パッケージインポート 21章 モジュールに関連する高度なテクニック - taketin.py

20章 パッケージインポート

ディレクトリパスを指定して行うインポートの事を「パッケージインポート」と呼ぶ。

Python のコードを納めたディレクトリの事を「パッケージ」と呼ぶ。


パッケージインポートとは、ディレクトリ名前空間にするものとも言える。

import dir1.dir2.mod

from dir1.gir2.mod import x

上記書式だと、モジュールサーチパスが /dir0 に通っていたとして、

/dir0/dir1/dir2/mod.py

を見る。

※reload もディレクトリ単位でできる



21章 モジュールに関連する高度なテクニック

  • データの隠蔽
    • モジュール内データのカプセル化はできない
    • from * ステートメントで読み込む場合のみ、以下のルールで特定の変数をコピー対象から外す事はできる
      • __all__ 属性に、コピー対象の変数名を列挙する。この宣言をされた変数のみ from * ステートメントでコピーされる ex) __all__ = ["foo", "bar", "baz"] 等
      • 変数名の頭にアンダースコアを付ける ex) _hoge 等。__all__ 属性が設定されていない場合、このアンダースコアが頭に無い変数が全てコピーされる
    • import ステートメントを利用した場合このルールは適用されない

  • 拡張機能を有効にする
    • 次世代バージョンで組み込まれる新機能は、まずは「拡張機能」として扱われる
    • from __future__ import 機能名 で、拡張機能を利用できる


import longmodulename as name

# 以下のコードと同じ
import longmodulename
name = longmodulename
del longmodulename

# from ステートメントも同様
from module import longname as name

  • 相対インポートの構文
    • Python2.5 では . を使う事で、fromステートメントが属するパッケージのモジュールインポートサーチパス(sys.path)内のその他の場所にある同じ名前のモジュールよりも優先になる
    • Python2.6までは . を使わない通常のインポートでは、デフォルトで「ステートメントが属するパッケージ > その他のパッケージ」の順に相対インポートが行われる。
    • Python2.7 では ではデフォルトで絶対インポートとなる(あいまいさを避ける為)。なので、2.6 以下のバージョンを利用する場合は、2.7以降のバージョンに合わせ、from __future__ absolute_import 宣言をしておくのが望ましい



  • モジュールについての注意事項
    • トップレベルのコードはステートメントの順序に注意
      • トップレベルコードは前方参照ができないので、defステートメントは全て上に集めて記述し、その後にロジックを書くのが良い
    • import, from に指定するモジュール名は「変数名」である
    • from によって作られる変数と元の変数の間につながりは無い(コピーとなる為)
    • from * を使うと変数の意味がわかりにくくなる
    • from によってコピーされた変数はリロードの影響を受けない
    • リロードは内部でimportしているモジュールまで自動で行われない
    • 再帰インポートに注意(どうしても再帰インポートが必要な場合は、fromステートメントではなく importステートメントを使用する。モジュールのトップレベルではなく関数内、またはモジュールの最後であれば fromステートメントを使用しても良い)

AlexAlex2012/08/21 13:46It's posts like this that make surfing so much plesarue

arfvmjporarfvmjpor2012/08/21 18:425xfI0p <a href="http://ehnxlojxktne.com/">ehnxlojxktne</a>

utszqjjfutszqjjf2012/08/25 01:44iWUrRB , [url=http://oofsuqwxnvfx.com/]oofsuqwxnvfx[/url], [link=http://tlpijuivkaae.com/]tlpijuivkaae[/link], http://mkkqjrwykltz.com/

2011-12-21

初めてのPython 18章 モジュールとインポート 19章 モジュールのインポート、リロード

00:34 | 初めてのPython 18章 モジュールとインポート 19章 モジュールのインポート、リロード - taketin.py を含むブックマーク はてなブックマーク - 初めてのPython 18章 モジュールとインポート 19章 モジュールのインポート、リロード - taketin.py

18章 モジュールインポート


モジュールファイルをインポートすると、グローバルスコープがモジュールオブジェクトの属性名前空間になる

C, C++,(Jython を使っている場合は Javaも)等の言語で作られたモジュールエクステンションモジュールと呼ばれる。インポート方法は通常と同じ。



import ステートメントに渡すモジュール名は呼び出すモジュールのファイル名であり、モジュールオブジェクトを格納する変数名でもある

import a    # a が変数名でありファイル名である
a.spam('gumby')

この処理が行われるのは、該当モジュールがはじめてインポートされた場合のみである


上記4つを連結したものが sys.path となる。1 と 3 は自動的に設定される。カスタマイズできるのは 2 と 4 の内容となる。


バイトコードファイルはインポートに際して作成される。トップレベルファイルはバイトコードである .pycファイルは作成されない。

ロード済みモジュールは sys.modules にディクショナリとして保存される。インポート処理が行われるとまずここに格納されていないかがチェックされ、既にロードされていれば読み込まれない。明示的にモジュールの再読み込みをする場合は reload関数を使用する。


19章 モジュールインポート、リロード

>>> from module1 import printer
>>> printer('hello world')
hello world

  • from * ステートメント
    • トップレベルの変数が全てコピーされる
    • import ステートメントとの違いは、「すべての変数をコピーする」というところ

from ステートメントは名前空間を混乱させてしまう場合があるので、簡単なモジュールであれば import を使うようにし、from を使う場合は * を使用するのは1ファイルに1回を限度とし、できるだけインポートする変数を指定する様にすれば安全である。




reload関数を定期的に呼び出すようにすれば、プログラム全体を停止せずに随時変更を行うようなプログラムを作成する事ができ、ダイナミックなアプリケーションを組む事ができる。

2011-12-17

はじめてのPython 17章 関数に関連する高度なテクニック

03:28 | はじめてのPython 17章 関数に関連する高度なテクニック - taketin.py を含むブックマーク はてなブックマーク - はじめてのPython 17章 関数に関連する高度なテクニック - taketin.py

  • lambda式
    • defステートメントと違う点は、作成された関数関数オブジェクト)が式の戻り値になる、という点。つまり、戻り値変数に代入しない限りは関数に名前が無い、という事になる。この為、「無名関数」と呼ばれる。インラインでの関数定義(コールバック関数の定義など)によく使用される
    • lambda式はあくまで式である為、リストのリテラル関数の呼び出しコードの中などでも使える
    • lambda式はボディ部分も式である為、defステートメントに比べると汎用性は劣るが、コードを短く凝縮できる
    • lmbda式はコールバック関数の他、ジャンプテーブル(要素として単なるオブジェクトではなく、行うべき処理を組み込んだリストやディクショナリのこと)によく利用される
L = [(lambda x: x ** 2), (lambda x: x ** 3), (lambda x: x ** 4)]

for f in L:
    print f(2)     # 4, 8, 16 が出力される

print L[0](3)     # 9 が出力される

  • lambda式とネストスコープ
    • defステートメントの中に組み込まれたlambda式では、defステートメントのスコープをそのまま利用でき、lambda式によって作成された関数オブジェクトはネストスコープの変数を保持し続ける
    • lambda式が他のlambda式に組み込まれた(ネストされた)場合も、内側の式から外側の式のスコープにアクセスする事ができる
>>> action = (lambda x: (lambda y: x + y))
>>> act = action(99)
>>> act(3)
102
>>> ((lambda x: (lambda y: x + y)) (99))(4)
103

こういった書き方は読み辛いので、あまり良い方法とは言えない。


>>> def func(x, y, z): return x + y + z
…
>>> apply(fund, (2, 3, 4))
9
>>> f = lambda x, y, z: x + y + z
>>> apply(f, (2, 3, 4))
9

※ 但し、apply関数は Python3.0 で無くなる為、使用すべきでは無い。

使っているコードの移植方法は以下など。

2to3を使ってコードをPython 3に移植する - Dive Into Python 3 日本語版


  • map関数
    • 第一引数に渡された関数を、その後に指定されたシーケンスの個々要素に適用する関数
    • forステートメントでも同じような処理は書けるが、一般的にmap関数の方が処理が早くなる
>>> counters = [1, 2, 3, 4]
>>> def inc(x): return x + 10
…
>>> map(inc, counters)
[11, 12, 13, 14]

  • map関数と類似した関数: filter と reduce
    • filter関数
      • シーケンスの各要素から特定の条件に合うものを抽出する
    • reduce関数
      • まずシーケンスの1、2番目の要素を引数として関数を実行し、次にその結果得られた値と3番目の要素を引数として同じ関数を実行する
# filter
>>> filter((lambda x: x > 0), range(-5, 5))
[1, 2, 3, 4]

# reduce
>>> reduce((lambda x, y: x + y), [1, 2, 3, 4])
10

※ reduce関数は Python3.0 で functools に隔離されたようです


  • リスト内包表記
    • リスト内包表記内で ifステートメントや forステートメントのネストを利用すれば、ビルトイン関数を使用するよりも簡素なコードが書ける
# if を使ったリスト内包表記
>>> [x for x in range(5) if x % 2 == 0]
[0, 2, 4]

# filter関数を使うと以下の様になる
>>> filter((lambda x: x % 2 == 0), range(5))
[0, 2, 4]

>>> res = []
>>> for x in range(5):
…        if x % 2 == 0:
…            res.append(x)
…
>>> res
[0, 2, 4]
# for のネストを使ったリスト内包表記
>>> res = [x + y for x in [0, 1, 2] for y in [100, 200, 300]]
>>> res
[100, 200, 300, 101, 201, 301, 102, 202, 302]

# リスト内包表記を使わない場合の例
>>> res = []
>>> for x in [0, 1, 2]:
…        for y in [100, 200, 300]:
…            res.append(x + y)
…
>>> res
[100, 200, 300, 101, 201, 301, 102, 202, 302]

    • リスト内包表記は柔軟性、汎用性が高いがそのためにコードが難解になりやすいという欠点がある。(特にネストが行われた場合)
    • しかし現状は、読みにくいコードに「パフォーマンスの高さ」があるのも事実
    • forループ < map関数 < リスト内包表記 の順にパフォーマンスが高い
    • プログラムは keep it simple を心がけるべきなので、特にパフォーマンスが重要になる部分以外は、分かりやすい forループで記述するべきである

  • ジェネレータとイテレータ
    • ジェネレータ
      • いったん何らかの値を戻して、しばらく後にその時点から処理を再開する
      • ジェネレータ関数は実行が一時停止される。停止している間は「停止時の状態はどうだったか」「どこまで処理が進んだか」というステート情報が保持される
      • 通常の関数との違いは、返り値を yieldステートメントで返すという事
    • イテレータ
    • ジェネレータ式
      • イテレータとリスト内包表記を組み合わせたもの。式はリスト内包表記の [] を () に変えたもの
      • リスト内包表記とコードの持つ意味はほぼ同じだが、リスト内包表記は結果のリストを一度に作るのに対し、ジェネレータ式は反復処理により随時生成していく
>>> for num in (x ** 2 for x in range(4)):
…        print '%s, %s' % (num, num / 2.0)
…
0, 0.0
1, 0.5
4, 2.0
9, 4.5
      • ジェネレータ式を囲む () は、そのジェネレータ式が他の () の中に単独で存在する場合には付けなくてもかまわない
>>> sum(x ** 2 for x in range(4))
14

>>> sorted(x ** 2 for x in range(4))
[0, 1, 4, 9]

>>> sorted((x ** 2 for x in range(4)), reverse=True)
[9, 4, 1, 0]

>>> import math
>>> map(math.sqrt, (x ** 2 for x in range(4)))
[0.0, 1.0, 2.0, 3.0]
      • ジェネレータ式はリスト内包表記よりもやや遅い為、使うのは実行結果が膨大になる場合のみ使用するべきである

  • 関数を作る際のコツ
    • できる限り入力には引数、出力には returnステートメントを使用する(できる限り外から独立したものにする)
    • グローバル変数はどうしても必要な場合以外は使用しない
    • 引数が可変性オブジェクトの場合でも上書きしない(意図して設計されるものは別)
    • 関数の役割は一つに絞る
    • 関数はできる限り規模の小さいものにする
    • 他のモジュール変数に直接変更を加えない

>>> schedule = [ {echo, 'Spam!', {echo, 'Ham!'} }]
>>> for (func, arg) in schedule:
…         func(arg)
…
Spam!
Ham!

  • 関数についての注意事項
    • 変数がローカルスコープに属するかどうかはスタティックに決定される(defステートメントのどこかに代入の記述があれば、実行時ではなくコンパイル時にローカルスコープと定義される)
# case1
>>> x = 99
>>> def selector():
…        print x;    # グローバル変数として扱われる
… 
>>> selector()
99

# case2
>>> def selector():
…        print x
…        x = 88    # この記述があるので、xはコンパイル時にローカルスコープとして定義される
…
>>> selector()
存在しない変数を使用した旨の UnboundLocalError が表示される
    • 戻り値の無い関数
      • return, yield ステートメントを使用しない関数戻り値は None になる
      • こういった関数は他の言語で「プロシージャ」と呼ばれるものと同様の役割となる。通常、オブジェクトを上書きすることによって役割を果たす為、いわば副作用に依存して機能するものと言える
    • ネストスコープのループ
      • ループによって次々に変更が加えられていく変数の、ある時点での値を内側にネストされたコードで保持する、という場合には注意が必要。単純に外側の値を内側の変数に代入するコードを書いただけだと、内側の変数の値も外側の値とともに次々に変化する為

PrapatanPrapatan2012/02/20 19:05Thanks for sharing. What a peslarue to read!

brqiuabrqiua2012/02/21 18:11m13eDA <a href="http://qzenzrwhjkxr.com/">qzenzrwhjkxr</a>

ketdxqyketdxqy2012/02/22 00:52dpiZKx , [url=http://wtyptaaooelw.com/]wtyptaaooelw[/url], [link=http://biarxexnjoao.com/]biarxexnjoao[/link], http://ybmseavredhw.com/

xwvdaqsfgxwvdaqsfg2012/02/29 02:58XmZddh <a href="http://gwhqkyqzsvwp.com/">gwhqkyqzsvwp</a>

2011-12-14

はじめてのPython 15章 関数の基礎、16章 スコープと引数

00:47 | はじめてのPython 15章 関数の基礎、16章 スコープと引数 - taketin.py を含むブックマーク はてなブックマーク - はじめてのPython 15章 関数の基礎、16章 スコープと引数 - taketin.py

15章 関数の基礎

ステートメント、式
呼び出しmyfunc("spam", "eggs", meat=ham)
def, return, yielddef adder(a, b=1, *c): return a+b+c[0]
globaldef function(): global x; x='new'
lambdafuncs = [lambda x: x**2, lambda x: x*3]


  • returnステートメント
    • return は他の言語同様、値を返却して制御を戻す。
    • 関数内で returnステートメントを省略すると、Noneオブジェクトが返される。
  • yieldステートメント
    • 呼び出し側に値を戻した後もステートを保持し、処理を再開できるジェネレータと呼ばれる特殊な関数に用いられる。


  • globalステートメント
    • 関数内で定義された変数は、関数内飲みのスコープとなる。
    • モジュール全体で有効にしたい場合、globalステートメントを使用する。

  • defステートメントのネストと動的呼び出し
if test:
    def func():
        …
else:
    def func():
        …
…
func()

分岐によって関数の内容を変えるような記述が可能。


funcname = func
func()

変数関数名を代入する事で、関数オブジェクトリファレンスを代入する為、変数に()をつける事で呼び出しが可能。


16章 スコープと引数

  • スコープに関するルール


  • ネストスコープ
    • 関数1内で変数1と更に関数2が定義され、関数2内で変数1を呼び出す場合、ネストスコープとして特別な宣言無しで利用できる。ただし変更、代入を行う場合は global宣言が必要。
    • 以下のコードのようにすでに存在しない外側のスコープに属する変数を保持しているオブジェクトの事を「クロージャ」あるいは「ファクトリ関数」と呼ぶ
def f1():
    x = 88
    def f2():
        print x
    return f2    # f1() の返り値は f2() である

action = f1()
action()    # f2() が実行され、88 と表示される

  • lambda式
    • defステートメントと同じように関数を作るのに用いられる式
    • 式なのでリストやディクショナリのリテラルの中など、defステートメントが使えない場所で使用する事ができる


つまり、

不変性オブジェクト引数は、Cの「値渡し」引数に似ている。

可変性オブジェクト引数は、Cの「ポインタ渡し」引数に似ている。


  • 参照渡しと同様の結果を得る
    • Pythonには他言語でいう「引数の参照渡し」は無い。しかし同様の結果を得る書き方はできる
def multiple(x, y):
    x = 2
    y = [3, 4]
    return x, y

X = 1
L = [1, 2]
X, L = multiple(X, L)    # X, L の値は (2, [3, 4]) というタプルになる。元の変数の値にアンパック代入している。

  • 引数のバリエーション
    • 通常の引数 <位置によるマッチング>
      • どの位置に置かれているかを基準にマッチングが行われる
    • キーワード引数 <名前によるマッチング>
      • 関数呼び出し側のコードで、(引数 = 値) と指定する事ができる。この場合引数はdefステートメントの引数と名前によって対応付けられる
    • デフォルト値の設定
      • defステートメントのカッコ内で = という記号を使用すれば、引数デフォルト値を設定できる
    • 引数の数を自由に変えられるようにする
      • defステートメントのカッコ内で * という記号を使用すれば、呼び出し時に引数の数を自由に増やす事ができる(Cで言う可変引数に似ている)
    • 引数の数を呼び出し側で自由に変えられるようにする
      • 呼び出し側で * という記号を使えば、複数の引数を同時に渡す事ができる。

※ * が一つならタプル、二つならディクショナリに収められる

JoanaJoana2012/02/21 03:21To think, I was confused a mintue ago.

iidyhrkdiidyhrkd2012/02/21 19:36GExFmc <a href="http://ufqkcxuvcarx.com/">ufqkcxuvcarx</a>

bniisekobniiseko2012/02/22 01:33AdzhX0 , [url=http://bcxehnggfccs.com/]bcxehnggfccs[/url], [link=http://sfntkuxvllmq.com/]sfntkuxvllmq[/link], http://vugswbsuqada.com/

cejpukeucejpukeu2012/02/29 01:507c7Tyi <a href="http://wglslokygyvl.com/">wglslokygyvl</a>

2011-12-10

初めてのPython 13章 whileループとforループ 14章 Pythonのドキュメント

01:06 | 初めてのPython 13章 whileループとforループ 14章 Pythonのドキュメント - taketin.py を含むブックマーク はてなブックマーク - 初めてのPython 13章 whileループとforループ 14章 Pythonのドキュメント - taketin.py

13章 whileループとforループ

・while ループ

while <条件>:
    <ステートメント>
else:
    <ステートメント2>

else ブロックはオプションであり、breakで処理が終了した場合は実行されない


・break, continue, pass ステートメントと else ブロック

  • break
    • ステートメントが直接属するループを無条件で抜ける
  • continue
    • ステートメントが直接属するループの先頭(見出し行)に無条件で戻る
  • pass
  • else
    • 見出し行に指定された条件が満たされなくなり、ループが終了する際に実行される。break ステートメントによってループが終了される場合には実行されない

・for ループ

for ループはシーケンスオブジェクトなら何にでも使用できる

for <target> in <object>:
    <statements>
else:
    <statements>

処理対象のオブジェクトと代入ターゲットを指定し、その後繰り返し処理に対応するステートメントを書く

  • 代入ターゲットは通常 for ステートメントと同じ名前空間に属する変数として扱われる
  • ループ終了後も最後に代入された要素へのリファレンスを保持し続ける

アンパック代入

>>> T = [(1, 2), (3, 4), (5, 6)]
>>> for (a, b) in T:
…        print a, b
…
1 2
3 4
5 6

ファイルを対象とした反復処理

>>> f = open('script.py')
>>> f.readline()

# 現在はこれに良く似た機能を持つ next() というメソッドが用意されている
# readline との違いはファイルの末尾に到達した時に空文字列を返さず、
# StopIteration というビルトイン例外を発生させる点

>>> f = open('script.py')
>>> f.next()

# 更に現在のPythonはファイル内容を1行づつ読み込む際、読み込みメソッドを呼び出す必要が無い
# この方法は3つのメリットがある。コードがシンプル、実行速度が上がる、メモリ節約。
>>> for line in open('script.py'): # next() が自動的に呼ばれるprint line,

他のオブジェクトへの反復処理

  • for ループは内部動作として、処理対象のオブジェクト引数として iter() というビルトイン関数を呼び出している。これを明示的に書く事で for ループを記述せずにイテレーション処理をする事ができる。
>>> L = [1, 2, 3]
>>> I = iter(L)
>>> I.next()
1
>>> I.next()
2
>>> I.next()
3

特殊な forループ

  • range() を使う
>>> for i in range(3):
…        print i,
0
1
2

# シーケンスに対して変則的なアクセス
>>> S = 'abcdefghijk'
>>> range(0, len(S), 2)
[0, 2, 4, 6, 8, 10]

>>> for i in range(0, len(S), 2): print S[i],
a c e g i k

しかし実はスライシングでもっと効率良く書ける

>>> for x in S[::2]: print x

シーケンスを更新する forループ

>>> L = [1, 2, 3, 4, 5]
>>> for i in range(len(L)):
…        L[i] += 1
...
>>> L
[2, 3, 4, 5, 6]

通常の forループだと代入された変数の方を更新してしまうので、インデックスを使ってオリジナルの値を変更するようにする。


zip関数の利用

>>> L1 = [1, 2, 3, 4]
>>> L2 = [5, 6, 7, 8]
>>> zip(L1, L2)
>>> for (x, y) in zip(L1, L2):
…        print x, y, '--', x+y
…
1 5 -- 6
2 6 -- 8
3 7 -- 10
4 8 -- 12

zip関数を使ったディクショナリの生成と dict関数

>>> keys = ['spam', 'eggs', 'toast']
>>> vals = [1, 3, 5]
>>> zip(keys, vals)
[('spam', 1), ('eggs', 3), ('toast', 5)]

>>> D = {}
>>> for (k, v) in zip(keys, gals): D[k] = v
…
>>> D
{'toast':5, 'eggs':3, 'spam':1}

# dict関数を使えば forループを使用せずに同じ事ができる
>>> D2 = dict(zip(keys, vals))
>>> D2
{'toast':5, 'eggs':3, 'spam':1}

dict は正確には「ディクショナリオブジェクトコンストラクタ」である。


enumerate関数

>>> S = 'spam'
>>> for (offset, item) in enumerate(S):
…        print item, 'appears at offset', offset
…
s appears at offset 0
p appears at offset 1
a appears at offset 2
m appears at offset 3

enumerate関数はジェネレータと呼ばれるオブジェクトを返す。これは反復処理に対応したオブジェクトであり、nextメソッドを持っている為、イテレート処理を行える。


・リスト内包表記

# range() を使った記法
>>> L = [1, 2, 3, 4, 5]
>>> for i in range(len(L)):
…        L[i] += 10
…
>>> L
[11, 12, 13, 14, 15]

# リスト内包表記で書き直す
>>> L = [x +10 for x in L]
>>> L
[21, 22, 23, 24, 25]

リスト内包表記でしかできない事といのは無いが、以下のメリットがある。


ファイルに対してのリスト内包表記

>>> lines = [line.rstrip() for line in open('huge.py')]
>>> lines
['import sys', 'print sys.path', 'x = 2', 'print 2 ** 33']

リスト内包表記の拡張構文

# 先頭が p の行だけ取り出す
>>> lines = [line.rstrip() for line in open('hoge.py') if line[0] == 'p']
>>> lines
['print sys.path', 'print 2 ** 33']

# ループのネスト
>>> [x + y for x in 'abc' for y in 'lmn']
['al', 'am', 'an', 'bl', 'bm', 'bn', 'cl', 'cm', 'cn']

14章 Pythonのドキュメント

Python のドキュメントの種類

#プログラム中のコメント
dir関数引数に渡したオブジェクトの属性リストを返す
ドキュメンテーション文字列:__doc__コメント同様、プログラム中に組み込む
PyDoc:help関数テキストベースでドキュメントを表示する
PyDoc:GUIインターフェースWebブラウザにドキュメント表示
標準マニュアルセットPythonやツールセットに関する標準マニュアル
Webサイトオンラインチュートリアルリファレンスなど
書籍市販されている紙媒体の書籍

ドキュメンテーション文字列:__doc__


PyDoc:help関数


ステートメントについてのまとめ

  • コロンを忘れない
  • トップレベルのコードは字下げしない
  • 対話型コマンドラインでは空白行が意味を持つ
  • 字下げに一貫性を持たせる
  • C と混同しない(カッコやセミコロン
  • できる限り whileやrange()は使わず、単純なforループを使う
  • 可変性を持つオブジェクトの代入に注意する
  • オブジェクトの上書きを行う関数は値を戻さない
  • 関数を呼び出す際には必ずカッコを使用する
  • インポート、リロードの際には拡張子やパスは使用しない