こんな人にオススメ
pythonのdef
ってあるけど、あれって何?関数にするとかなんとからしいけど使い方とかメリットがわからん!
ということで、pythonのdef
の役割とメリットなどを解説する。既に本ブログでは腐るほどのdef
を使用してきたが、改まってこのようにしてdef
について書くのは初めて。
かくいう執筆者自身も今回の疑問のようにそもそもdefって何なのかとかどういうメリットがあるのかといったことがわからずにずっと使ってこなかった。
しかし、一旦使うと結構便利なもので、使い始めてからほとんど全ての研究.py
ファイルに活用している。
python環境は以下。
- Python 3.9.4
- numpy 1.20.3
def
を使うメリット
まずはそもそもdef
を使うメリットをお話しする。def
を使わなくてもコードは書けるし実際にプログラムは動く。じゃあなんでわざわざ小難しいdef
を使わないといけないのか。
それは楽ができるから(と思っている)。
def
で関数を定義
import numpy as np # defで関数を定義 # a, b, cはex関数の引数 def cal(a, b, c): """3つの引数より複雑な計算を行う defでの関数定義の練習計算 Parameters ---------- a : int or float 引数1 b : int or float 引数2 c : int or float 引数3 Returns ------- float 計算結果 """ # 以下cal1, cal2, cal3, ansは処理 cal1 = a ** 2 + b ** 2 cal2 = np.sqrt(cal1) cal3 = cal2 + 1 ans = cal3 * c # returnで値を返すことができる return ans
そもそもdef
は上のコードのような感じで、def (関数名)((引数)):
という構成で記述する。で、インデントをつけた後にいつも通りコードを書く。
その下についている"""
で書かれた部分はdocstringといって、書いた関数がどのような内容でどんな引数や返り値(戻り値)を返すのかなどを記述する。
なお、執筆者はVScodeの「Python Docstring Generator」で自動生成している。VScodeの拡張機能については以下参照。
[card2 id="ID"]
def
を使うメリット
lst1 = [] for i in range(3): a = i b = i ** 2 c = i + 2 # 予め定義しておくとコードが短縮できる # calは戻り値(返り値)があるので代入して値を使用できる ans = cal(a=a, b=b, c=c) lst1.append(ans) print(lst1) # [2.0, 7.242640687119285, 21.88854381999832]
ではdef
を使うことのメリットについてだが、例えば先程のcal
関数では複雑な処理を行なっている。しかし、一度関数を定義しておくと上のコードのようにコードを短縮して書くことができる。
また、cal
関数に書かれた内容を再度使用する時にも、予め関数化しておくとその関数を呼び出すだけで使用できるので楽。
a = 10 b = 3 c = 1 # 再度使用する時にコードが短くて済む ans = cal(a=a, b=b, c=c) ans2 = cal(a=a, b=b, c=c) * 2 print(ans) # 11.44030650891055 print(ans2) # 22.8806130178211
返り値(戻り値)がない場合
def no_return(a, b, c): """3つの引数を出力 Parameters ---------- a : list 引数1 b : int 引数2 c : str 引数3 """ # 返り値はなくてもいい # 返り値がない場合に関数の結果を代入するとNoneになる print(f"a: {a}, b: {b}, c: {c}")
先程のcal
関数だとreturn
として返り値(戻り値)が設定されていたが、return
がない場合(返り値がない)もある。上の例だとreturn
の代わりにprint
が存在している。
この場合にこの関数を使用すると関数内にprint
があるので、関数を使用するだけでprint
文が出力される。
# 代入するだけでも関数を使用するのでprintされる ans = no_return(a=[1, 2, 3], b=1, c='str') # a: [1, 2, 3], b: 1, c: str
で、このno_return
関数を変数に代入すると何が代入されるのかというとNone
が返される。
# 単発で使ってもprintされる no_return(a=[1, 2, 3], b=1, c='str') # a: [1, 2, 3], b: 1, c: str
返り値がない場合に変数を代入してもエラーが出ることははないが、それでも誤解を与えかねない気がするので明確に戻り値があるかどうかは分けたほうがいいだろう。
引数指定時の=
と引数の順番
上で色々と関数を作成して挙動を調べていたが、ここでは引数を入れる時の挙動について解説する。
=
はあってもなくてもいい
# defで関数を定義 # a, b, cはex関数の匹数 def add(a, b, c): """3つの引数より簡単な計算を行う Parameters ---------- a : int or float 引数1 b : int or float 引数2 c : int or float 引数3 Returns ------- float 計算結果 """ ans = a + (- b) + c return ans
add
関数はシンプルに引数を足していく関数。全ての引数を指定して値を入れるともちろん正しく計算されるので大丈夫。
# 全ての引数に=をつけるとその引数に代入される ans = add(a=1, b=2, c=3) print(ans) # 2
また、引数を指定している場合は関数を定義したときの順番で書かなくても正しく計算される。どの引数にどの値を入れるのかが指定されているから。
# 引数の順番を変えることも可能 ans = add(b=2, a=1, c=3) print(ans) # 2
=
をつけなくても正しく動くけど、その時は関数を定義した順番で引数に代入されていく。add
関数でいうとa
, b
, c
の順番に強制的に値が代入されていく。
# =をつけなくてもいいが、その時は定義時の引数の順番で代入される ans = add(1, 2, 3) print(ans) # 2
代入する値がlist
やtuple
でまとまっているならアンパック(展開)して代入することも可能。アンパックは*
を使って行う。
# 引数指定はアンパック(展開)でも可能 lst = [1, 2, 3] ans = add(*lst) print(ans) # 2
=
の省略と引数指定
# =の前なら引数の指定はなしでもいい ans = add(1, b=2, c=3) print(ans) # 2
さっきは全ての引数に対して=
をつけるか全てにつけないかの0, 100理論だった。上の例では初めの匹数aだけは引数指定なしでその他の引数指定をしている。この場合でも正しく計算される。
また、先程同様、引数指定をしていると順番を入れ替えても大丈夫。
# 引数名入りなら順番を変更してもいい ans = add(1, c=3, b=2) print(ans) # 2
しかし、引数指定をした後で引数指定をしない引数を入れるのはエラー。値をどの引数に入れたらいいのかがわからなくなるから。今回はa
だけ指定したが、この場合はb
とc
にそれぞれ2
と3
のどちらを入れたらいいのかがわからない。
# 引数指定したあとは引数指定なしは不可 ans = add(a=1, 2, 3) # ans = add(a=1, 2, 3) # ^ # SyntaxError: positional argument follows keyword argument
引数の数は合わせないといけない
# 引数が足りない ans = add(1, 2) # ans = add(1, 2) # TypeError: add() missing 1 required positional argument: 'c'
add
関数にはa
, b
, c
の合計3つの引数が存在している。なので、引数が足りないとエラーになる。これは引数が多い場合も同様。
# 引数が多い ans = add(1, 2, 3, 4) # ans = add(1, 2, 3, 4) # TypeError: add() takes 3 positional arguments but 4 were given
また、勝手に引数を作成するのもエラー。d
なんて引数はないということだ。
# 引数を勝手に作ってはいけない ans = add(a=1, b=2, c=3, d=10) # ans = add(a=1, b=2, c=3, d=10) # TypeError: add() got an unexpected keyword argument 'd'
引数のデフォルトの値を設定
関数っていうのは同じ処理・コードを繰り返し使うときに、処理を予め定義しておくと楽というメリットがあることは上に書いた通り。しかし、引数も予め決まった値が入ることが高い場合はどうだろう。
具体的には、ある引数は基本10
だけどあるタイミングでは1
にしたい時があるとか。def
では引数のデフォルト値を設定することができるのでこの問題は解決する。
デフォルト値があると引数は省略可能
# default関数は引数cのデフォルト値が10 def default(a, b, c=10): """3つの引数を出力 Parameters ---------- a : int 引数1 b : int 引数2 c : int, optional 引数3, by default 10 """ print(f"a: {a}, b: {b}, c: {c}")
default
関数は引数としてa
, b
, c
を持つ関数だが、引数のうちc
に関してはデフォルト値として10
が指定されている。docstringにもこの旨を記載する必要がある。
c
の値がデフォルトで入っているのでわざわざ指定しなくても大丈夫。もちろんこの時のc
の値は10
。
# cはデフォルト値があるので省略可能 default(a=1, b=2) # a: 1, b: 2, c: 10
c
の値はあくまでもデフォルト値なので上書きすることも可能。以下の例ではc
の値を1
に上書きした。上書きなのでc
デフォルト値の10
ではなく新規の1
で計算される。
# cを上書き default(a=1, b=2, c=1) # a: 1, b: 2, c: 1
もちろんデフォルト値ではない引数を省略することはできない。default
関数はc
だけデフォルト値が設定されているのでb
は省略できない。だって値がわからなくなるもん。
# デフォルト値がない引数は省略できない default(a=1) # default(a=1) # TypeError: default() missing 1 required positional argument: 'b'
引数をbool
にすると便利
# 引数にboolを持ってくるとしたい処理に対して便利に対応できる def default_tf(check=False): """checkの真偽で出力内容を変更する Parameters ---------- check : bool, optional チェックを入れるか否か, by default False """ if check: # check = Trueの時 print('check入りまーす') else: print('何もないよ')
個人的に便利な使いかたとして挙げているデフォルト値の使い方がbool
を入れるというもの。bool
というのはTrue
とFalse
のことで、if
で条件分岐する際にコードを短く書くことができる。
# 引数指定を改行しておけばすぐに切り替えられる default_tf( check=True ) # check入りまーす # デフォルトがFalseなので、引数を指定しないとFalse時の出力となる default_tf( # check=True ) # 何もないよ
じゃあどんな時に使えそうかということだが、執筆者自身はplotlyでグラフを作った時にそのグラフを表示するかどうか、保存するかどうかの判定に使っている。
基本的にはグラフを表示しながらちゃんと目的通りのグラフができているかをグラフ表示の引数をTreu
で確認しつつ、保存する時には保存するとして保存の引数をTrue
にする。
大量にグラフを保存したい時は表示をFalse
にして保存をTrue
にすればいちいち表示しなくても勝手に保存されていく。デフォルト値があるとTrueからFalse
に書き換えなくてもコメントアウトだけで事足りるから便利。
可変長引数*args
で任意の数の引数を使用
これまでは引数の数が3つとかで規定の数だった。しかし、数が不明瞭な場合があるかもしれない。ある状況では引数が3個だが、別の状況だと10個になるとか。
list
とかにまとめて引数として入れて処理することも可能だが、ここでは可変長引数*args
というものを使用して、任意の数の引数を直接、関数に入力する方法を解説する。
ちなみにargs
= argumentsの略で「可変長tuple」というらしい。tuple
と名づいているのは、受け取った任意の数の引数がtuple
に入れられるから。
可変長引数*args
で任意の数の引数を指定
# 可変長引数は慣例的にargsを使用する def args_def(*args): print(f"args: {args}") print(f"type(args): {type(args)}")
可変長引数を使用するには*
を使用する。実は「args」という文字にこだわる必要はなく、*name
でも*hikisu
でも大丈夫。しかし慣例的に*args
になっているのでここでもそれに倣う。
上のargs_def
関数では入力されたargs
とその型を出力する関数。実際に1
, 2
, 3
を入れてみる。入力時には直接、値を入れるだけでいい。便利。
# 好きな数の引数を入れられる args_def(1, 2, 3) # args: (1, 2, 3) # type(args): <class 'tuple'> args_def(10, 20, 3, 'moji') # args: (10, 20, 3, 'moji') # type(args): <class 'tuple'>
args
に入れられた引数達はtuple
にまとめられていることがわかる。tuple
にまとめられるのでfor
ループで1要素ずつ取り出すことが可能。
# 可変長引数はtupleで入るので、そのままforに使える def args_def_for(*args): for num, arg in enumerate(args): print(f"args[{num}]: {arg}") args_def_for('1', [1, 2, 3], True, None) # args[0]: 1 # args[1]: [1, 2, 3] # args[2]: True # args[3]: None
*args
と通常の引数を併用
def args_def_other(*args, a, b, c=10): print(f"args: {args}") print(f"a: {a}") print(f"b: {b}") print(f"c: {c}") print(f"type(args): {type(args)}") print(f"type(a): {type(a)}") print(f"type(b): {type(b)}") print(f"type(c): {type(c)}")
可変長引数という特殊な引数を紹介したが、通常の引数と一緒に使えないのかというとそうではない。使える。以下の例だと、1
, 2
, 3
はargs
に、その他の引数は指定の引数に入れられる。
# 可変長ではない引数との併用も可能 args_def_other(1, 2, 3, a=10, b=20, c=30) # args: (1, 2, 3) # a: 10 # b: 20 # c: 30 # type(args): <class 'tuple'> # type(a): <class 'int'> # type(b): <class 'int'> # type(c): <class 'int'>
もちろんデフォルト値との併用も可能でargs_def_other
関数ではc
がデフォルトで値が決められているのでc
の指定を省略できる。
# デフォルト値のある引数との併用も可能 args_def_other(1, 2, 3, a=10, b=20) # args: (1, 2, 3) # a: 10 # b: 20 # c: 10 # type(args): <class 'tuple'> # type(a): <class 'int'> # type(b): <class 'int'> # type(c): <class 'int'>
ただし、引数の自動的な数合わせをしてくれるわけではない。どこからどこまでがargs
でどこからどこまでがa
, b
, c
なのかを指定する必要がある。
たとえデフォルト値のあるc
を指定してもエラーが出る。しっかりと指定しましょう。
# 省略したら勝手に数合わせをしてくれるわけではない args_def_other(1, 2, 3, 10) # args_def_other(1, 2, 3, 10) # TypeError: args_def_other() missing 2 required keyword-only arguments: 'a' and 'b' # cを入れても勝手に数合わせをしてくれないよう args_def_other(1, 2, 3, c=30) # args_def_other(1, 2, 3, c=30) # TypeError: args_def_other() missing 2 required keyword-only arguments: 'a' and 'b'
*args
を最後に持ってくる
def args_def_end(a, b, *args): print(f"a: {a}") print(f"b: {b}") print(f"args: {args}") print(f"type(a): {type(a)}") print(f"type(b): {type(b)}") print(f"type(args): {type(args)}")
先ほどまでは*args
を最初に持ってきたが、ここでは*args
を最後に持ってくる。まずは先程最後の引数指定のことを踏まえてa
, b
を引数名指定して、args
を直接書いてみた。エラー。
a
, b
で引数指定をしてしまったから、その後の値はどの引数かわからんよ状態。
# a, bを引数指定するとエラー args_def_end(a=1, b=2, 10, 20, 30) # args_def_end(a=1, b=2, 10, 20, 30) # ^ # SyntaxError: positional argument follows keyword argument
なるほど、ならargs=
と書けばいいじゃない。エラー。そんなんねーよと。
# argsを引数指定しようとすると引数名にそんなん無いと args_def_end(a=1, b=2, args=(10, 20, 30)) # args_def_end(a=1, b=2, args=(10, 20, 30)) # TypeError: args_def_end() got an unexpected keyword argument 'args'
ならばargsを展開してみる。エラー。そもそもの文法ミス判定。
# 展開して入れようとしてもエラー args_def_end(a=1, b=2, *args=(10, 20, 30)) # args_def_end(a=1, b=2, *args=(10, 20, 30)) # ^ # SyntaxError: invalid syntax
じゃあどうすればいいかというと、シンプルに全ての引数から引数指定を無くせばいい。でもこれはこれでわかりにくい。どこからどこまでがargs
なのかを目で追う必要がありそう。
# 引数指定をしないとOK args_def_end(1, 2, 10, 20, 30) # a: 1 # b: 2 # args: (10, 20, 30) # type(a): <class 'int'> # type(b): <class 'int'> # type(args): <class 'tuple'>
*args
を真ん中に持ってくる
def args_def_mid(a, *args, b): print(f"a: {a}") print(f"args: {args}") print(f"b: {b}") print(f"type(a): {type(a)}") print(f"type(args): {type(args)}") print(f"type(b): {type(b)}")
では*args
を真ん中に持ってきてみる。この場合では全ての引数を指定せずに入力するとエラー。b
が指定されていないとな。
# bは引数指定が必要 args_def_mid(1, 2, 3, 4) # args_def_mid(1, 2, 3, 4) # TypeError: args_def_mid() missing 1 required keyword-only argument: 'b'
この場合はb
を指定する必要がありそう。ややこしい。
# 引数指定をするとOK args_def_mid(1, 2, 3, b=4) # a: 1 # b: 4 # args: (2, 3) # type(a): <class 'int'> # type(b): <class 'int'> # type(args): <class 'tuple'>
可変長引数**kwargs
で任意の数の引数をdict
で使用
先ほどは任意の数の引数を直接使用できるという可変長引数*args
の話だった。ここでは*args
と対を成す**kwargs
を解説する。*
が増えると意味が全然違ってくる。
*args
では1
や’str’
といった単発の引数だったが、**kwargs
だとa=1
やb=2
といったセットでの引数を使用可能になる。要するにdict
っぽいってこと。
ちなみにkwargs
= keyword argumentsの略で「キーワード辞書」というらしい。まさしくdict
。
可変長引数**kwargs
で任意の数の引数をdict
で指定
# **とすると辞書型を受け付けるようになる def kwargs_def(**kwargs): print(f"kwargs: {kwargs}") print(f"type(kwargs): {type(kwargs)}")
**kwargs
とすると辞書型を受け付けるので、引数も辞書型が採用される。以下の例ではa
, b
, c
というkey
に1
, 2
, 10
というvalue
を入れてみた。
kwargs_def(a=1, b=2, c=10) # kwargs: {'a': 1, 'b': 2, 'c': 10} # type(kwargs): <class 'dict'>
辞書型なので**
での展開で引数を入れることも可能。
# dictの展開でも引数の指定が可能 dct = {'a': 1, 'b': 2, 'c': 10} kwargs_def(**dct) # kwargs: {'a': 1, 'b': 2, 'c': 10} # type(kwargs): <class 'dict'>
ただし、引数に数字を持ってくるのはエラー。文字列にした数字をdict
の展開で入れるのは大丈夫だが、dict
に入れても数字はエラー。
# 数字をkeyに持ってくることはできない kwargs_def(1=1, b=2, c=10) # kwargs_def(1=1, b=2, c=10) # ^ # SyntaxError: expression cannot contain assignment, perhaps you meant "=="? # 予めdictで文字列の数字を使用するとセーフ dct = {'1': 1, '0.1': 2, 'c': 10} kwargs_def(**dct) # kwargs: {'1': 1, '0.1': 2, 'c': 10} # type(kwargs): <class 'dict'> # 予めdictでも数字はエラー dct = {1: 1, '0.1': 2, 'c': 10} kwargs_def(**dct) # kwargs_def(**dct) # TypeError: keywords must be strings
**kwargs
を展開する
def kwargs_def_unpack(**kwargs): # f-stringでは{}内で展開出来ない # print(f"{*kwargs}") # # (*kwargs) # # ^ # # SyntaxError: f-string: can't use starred expression here # *で引数の展開が可能 print(*kwargs) # print(a=1, b=2, c=10)となるので**での展開はできない # print(**kwargs) # # TypeError: 'a' is an invalid keyword argument for print() # 辞書型なのでvaluesで値を取得可能 print(*kwargs.values()) # どちらも欲しい時はitems() print(*kwargs.items())
kwargs
を展開する方法はいくつかあるが、f-stringで展開することとprint
で**
の展開をするのはエラー。ただし、print
で*
の展開はセーフ。
シンプルに*
で展開するとkey
を、.values()
で展開するとvalue
を、.items()
で展開するとkey
とvalue
を取得可能。
kwargs_def_unpack(a=1, b=2, c=10) # a b c # 1 2 10 # ('a', 1) ('b', 2) ('c', 10)
**kwargs
を最後に持ってくる
def kwargs_def_end(A, B, **kwargs): print(f"A: {A}") print(f"B: {B}") print(f"kwargs: {kwargs}") print(f"type(A): {type(A)}") print(f"type(B): {type(B)}") print(f"type(kwargs): {type(kwargs)}")
*args
の時と同じように*、**kwargs
も最後に持ってきてみる。A
, B
を引数指定なしにして**kwargs
を引数指定ありにすると正常に動く。
kwargs_def_end(1, 2, a=1, b=0) # A: 1 # B: 2 # kwargs: {'a': 1, 'b': 0} # type(A): <class 'int'> # type(B): <class 'int'> # type(kwargs): <class 'dict'>
もちろんA
, B
の引数指定も可能。
# もちろん通常の引数の=指定も可能 kwargs_def_end(A=10, B=20, a=1, b=0, AA=0.1) # A: 10 # B: 20 # kwargs: {'a': 1, 'b': 0, 'AA': 0.1} # type(A): <class 'int'> # type(B): <class 'int'> # type(kwargs): <class 'dict'>
しかし、既に引数で指定されているA
, B
を**kwargs
で指定するのはエラー。
# 既に引数として存在している引数は可変長で入れることができない kwargs_def_end(1, 2, A=1, b=0) # kwargs_def_end(1, 2, A=1, b=0) # TypeError: kwargs_def_end() got multiple values for argument 'A'
**kwargs
は最後でないといけない
def kwargs_def_mid(A, **kwargs, B=1): print(f"A: {A}") print(f"kwargs: {kwargs}") print(f"B: {B}") print(f"type(A): {type(A)}") print(f"type(kwargs): {type(kwargs)}") print(f"type(B): {type(B)}") # def kwargs_def_mid(A, **kwargs, B=1): # ^ # SyntaxError: invalid syntax
kwargs
を真ん中に持ってこようとしたが、なんと真ん中に持ってくるだけでエラー。というのもkwargs
は書く際の順番的に最後らしい。
優先順位 | 引数の種類 |
1 | デフォルト値なしの引数 |
2 | *args |
3 | デフォルト値ありの引数 |
4 | **kwargs |
なので**kwargs
はどう足掻いても最後。
*args
と**kwargs
の組み合わせ
def kw_args(*args, **kwargs): print(f"args: {args}") print(f"kwargs: {kwargs}")
上で*args
と**kwargs
を解説したが、2つの組み合わせも許容される。順番は先ほどに従って*args
、**kwargs
の順番。args
はargs=
とできないから引数だけ記述、kwargs
はa=10
のように記述。
# 1, 2, 3がargs、a=10, b=20がkwargsに格納 kw_args(1, 2, 3, a=10, b=20) # args: (1, 2, 3) # kwargs: {'a': 10, 'b': 20}
args
、kwargs
のどちらか、もしくはどちらも何も入れないと、それぞれ空の配列として出力される。
# kwargsを省略するとkwargsには空のdictが生成 kw_args(1, 2, 3) # args: (1, 2, 3) # kwargs: {} # argsを省略するとargsには空のtupleが生成 kw_args(a=10, b=20) # args: () # kwargs: {'a': 10, 'b': 20} # args, kwargsどちらも省略するとどちらも空で生成 kw_args() # args: () # kwargs: {}
なお、優先順位よりkwargs
を先に持ってくることはできない。
# kwargsを先に書いて後からargsはエラー kw_args(a=1, 2, 3) # kw_args(a=1, 2, 3) # ^ # SyntaxError: positional argument follows keyword argument
複数return
を展開で代入
def multiple_return(a, b, c): return a, b, c
最後に今更感はあるが、複数のreturnを展開で変数へ代入する。複数の値をreturnした場合、戻り値はtupleへ格納されて出力される。
# 複数の返り値はtupleに入れられる ans = multiple_return(a=1, b=2, c=3) print(ans) # (1, 2, 3) print(type(ans)) # <class 'tuple'>
したがって、変数を複数個用意して代入することで展開の容量で返り値を代入することができる。
# 複数個の返り値をその数に合った個数の変数に代入 a, b, c = multiple_return(a=1, b=2, c=3) print(f"a: {a}, b: {b}, c: {c}") # a: 1, b: 2, c: 3
代入先の変数が足りていないとエラーとなるが、変数を可変長にするとエラーを回避できる。
# 数が足りていないとエラー # a, b = multiple_return(a=1, b=2, c=3) # # a, b = multiple_return(a=1, b=2, c=3) # # ValueError: too many values to unpack (expected 2) # 代入先の変数を可変長にすると残りの返り値を代入可能 a, *b = multiple_return(a=1, b=2, c=3) print(f"a: {a}, b: {b}") # a: 1, b: [2, 3]
なお、可変長は最初に持ってきてもいい。この場合は後の引数の数で帳尻が合うように可変長の変数に代入される。
# 可変長は最後に持ってきてもいい *a, b = multiple_return(a=1, b=2, c=3) print(f"a: {a}, b: {b}") # a: [1, 2], b: 3
def
で関数化して楽に
今回はpythonのdefを使用して関数化を行った。関数化することで繰り返し同じコードを書く際に、コードを短縮することができる。さらに入力引数が増えた時も可変長引数を使用することで簡単に対応することができる。
また、別ファイルに関数をまとめて入れておくことで、色んなファイルで関数を一元管理できる。すなわち、あの関数どこだっけがなくなる。ただし、1つ編集したらその関数を使用しているファイルでも同様の編集をする危険性はあるが。
(関数を使って、)お前も楽にならないか?
関連記事
-
-
【pltテンプレート】matplotlib.pyplotのグラフ作成テンプレート
続きを見る
-
-
【plotlyテンプレート】plotlyのグラフ作成テンプレート
続きを見る
-
-
【辞書の結合】dictのマージ
続きを見る
-
-
【python&初級】のlistとかforとかifとかまとめ
続きを見る