Skip to content

Latest commit

 

History

History

d02

day02: vscodeでプログラミング

1. 課題用のディレクトリを作る

1.1. poetry new k00

今日の課題は k00 です.

> poetry new k00

いろいろ聞かれます.よく読んで答えましょう.基本的にはすべて提示されたままでいいですが,Authorについては,Kotaro Sonoda <aa83988848@ms.nagasaki-u.ac.jp>などと,「自分の名前 スペース 三角カッコ メールアドレス 三角カッコ閉じ」にしましょう.

ディレクトリができたら,そのディレクトリの下に移動します.

> cd k00

仮想環境(システムのsite-packagesを用いない,独自のsite-packages)をpoetry で作成します.独自のsite-packagesを使うことで,システムのsite-packagesに依存させないようにできます.

> poetry env use py # `py`は仮想環境で`python`として利用するコマンドパス

これにより,.venv/というディレクトリが新たに作られます.

> poetry env info

Virtualenv
Python:         3.12.3
Implementation: CPython
Path:           /Users/kotaro/MyRepository/MyLecture/psp2/k00/.venv
Executable:     /Users/kotaro/MyRepository/MyLecture/psp2/k00/.venv/bin/python
Valid:          True

Base
Platform:   darwin
OS:         posix
Python:     3.12.3
Path:       /opt/homebrew/opt/python@3.12/Frameworks/Python.framework/Versions/3.12
Executable: /opt/homebrew/opt/python@3.12/Frameworks/Python.framework/Versions/3.12/bin/python3.12

皆さんのところでは,どうなるでしょう.

1.2. k00/.venv/

仮想環境に入るときには,macやlinuxなら

> source .venv/bin/activate

windows の command promptなら

> .\.venv\Scripts\Activate.bat

windows の PowerShellの場合は,

PS1 > .\.venv\Scripts\Activate.ps1

で入ることができます.この場合プロンプトが(k00-py3.12)となります.

PowerShellの場合,うまく行かない可能性があります.そのときは,

PS > Set-ExecutionPolicy RemoteSigned -Scope CurrentUser -Force

を入力してください.

仮想環境に入ると,インタプリタの場所,および外部パッケージ置き場が変わります.

仮想環境から出るときには,いずれのOSでも

> deactivate

です.

2. それでは今日の課題をやっていきましょう.

2.1. k00/k00/k00_turtle.py

vscodeを起動します.

起動直後

左端にあるアイコンは,メニューです.一番下にある帯には,現在開いているファイルに関する「状態」が表示されています.

ウィンドウのほとんどの部分は,エディタです.「ファイル名 x」という感じで,最近のウェブブラウザのように「タブ」が並びます.

初期起動時には,「Get Started」というタブが立ち上がっています.使わないので「x」を押して消してください.

一番上にあるアイコンを押してください.これは「エクスプローラ」と呼ばれています.

エクスプローラ

OPEN EDITORSには,現在開いているエディタで編集しているファイル名が並びます.先ほどタブを閉じたので何もありません.

その下にはNO FOLDER OPENEDと表示され,何やら青いボタンが並んでいます.

説明したように,「ファイルを開く」のではなく,「フォルダを開く」というボタンです.ちなみに下のボタン「Clone Repository」は「レポジトリ」と呼ばれる特殊なフォルダを開くボタンです.

さきほど作ったk00フォルダを開きます.

NO FOLDER OPENED」の表示が「k00」に変わり,

k00を開く

のように表示されていると思います.

K00」のあたりにマウスを移動させると,その帯の右側に4つのアイコンが並びます.それぞれのアイコンにマウスを移動させると説明が表示されますが,左から,「ファイルを追加」「フォルダを追加」「更新」「表示を縮める」です.

k00の横

なにかプログラミングしてみましょう.K00の下のk00というディレクトリが提出するパッケージです.まずはk00/k00の下にファイルを追加します.

v K00の下の> k00をクリックすると,k00フォルダが選択され,中身がリストアップされます.

unfold k00/k00

このフォルダで「ファイル追加」アイコンを押して,「k00_turtle.py」という名前のファイルを新しく作ってみます.

