それでは下記の記事の続きをやっていこう!
前回までは<関数編>ということで基本的な関数について体系的まとめました。
今回は<モジュール編>になります。一緒に勉強していこう🤓
Contents
import
✔️別の.pyで定義したモジュールを呼び出して使うことが出来る
✔️fromを付けることでモジュールを直接的に呼び出すことが出来る
✔️.pyの名前をimportしasで定義することで、後ろにモジュールを指定して呼び出すことがきる
✔️関数名に_(アンダースコア)を付けることで、呼び出し不可を明示
✔️importは.pyの先頭に記述(標準ライブラリ⇨サードパーティのライブラリ⇨自作のライブラリ⇨ローカルのライブラリの順で書く)
✔️別のスクリプトをimportした場合、そのスクリプトの内容をメモリに書き込むために一度実行される
1 2 3 4 5 6 7 8 9 10 11 12 |
<mymodule.py> ->様々な関数を定義 呼び出される側 myvariable = "This is global variable." def myfunc(): print("This is my function") def anotherfunc(): print("This is another function") # 関数名に_(アンダースコア)を付けることで、呼び出し不可を明示 def _anotherfunc2(): print("This function is not called") |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<myscript.py> ->mymodule.pyからモジュールを呼び出す側 # fromを付けることでモジュールを直接的に呼び出すことが出来る from mymodule import myfunc, myvariable, anotherfunc myfunc() # This is my function anotherfunc() # This is another function print(myvariable) # This is global variable. # .pyの名前をimportしasで定義することで、後ろにモジュールを指定して呼び出すことがきる import mymodule as mm mm.myfunc() # This is my function mm.anotherfunc() # This is another function print(mm.myvariable) # This is global variable. # mymoduleから呼び出すモジュールが多い場合は*を使う # ↑どのモジュールから呼び出されたか読み手が分からないため、非推奨 from mymodule import * |
sysモジュール
✔️sysモジュールをインポートし、自身が呼び出したい関数があるpathを記述
1 2 3 |
import sys sys.path.append("/Users/<username>/PycharmProjects/lecture/function/") import function_basic # function_basicは/function/にあるファイルを想定 |
Third party libraires & pip
✔️ライブラリ: 複数のパッケージをまとめてインストール可能にしたもの
✔️pyPI(The python Package Index): pythonのサードパーティライブラリやパッケージを管理しているレポジトリ
✔️pyPIから様々なライブラリをインストールすることが可能
✔️pip: pythonのパッケージ管理システム
✔️pyPIからパッケージをダウンロード&インストールすることが出来る
✔️pythonの標準ライブラリとして入っている
1 2 3 4 5 6 7 |
ex. pipを使ったnumpyライブラリのインストール (venv) [~/PycharmProjects/module] $ pip install numpy Collecting numpy Downloading numpy-1.20.3-cp38-cp38-macosx_10_9_x86_64.whl (16.0 MB) |████████████████████████████████| 16.0 MB 885 kB/s Installing collected packages: numpy Successfully installed numpy-1.20.3 |
✔️サードパーティライブラリであるnumpyを呼び出す時は一般的に”as np”とする
1 2 3 |
import numpy as np # numpyがインストールされているフォルダを確認 print(np.__file__) # /Users/<username>/PycharmProjects/module/venv/lib/python3.8/site-packages/numpy/__init__.py |
built in module(re: 正規表現RegEx)
✔️pythonが標準で組み込まれているモジュールのこと(pyhon Mudule Indexで適宜確認する)
1 2 3 4 5 6 7 8 9 10 |
import re email = "myemail@gmail.com" # emailに"@"があって、その後に文字列があり、.(ドット)が含まれているかを確認 matched = re.search('@\w+\.', email) if matched: print(matched) # <re.Match object; span=(7, 14), match='@gmail.'> print("Mached") else: print("Not found") |
metahcaracterの使い方
✔️条件を表す記号のことをmetacharacterという
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
import re # metacharacter # []: その文字が含まれるか print(re.search('[abc]', 'apple')) # <re.Match object; span=(0, 1), match='a'> print(re.search('[0-9]', '5')) # <re.Match object; span=(0, 1), match='5'> # ^: 最初の文字がマッチするか print(re.search('^[0-9]', 'test0')) # None # {}: n回リピートして確認 print(re.search('^[0-9]{4}', '2021/6/20')) # <re.Match object; span=(0, 4), match='2021'> # {n,m}: 最低n回、最高m回リピートで確認 print(re.search('^[0-9]{2,4}', '21/6/20')) # <re.Match object; span=(0, 2), match='21'> # $: 最後の文字 print(re.search('[0-9]{2}$', '2021/6/20')) # <re.Match object; span=(7, 9), match='20'> # *: 左のパターンを0回以上繰り返し、右の文字列が存在しているか print(re.search('a*b', 'b')) # <re.Match object; span=(0, 1), match='b'> print(re.search('a*b', 'aaaa')) # None print(re.search('a*b', 'aaaab')) # <re.Match object; span=(0, 5), match='aaaab'> # +: 左のパターンを1回以上繰り返し、右の文字列が存在しているか print(re.search('a+b', 'b')) # None print(re.search('a+b', 'ab')) # <re.Match object; span=(0, 2), match='ab'> # ?: 左のパターンを0回か1回繰り返す print(re.search('ab?c', 'ac')) # <re.Match object; span=(0, 2), match='ac'> print(re.search('ab?c', 'abc')) # <re.Match object; span=(0, 3), match='abc'> print(re.search('ab?c', 'bc')) # None print(re.search('ab?c', 'abbc')) # None # |: orを意味する print(re.search('abc|012', 'abc')) # <re.Match object; span=(0, 3), match='abc'> print(re.search('abc|012', '012')) # <re.Match object; span=(0, 3), match='012'> print(re.search('abc|012', '01')) # None # (): グループを表す print(re.search('te(s|x)t', 'test')) # <re.Match object; span=(0, 4), match='test'> print(re.search('te(s|x)t', 'teet')) # None # .: 任意の一文字 print(re.search('h.t', 'hit')) # <re.Match object; span=(0, 3), match='hit'> # \: エスケープ print(re.search('h\.t', 'h.t')) # <re.Match object; span=(0, 3), match='h.t'> # \w: [a-zA-Z0-9_] 全てのアルファベット&数字&アンダースコア print(re.search('h\wt', 'h9t')) # <re.Match object; span=(0, 3), match='h9t'> print(re.search('h\wt', 'h9zt')) # None |
input()で入力した生年月日(yyyy/mm/dd)のフォーマットが正しい形式になっているかcheck
1 2 3 4 5 6 7 8 9 10 11 12 13 |
# 課題:input()で入力した生年月日(yyyy/mm/dd)のフォーマットが # 正しい形式になっているかcheck import re correct_birth = "^(19|20)[0-9]{2}/([1-9]|1[0-2])/([1-9]|1[0-9]|2[0-9]|3[0-1])$" while True: your_birth = input("Please teach me your birth?(yyyy/mm/dd): ") check = re.search(correct_birth, your_birth) if check == None: print("Please input your correct birth") continue else: print(f"Your birth is {your_birth}") break |
input()で入力したemailアドレス(my_email.address@gmail.com)のフォーマットが正しい形式になっているかcheck
1 2 3 4 5 6 7 8 9 10 11 12 13 |
# 課題: input()で入力したemailアドレス(my_email.address@gmail.com)の # フォーマットが正しい形式になっているかcheck import re correct_email = "^(\w|.|-)+@(\w|.|-)+\.[a-zA-Z]{2,3}$" while True: your_emmail = input("Please teach me your email?: ") check = re.search(correct_email, your_emmail) if check == None: print("Please input your correct email") continue else: print(f"Your email is {your_emmail}") break |
built in module(time)
✔️timeモジュールを使うことで、プログラムの実行にかかった時間を計測することが出来る
1 2 3 4 5 6 7 8 9 10 11 |
# timeモジュール import time # .time(): 1970/1/1からの経過時間 秒数が表示(Unix時間) print(time.time()) # 1624200939.0049438 print(time.time()/(60*60*24*365)) # 51.50563182062731年経っている # 用途: プログラムの実行のどれくらい時間がかかったか計測 before = time.time() # 処理 after = time.time() print(after - before) # 9.5367431640625e-07 |
フィボナッチ数列を.time()モジュールを使って計測する例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
# ex.) フィボナッチ数列 from functools import lru_cache import time @lru_cache() # 一度計算したキャッシュを保持 def fib(n): if n < 2: return n else: return fib(n-1) + fib(n-2) before = time.time() print(fib(30)) # 832040 after = time.time() # :.2f 小数点第二位まで表示 print(f"recursive fibonacci took {after - before:.2f}sec.") # recursive fibonacci took 0.00sec. |
.ctime(), .localtime(), .sleep()の用法
✔️.sleepを使うことでコードを一時的に止めることが出来る
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# .ctime(): 現在のローカル時間を文字列で返す import time print(time.ctime()) # Mon Jun 21 22:48:00 2021 # .localtime(): 構造化されたデータで返す localtime = time.localtime() print(localtime) # time.struct_time(tm_year=2021, tm_mon=6, tm_mday=21, tm_hour=22, tm_min=52, tm_sec=19, tm_wday=0, tm_yday=172, tm_isdst=0) print(f"今の時刻は{localtime.tm_year}年{localtime.tm_mon}月{localtime.tm_mday}日{localtime.tm_hour}時{localtime.tm_min}分です") # 今の時刻は2021年6月21日23時4分です print("今の時刻は{0.tm_year}年{0.tm_mon}月{0.tm_mday}日{0.tm_hour}時{0.tm_min}分です".format(localtime)) # 今の時刻は2021年6月21日23時4分です # .sleep(secs): secs秒だけプログラムが待機する sec = 10 print(f"{sec}秒だけ待って下さい") time.sleep(sec) print(f"{sec}秒経ちました") |
timeモジュールを使って関数の処理時間を計測するタイマーを作る
✔️デコレータを使うことで関数処理計測のタイマーを作る
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
# timeモジュールを使って関数の処理時間を計測するタイマーを作る import time def timer(func): def inner(*args, **kwargs): before = time.time() func(*args, **kwargs) after = time.time() print(f"{func.__name__} took {after - before:.2f}sec!") return inner @timer def lazy_func(sec): print(f"I'm working so hard...") time.sleep(sec) print(f"I'm finally done!!") lazy_func(5) # I'm working so hard... I'm finally done!! lazy_func took 5.00sec! |
built in function
✔️インポートしなくてもPythonの標準に入っているfunctionのこと(built in functionは公式ドキュメントで確認)
dir()
✔️dir():このスクリプトがどんなメソッドにアクセス出来るのかを表示
✔️__builtins__に様々なfunctionが定義されている
1 2 3 4 5 6 7 |
# dir():このスクリプトが何にアクセス出来るのかを表示 print(dir()) # ['ArithmeticError', 'AssertionError', 'AttributeError',...] # __builtins__に様々なfunctionが定義されている print(dir(__builtins__)) # attributeのファンクション一覧が見れる # print()もbuilt in function の一つ # __file__, __doc__などのことをマジックファンクションという __builtins__.print("Hello World") # Hello World |
__name__と__main__
✔️別のスクリプトでimportされた時、実行されたくないコードはif __name__ == “__main__”:内に書く
1 2 3 4 5 6 7 8 9 10 11 12 |
<mymodule.py> def myfunc(): print("This is my function") def anotherfunc(): print("This is another function") if __name__ == "__main__": # 別のスクリプトでimportされた時、実行されたくないコードはここに書く myfunc() anotherfunc() myvariable = "This is global variable." |
1 2 3 |
<main.py> import mymodule print(__name__) #__main__ |
パッケージ(package)
✔️複数のpythonモジュールをディレクトリにまとめたもの
✔️.(ドット)を通すことで、モジュールにアクセスし、メソッドを呼び出すことが出来る
✔️ディレクトリに___init__.pyというファイルを作成し定義することで、そのディレクトリがパッケージとして認識される
✔️__init__.pyがないと『名前空間パッケージ』として認識される(Python3.3~)
(名前空間:下記の例でmodule1にmyfuncという関数が定義されていた場合、myfancはpackage.module1.myfunc(という名前空間)に属すると言える)
✔️特に理由がなければ__init__.pyを作成し通常のパッケージとするのが一般的
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<Command> [~/PycharmProjects/module] $ tree . ├── package ├──package_practice.py # 実行スクリプト └── module2.py [~/PycharmProjects/module/package] $ tree . ├── __init__.py ├── module1.py # 呼び出される.py └── module2.py # 呼び出される.py |
1 2 3 |
# <module1.py> def myfunc(): print("myfunc form module1 is called") |
1 2 3 4 5 6 |
# <module2.py> def myfunc(): print("myfunc form module2 is called") def myfunc2(): print("myfunc2 form module2 is called") |
__init__.py
✔️__init__.pyには初期化用コードを記述する(import時に実行される)
✔️__init__.pyにimport文を記述することで別のスクリプトで呼び出す時、モジュール名をスキップしてpackage.の後に関数やクラスにアクセスできる
✔️__init__.pyに__all__を定義することで、そのパッケージが”import*”で呼び出されると、全ての関数、クラスが定義される
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<module2のmyfuncにアクセスする方法を解説> [~/PycharmProjects/module] $ tree . ├── package └──package_practice.py [~/PycharmProjects/module/package] $ tree . ├── __init__.py ├── module1.py └── subpackage ├── __init__.py └── module2.py |
1 2 3 |
# <package/__init__.py> # module1.pyと同じdirの__init__.pyに以下を記述することでmodule.pyにアクセスしやすくする from package.subpackage.module2 import * |
1 2 3 4 5 |
# subpackage/__init__.py # myfuncのみをimportしたい場合(myfunc2はimportされない) from .module2 import * __all__ = ["myfunc"] |
1 2 3 4 5 |
# <package_practice.py> from package.subpackage import * myfunc() # myfunc form module2 is called myfunc2() # NameError: name 'myfunc2' is not defined |
相対import(realtive import)
✔️『.』: カレントディレクトリ、『..』: 親ディレクトリ
✔️from .<package/module> import XXX
✔️relative import の場合は、import <>ではなくfrom <> import<>の形をとる
1 2 3 4 5 6 7 8 9 10 11 12 13 |
[~/PycharmProjects/module] $ tree . ├── package └──package_practice.py [~/PycharmProjects/module/package] $ tree . ├── __init__.py ├── module1.py └── subpackage ├── __init__.py ├── module2.py └── module3.py |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
# <module3.py> def myfunc3(): print("This is myfunc3 from module3") # <module2.py> # module3.pyを呼び出してmyfunc3()を実行する from .module3 import myfunc3 def myfunc(): print("myfunc form module2 is called") def myfunc2(): print("myfunc2 form module2 is called") myfunc3() # <package_practice.py> import package.subpackage.module2 package.subpackage.module2.myfunc2() # myfunc2 form module2 is called This is myfunc3 from module3 |
これでpythonの文法<モジュール編>は終了です、いかがだったでしょうか?
これだけのボリュームがあるので、「pythonの文法なんて全部わかってるよっ」って方も、初めて知ったことや新しい発見があったんじゃないかなと思います。
コードを自分で書くには今回の内容はある程度頭に入れておきたいところですよね😎
次回は<オブジェクト指向編>についてまとめていきたいと思います☀️
今回はこの辺で、ばいばい👋
コメントを残す