ライフゲーム写経その4: Pythonのdef関数、スコープとざっくり出会う
とりあえず部分的に練った奴だけ貼っとこうと思った。
何故インデントが反映されないんだ(懊悩)*1
ひとまずは全角space2つでindent1つ分を表現した。
そして、何故か、空のリストを表す[ ]が表示されないので、間に半角spaceを入れた。
コードの挿入ってどうやるのがいいのか?????
#関数
def func(a, b):
c = a + b
return c
p = func(3, 4)
print(p)#7
def func(a, b):
return a + b
p = func(3, 4)
print(p)#7
def func(a,b):
return a+b
p=func(3,4)
print(p)#7
#えー。ひどい。 There's the only way to do it.にしてはスペースの扱いが雑だなあ。三つめのスクリプトが少なくとも一番短い、関数の定義の中身があれっぽいけど。でもこれだけ短い処理ならありな表記なんじゃ。でもこれだけ短いからこそ、短くする必要もないし、可読性を重視するなら一番上か。これだけ短いコードだから読みにくいも読みやすいもないけど。スペースは、アルファベットが続かない時には省略する方向で行こうと思う。
公式にPEP8、Style Guide for Python Codeとかっていう名前のコーディングガイドがあることが分かった。IDEにはガイドラインによるチェックの機能があるのらしいので、開発環境をセットアップする時点でこれを入れておかないと、あとで統一のために修正するのが大変だということ。私が無知なだけだった、よかった。
以下、スペースについて、PEP8から引用。
式や文の中のスペース文字
Whitespace in Expressions and StatementsPet Peeves
以下のような状況で、余計なスペース文字を使わないでください。
Avoid extraneous whitespace in the following situations:
丸カッコ、角カッコ、波カッコの内側.
Immediately inside parentheses, brackets or braces.
Yes: spam(ham[1], {eggs: 2}) No: spam( ham[ 1 ], { eggs: 2 } )
カンマ、セミコロン、コロンの手前
Immediately before a comma, semicolon, or colon
Yes: if x == 4: print x, y; x, y = y, x No: if x == 4 : print x , y ; x , y = y , x
関数呼び出しの引数リストの開始時の開きカッコの手前
Immediately before the open parenthesis that starts the argument list of a function call
Yes: spam(1) No: spam (1)
インデックスやスライスの角カッコの開きカッコの手前
Immediately before the open parenthesis that starts an indexing or slicing
Yes: dict['key'] = list[index] No: dict ['key'] = list [index]
代入などの演算子の左右に、他の行と揃えるために2つ以上のスペースを 入れないでください。
More than one space around an assignment (or other) operator to align it with another.
Yes:
x = 1 y = 2 long_variable = 3
No:
x = 1 y = 2 long_variable = 3
その他の推奨
Other Recommendations
次の2項演算子の左右は常に1つのスペースで囲んでください。: 代入 (=), 複合代入 (+=, -= etc.), 比較 (==, <, >, !=, <>, <=, >=, in, not in, is, is not), 論理 (and, or,not).
Always surround these binary operators with a single space on either side: assignment (=), augmented assignment (+=, -= etc.), comparisons (==, <, >, !=, <>, <=, >=, in, not in, is, is not), Booleans (and, or, not).
優先順位の違う演算子を使う場合、最も優先順位が低い演算子の左右に スペースを入れることを考慮してください。 スペースを入れるかどうかは各自の判断に任せますが、2つ以上のスペースを 使うことは避け、2項演算子の左右は常に同じ量のスペースを入れてください。
If operators with different priorities are used, consider adding whitespace around the operators with the lowest priority(ies). Use your own judgment; however, never use more than one space, and always have the same amount of whitespace on both sides of a binary operator.
Yes:
i = i + 1 submitted += 1 x = x*2 - 1 hypot2 = x*x + y*y c = (a+b) * (a-b)
No:
i=i+1 submitted +=1 x = x * 2 - 1 hypot2 = x * x + y * y c = (a + b) * (a - b)
キーワード引数や引数のデフォルト値では = の左右にスペースを入れないでください
Don't use spaces around the = sign when used to indicate a keyword argument or a default parameter value.
Yes:
def complex(real, imag=0.0): return magic(r=real, i=imag)
No:
def complex(real, imag = 0.0): return magic(r = real, i = imag)
複合文 (複数の文を1つの行に書くこと) は一般的には推奨されません.
Compound statements (multiple statements on the same line) are generally discouraged.
Yes:
if foo == 'blah': do_blah_thing() do_one() do_two() do_three()
Rather not:
if foo == 'blah': do_blah_thing() do_one(); do_two(); do_three()
小さい body を持つ if/for/while 文を1行に書くことが許される場合もありますが、 複数項を持つ文では絶対にしないでください。また、そういった長い行を 折り返ししないでください。
While sometimes it's okay to put an if/for/while with a small body on the same line, never do this for multi-clause statements. Also avoid folding such long lines!
Rather not:
if foo == 'blah': do_blah_thing() for x in lst: total += x while t < 10: t = delay()
Definitely not:
if foo == 'blah': do_blah_thing() else: do_non_blah_thing() try: something() finally: cleanup() do_one(); do_two(); do_three(long, argument, list, like, this) if foo == 'blah': one(); two(); three()
で、続き。
##スコープ
#変数を定義する場所によって決まる、変数が扱える範囲のこと#関数の外で定義した変数は関数内で利用できるが、関数内で定義した変数は関数の外では利用できない、さらに、同じ名前の変数を定義した場合、関数内で定義した変数と関数外で定義した変数は別物として両立して扱う
#関数内で定義した変数をprivate変数、関数外で定義した変数をglobal変数という##変数と引数と代入の関係と立場の違いがよく分からない
def func(a2,b2):
c=a+b
return c
a=2
b=3
p=func(5,6)
print(p)#5
#信じられない、後の行に出てくる変数の定義を関数内に持ってくるってことは、private変数が代入されてない場合、関数の外を全走査してglobal変数で定義されてる値を探してくるってこと?
##ついでに、もし同じglobal変数が複数回宣言されていたら、一番最後の代入に従うの?
#因みに関数にreturnを忘れた場合、
def func(a2,b2):
c=a+b
a=2
b=3
p=func(5,6)
print(p)#None 初めて見た、この返事。どういう時に出るんだろう?
def func(a2,b2):
c=a+b
return
a=2
b=3
p=func(5,6)
print(p)
#None
##########################################alive, dead, height, width という変数で、生きているセル、死んでいるセル、フィールドの縦幅、横幅を表す。
#ずっと使う値は最初に変数に代入しておくと間違えにくくて変更もしやすくて便利#init(), show()という関数は、フィールドを初期化する変数で全部死んだセルのフィールドを返す関数、引数で渡したfieldを画面に表示する関数
##デフォルト??→あ、ちがった。#わかったこと:def関数は、デフォルトでPythonが用意してくれてる関数と同じように使う事のできる関数を、自分で新たに追加させてくれる関数なんだ
#リスト.append()は、リストの最後尾にデータを追加する操作。
##関数?
def init(): #引数なしか。引数ってなんだ!(発狂)
field=[ ] #ライフゲームのフィールド#なんなんだこの変数は、空のリストでも定義として成立するのかへー
for i in range(height): #height回ループし、フィールドの縦のマス目を表現#ここに定義がない変数heightが出てきたけど、global変数であとから定義するんだろう
row=[ ]#じゃあなんだこれ#リストrow、フィールドの一行分
for j in range(width): #iとかjが分からない
row.append(dead) #リストrowに中身を与える#deadはglobal変数で与える
field.append(row) #fieldにリストrowを与える
return field
#メモなしver.def init():
field=[ ]
for i in range(height):
row=[ ]
for j in range(width):
row.append(dead)
field.append(row)
return field#うわぁーん!私はデカルトさんじゃないんだよう!(図と式の間の行き来が、思考停止的にしか理解できない)
#何も見ないで自分でやってみよう!
#空のフィールドを与える
def init(height, width): #なんで!引数、与えた方が色んなサイズのフィールドでできて便利でしょ!引数なしなんてことあっていいのか!引数(あれば)なのかっ!
field=[ ]
for i in range(height):
row=[ ]
field.append(row)
for j in range(width):
row.append(dead)
return field
#し~ん
#写経と見せかけてトライツー。
#空のフィールドを与える関数、多分後でGUIのボタン一つで呼び出せるようにするものdef init(): #引数にheightとwidthあった方が便利だと思うなあ。→ああ!なくてもglobal変数で定義されれば勝手に走査して持ってくるんだ!ほんとに引数ってなにさ…いらない子?可読性のため?
field=[ ]
for i in range(height): #ほんとにiが分からない rangeも分かってない?height回処理を繰り返す、というのが行の意味だけど、逐語的には分からぬ
row=[ ] #これは1行前に与えてもよさそう。
field.append(row) #う~ん、2行前に出しちゃった。これでも行けるかどうか知りたくなる
for j in range(width):
row.append(dead)
return field#さっきよりはまし。と見せかけて、引数以外はさっきと一緒だなあ。不安になってとりあえず空のリストだけのフィールドを作っているwで、後からその全部にゾザーッと入れてる。
#写経
#空のフィールドを与える関数。呼び出しやすいように関数にする。多分、GUIのボタン一つで呼び出す、高さと幅はその時々で指定できるように、スコープの広いglobal変数で与えることにする。
def init():
field=[ ]
for i in range(height):
row=[ ]
for j in range(width): #ここはぐっと堪えた
row.append(dead)
field.append(row)
return field
#うん、この書き方だと一瞬不安になる(入れ子になってるので途中でちょっと宙ぶらりんな感じになる)けど、入れ子っぽくて、オブジェクトっぽいのかも?
#最初にぜんぶ与えるのが好きだなあ、今のところ
#閑話休題
def init():
field=[ ]
for i in range(height):
row=[ ]
for j in range(width):
row.append(dead)
field.append(row)
return field
def show(field): #global関数の方のfieldだ、今回は引数になってる。吐こうかな
for i in range(height):
for j in range(width):
if field[i][j]==alive:
print("##",end=" ")
elif field[i][j]==dead:
print("[ ]",end=" ")
print()alive=1
dead=0height=5
width=5field=init() #ここのfieldと関数の中のfieldは別の関数(global関数、private関数)
show(field)
#メモなしver.
def init():
field=[ ]
for i in range(height):
row=[ ]
for j in range(width):
row.append(dead)
field.append(row)
return fielddef show(field):
for i in range(height):
for j in range(width):
if field[i][j]==alive:
print("##",end=" ")
elif field[i][j]==dead:
print("[ ]",end=" ")
print()alive=1
dead=0height=5
width=5field=init()
show(field)
#[ ] [ ] [ ] [ ] [ ]
#[ ] [ ] [ ] [ ] [ ]
#[ ] [ ] [ ] [ ] [ ]
#[ ] [ ] [ ] [ ] [ ]
#[ ] [ ] [ ] [ ] [ ]
まとめ
#なんか、part3に戻ろう。range忘れたし。
#インタープリタ言語だと分かってからぐんと文法の理解がしやすくなった。
#本当にコード書くのは、再現性のあることで、これは新しい幸せだなあ。みんながある約束事の範疇で、同じ機能を見ていることができる。
#細則気になる初心者くんの私、上記リンク先PEP8を見て量の多さに怯えるべき。そして、怠けたいと強く望んだなら、コードガイドの入った開発環境を用意するべき。(必要を痛感してから動く方の人間)
*1:ああああ!もしかして、インデントにはTabではなくSpace4つが推奨されているのって、こういうことか!