new file k00_turtle.py

OPENED EDITORS」にk00_turtle.pyが列挙され,k00_turtle.pyというタブが開きます.

もしかしたら,インタープリタを聞かれるかもしれません.そのときは,./.venv/bin/pythonを選びましょう.

select interpreter

k00_turtle.py に以下のようなコードを書きましょう.

# coding:utf-8

# 使うモジュールの指定
# turtleというモジュールを使う
import turtle

def main()-> None:
    """
    (このmain関数が何をするのかを書く.)
    """
    # 上の"""〜"""は,help(関数名)で表示される.

    #
    turtle.setup(width=300, height=300)

    #
    # kame1, kame2は,turtleモジュールに定義されているTurtle型
    kame1 = turtle.Turtle()
    kame2 = turtle.Turtle()

    #
    kame1.pencolor('red')
    kame2.pencolor('blue')

    #
    kame1.penup()
    kame1.goto(50,50)

    kame2.penup()
    kame2.goto(-50,50)

    kame1.pendown()
    kame2.pendown()

    #
    kame1.left(60)
    kame2.left(120)

    #
    kame1.forward(100)
    kame2.backward(200)

    #
    turtle.exitonclick()

if __name__ == '__main__':
    main()
  • """」で囲まれた部分は,一般に複数行のコメントアウトで,pythonの実行コードから無視されます.
    • 特にdef文直後の"""ブロックは「docString」と呼ばれ,help()関数で表示されます.
  • #」記号のある行はいわゆるコメントアウトで,pythonの実行コードから無視されます.
  • コメントアウト,文字列,など色分けされていますね.
  • 最初の行のコメントアウト「# coding:utf-8」は,このソースコードの日本語が文字コード「utf-8」で書かれていることをIDEに教えています.Windowsの場合は文字コードが「shift-jis」かもしれません.

では,このk00_turtle.pyを実行しましょう.

vscodeとは別に,コマンドプロンプトを立ち上げて,

> cd c:\Users\kotaro\Documents\psp2\k00\k00

k00フォルダに移動し,

> poetry run python k00/k00_turtle.py

とすればプログラムが動きます.

これでもいいのですが,vscodeはウィンドウの中でコマンドプロンプトを起動できます.上部メニューに「ターミナル」があり,そこに「新しいターミナルを開く」というのがあります.

ターミナル

(k00-py3.12)」というプロンプトのコマンドプロンプトがエディタの下の領域に立ち上がります.フォルダも現在作業中の場所に移動しています.つまり,vscodeでは直下に.venvというフォルダがあると,自動的に仮想環境に入るのです.

PowerShellの場合は,プロンプトが変わらないので,仮想環境が適用されているのか否かが不明なので,「規定のプロファイルを選択」からCommand Promptを選んでおきましょう.

規定のプロファイルを選択

実行は,ここで

(k00-py3.12) > python k00/k00_turtle.py

でよいでしょう.

2.2. k00/test_k00_turtle.py:インタフェースからのパッケージ読み込み

モジュールk00_turtle.pyは,パッケージk00(ディレクトリ)に含まれています.

このモジュールをインタフェースプログラムの中で呼び出して実行してみましょう.

モジュール関数の呼び出し方は,以下のようになります.

from k00 import k00_turtle as my

my.main()
  • from (パッケージディレクトリパス) import (モジュールの拡張子省略名) as (別名)
  • (別名).(関数オブジェクト)で呼び出します.

パスについては,importについてを参照.

パッケージのパス(PATH,場所)は,実行するpython環境のsys.pathに列挙されているPATHの直下に無ければいけません.

(k00-py3.12) > python
>>>> import sys
>>>> print(sys.path)
['', '/opt/homebrew/Cellar/python@3.12/3.12.3/Frameworks/Python.framework/Versions/3.12/lib/python312.zip', '/opt/homebrew/Cellar/python@3.12/3.12.3/Frameworks/Python.framework/Versions/3.12/lib/python3.12', '/opt/homebrew/Cellar/python@3.12/3.12.3/Frameworks/Python.framework/Versions/3.12/lib/python3.12/lib-dynload', '/Users/kotaro/MyRepository/MyLecture/psp2/k00/.venv/lib/python3.12/site-packages']
>>>>

あなたのk00開発環境(仮想環境.venv,(k00-py3.12))のsys.pathsite-packagesは上記のようになると思います.

唯一のsite-packagesである,psp2/k00/.venv/lib/python3.12/site-packagesを実際に見てみると

規定のプロファイルを選択

の左側のエクスプローラでわかるように,今のところk00はありません.

> poetry install --sync

をすると,現在作成中のパッケージk00/k00を呼び出せるようになります.

(k00-py3.12) > python
>>> import sys
>>> print(sys.path)
['', '/opt/homebrew/Cellar/python@3.12/3.12.3/Frameworks/Python.framework/Versions/3.12/lib/python312.zip', '/opt/homebrew/Cellar/python@3.12/3.12.3/Frameworks/Python.framework/Versions/3.12/lib/python3.12', '/opt/homebrew/Cellar/python@3.12/3.12.3/Frameworks/Python.framework/Versions/3.12/lib/python3.12/lib-dynload', '/Users/kotaro/MyRepository/MyLecture/psp2/k00/.venv/lib/python3.12/site-packages', '/Users/kotaro/MyRepository/MyLecture/psp2/k00']
>>>

sys.pathの中に,psp2/k00が加わりました.

また,site-packagesを見ると

install

のように,若干ファイルが増えています(だけど,k00フォルダは無い)

sys.pathpsp2/k00フォルダが列挙されているので,(k00-py3.12)の仮想環境であれば, psp2/k00/k00というフォルダをパッケージとして読み込むことができます.

たとえば,psp2/k00/tests/test_k00_turtle.pyという名前で上のインタフェースプログラムを書いておき,

> poetry run python tests/test_k00_turtle.py

でテストできます.

また,

> poetry run python
>>> from k00 import k00_turtle as my
>>> help(my.main)
Help on function main in module k00.k00_turtle:

main() -> None
    (このmain関数が何をするのかを書く.)

k00_turtle.pymain関数のdocStringが表示されます.

2.3. k00/dists/k00-[...].whl:提出

2.3.1. poetry version,poetry build: wheelに圧縮

> poetry build

で,k00/dists/k00-0.1.0-py3-none-any.whlが作られます.

これを提出してください.0.1.0はversionです.

再提出の際,buildの前に以下の操作を行ってください.

  • 前に提出したものとモジュール名や関数名を変えない修正なら(例:関数の中の処理を変更.間違いを修正)
    poetry version patch
    
  • モジュールや関数を増やす修正なら(例:最初の提出は(1)だけだったが,次の提出は(2)のモジュールも増やした)
    poetry version minor
    
  • モジュールや関数を減らす修正なら(例:関数名を変更した.)
    poetry version major
    

patcha.b.ccが増え,minorb, majoraが増えます.

2.3.2. 提出物のcheck

TAは,適当な環境で,

pip install k00-0.1.0-py3-none-any.whl

して,site-packagesk00をインストールします.

そこで上のtest_k00_turtle.pyを実行します.再現されるかな.

チェックが終わったら,忘れずにアンインストールして環境美化に努めます.

pip uninstall k00

@. jupyter で実行する場合

vscodeやコマンドプロンプト,terminalから実行する場合はよいのですが,jupyterやGoogleColabなどweb上では表示できずエラーになります.

そこで,jupyter用のturtle ColabTurtlePlus をインストールします.

> poetry add ColabTurtlePlus

さきほどのk00_turtle.py

import turtle

のところを

from ColabTurtlePlus import Turtle as turtle

としてください.

3. 今日の課題

で,このソースコードは,どんなプログラムでしょうか?

ざっくり言うと,新しくウインドウが立ち上がって,矢印とカメがそれぞれ線を描きながら動いて停止します.ちなみに,ウインドウが立ち上がったままですが,ウインドウ内のどこかでクリックすると,ウインドウが閉じます.

というわけで,今日の課題

(1)k00_turtle.pyのそれぞれの行で行われていることを調べて,ソースコードにそれぞれの行で行われていることをコメントアウトに追記せよ.

(2)正六角形を描画するモジュールk00_hexagon.pyを作成せよ.ただし,左半分は矢印で赤,右半分はカメで青で描くこと.for文もしくはwhile文などの繰り返し処理を用いること.自分で編集したソースコードのそれぞれの行で行われていることをコメントアウトに追加せよ.

(3)k00_pentagon.pyに正N角形を描画する関数NsidePolygon(n)を作成し,NsidePolygon関数を利用して正五角形を描け.ただし,関数NsidePolygon(n)n匹のカメを発生させ,それぞれのカメがそれぞれ各頂点に移動して一つの辺のみを描画することとする.繰り返し処理を利用してできるだけ行数を短くせよ.

(4)k00_pentagon.pyk00_invalid.pyにコピーし,NsidePolygon関数に描く線の色名を引数colorとして指定してできるようにせよ.その上で正五角形を描け.pencolor('yellow')で黄色に,pencolor('blue')で青色の線を指定できる.ただし,適当な文字列を色名とするとエラーが出てプログラムが止まるであろう.適当な色名が指定されたときにはpencolor('black')で線を黒色に指定しなおすように,例外処理を加えよ.

(5) パッケージk00の下にさらにディレクトリk00funcsを作り,その下にk00_func.pyを作成せよ.(4)の関数NsidePolygon関数をk00_func.pyに書き,k00_octagon.pyfrom k00.k00funcs import k00_funcとして読み込んだ上で,NsidePolygon関数を利用して,正八角形を描け.

最終的に今回 poetry new k00 で作成したディレクトリの構造は以下のようになる.

k00
├── README.md
├── k00
│   ├── __init__.py
│   ├── k00_hexagon.py
│   ├── k00_invalid.py
│   ├── k00_octagon.py
│   ├── k00_pentagon.py
│   ├── k00_turtle.py
│   └── k00funcs
│       └── k00_func.py
├── pyproject.toml
└── tests
    └── __init__.py

課題は,

  • LACSの課題から,パッケージk00wheelにしたもの,と,描画されたウィンドウのスクリーンショットを提出してください.
  • 初めての提出作業は5月8日正午までに必ず行ってください. 課題提出があると,TAや私がそれを採点し,改善点があればコメントを残します.
  • コメントを踏まえて再度提出し,10点満点を目指し何度でも提出を受付ます.課題k00の最終期限は5月22日正午までを目安とします.
  • 今後の課題も,基本的には,初めての提出の期限を2週間後,最終期限を4週間後とします.

@1. 便利なvscode用コメントアウト 「# %%

ソースコードは基本的には,python **.pyだと最初の行から最後の行まですべての工程を行います.

コードのそれぞれの行で何を行っているか調べるなら,もしくは新しく文を書いて,その動きを確かめたいのなら,pythonだとIPythonが有名です.IPythonは,JupyterやGoogle Colabを動かしているプログラムです.

ターミナルやコマンドプロンプトで,ipythonと打つと,

(.venv) kotaro@calvados psp2 % ARM❯ ipython                                [04/12 21:31]
Python 3.10.0 (default, Jan 13 2022, 14:22:16) [Clang 13.0.0 (clang-1300.0.29.30)]
Type 'copyright', 'credits' or 'license' for more information
IPython 8.2.0 -- An enhanced Interactive Python. Type '?' for help.
Unable to automatically import mitosheet

In [1]:

のように,インタラクティブモードが立ち上がります.

In [1]: x = 10

In [2]: print(x)
10

のように,JupyterやGoogle Colabと何ら変わりません.

ただ,問題なのは,このインタラクティブモードで書いたソースコードは保存されないということ.JupyterやGoogle Colabで書いたものも,基本的には「jupyter notebook」(拡張子は .ipynb)であり,pythonのソースコード(.py)ではないということです.

JupyterやGoogle Colabではメニューから,JupyterNotebook(.ipynb)からpythonソースコード(.py)に変換することは可能ですが,

僕らが今欲しいのは,書いているpythonソースコードをブロック毎に動きを確かめたい.そこで,vscodeの「# %%」です.

実は,

「Run Cell | Run Below | Debug Cell」
------------------------------------------
# %%

は,vscode上で,pythonソースコードを簡単にインタラクティブモードで動かすコメントアウトになっているのです.凄い便利!!

# %%」から次の「# %%」までが,IPythonの「セル」です.

  • 「Run Cell」は,セルを実行する
  • 「Run Below」は,以下のすべてのセルを実行する
  • 「Debug Cell」は,セルをデバグする.(デバグについては後日)

また,このように書かれたpythonソースコード.pyは,Run CellRun Belowで隣に立ち上がったJupyterみたいなタブでsaveをすることでJupyter Notebook .ipynbに保存できます.ターミナルでjupyter notebookと打つとウェブブラウザが立ち上がり,

Jupyter Notebook

ここで,.ipynbを選択すると,jupyter Notebookを実行できます.

Jupter Notebookで開く

ちなみに,Jupyter notebookでの編集は,.ipynbには反映されますが,元の.pyには反映されないので注意.

@2. 繰り返し処理

python言語の繰り返し処理は,

処理文A
for 仮変数X in コンテナP:
    仮変数Xを利用できる処理文B
    仮変数Xを利用できる処理文C
処理文D

の形で処理文Bと処理文Cの繰り返しを実現します.

仮変数Xは繰り返しのたびに,コンテナPの先頭から1つだけ要素が代入されます.コンテナPの最後の要素が代入されたら最後の繰り返しとなり,繰り返しブロックを抜けます.

コンテナPがリストの場合,

L = [1, 10, 'blue', 3.14]
for i in L:
    print(i)
for j in L:
    print('i')

は,どのように出力されるでしょうか?やってみましょう.

コンテナPが文字列の場合は,どうなるでしょう?

S = 'Programing'
for i in S:
    print(i)

コンテナPが辞書の場合は,どうなるでしょう?

D = {'a':1, 'b':10, 'c':'blue', 'd':3.14}
for i in D:
    print(i)
for j in D:
    print(D[j])

コンテナPは,スライスでも構いません.

S = 'Programing'
for i in S[1:]:
    print(i)

コンテナPは,その場でrangeを利用することもできます.

for i in range(5):
    print(i)

enumerateも覚えておくとよいでしょう.何が行われるか試してみてください.

S = 'Programing'
for i,j in enumerate(S):
    print(f'{i}:{j}')

@3. モジュールおよび関数

関数は,次のような書き方で宣言でき,同一のファイル内であれば,宣言したあとに呼び出せます.

def 関数名(仮引数...):
    仮引数を利用できる処理文
    return 出力変数

y = 関数名(x)

別のファイルに関数が書かれている場合,呼び出し側のファイルでimportします.関数が書かれた.pyファイル,またはそのファイル名の.pyを除いた文字列をモジュールと呼びます.

importについては,こちらを参考にしてください.

呼び出し側で,関数を呼び出すときは,以下のようにします.

from forder1.forder2 import module
y = module.func(x)

のように呼び出し側のファイルでは,単に関数名ではなく,モジュール.関数名で呼び出します.

import module as modのように別名を指定すれば,

y = mod.func(x)

のように別名を使うこともできます.

また,モジュールがソースコードと同じフォルダにある場合は, from を省略できます.

また,ソースコードと同じフォルダの下でなくとも,pippoetrycondaで入れたパッケージやモジュールはimportできます.

混乱を生むが許されている他のimport方法

実は他のimport方法があります.

  1. モジュールをfromにして,関数をimport

    呼び出し側のソースコードでも,単に関数名になります. 関数名が他でも使われている場合に混乱します.

    from フォルダ.モジュール import func
    
    y = func(x)
    
  2. 1でさらにワイルドカード*で関数をimport

    importは,「,」で区切って複数のものをimportできますが, あるモジュール内に存在するすべての関数をimportする場合, 以下のように書くことができます.

    from モジュールA import *
    from モジュールB import *
    
    y = func(x)
    

    しかし,この場合,funcという関数が,どちらのモジュールに書かれているものなのか,ソースコードから読み取れません.どちらのモジュールにもfuncが存在する場合,後ろにあるモジュールBのfuncが利用され,混乱の元になります.