Python の関数、メソッドの命名について

get を使わない。

原則、副作用の無く新たにオブジェクトを生成しない関数, メソッドは原則「名詞」を使うのが望まい。

# x
noun = obj.get_noun()  
# o
noun = obj.noun()  

感動した記事
Getter/Setterは悪だ。以上

もし get がダメなら、give ならどうだろう、とか考えてしまった笑 obj がすでに持っているオブジェクトを get しろというのは、文章としておかしい。ならば tell とか give ならと思った。

確かにそれっぽいけど。最終的に値を生成した関数やメソッドは、例えば create_new_user() みたいなのも create して tell が入ってるけど その tell は省略されてるから tell, give みたいなのは省略するのがいい感じかな..

そんなコードみたことないし obj.noun() が妥当そう..。

# 
noun = obj.give_noun()  

# me をつけるともっとそれらしい笑
noun = obj.tell_me_max()

# うーん笑
noun = obj.give_me_chocolate()  

noun と create, make, generate の使い分け

# 新しいオブジェクト, id を生成しない。    
obj.noun()
# 新しいオブジェクト, id を生成する。  
obj.create()
obj.make()
obj.generate()

でもこの流れでいくと create, make, generate をつけるのは
どうするべきか?

create と make と generate の使い分け

返り値をもつ関数名は、以下のいずれかになるかな。

# 引数と返り値で型が変わらない場合  
obj.make()
make(obj)

# 例
make_sorted_list(list_)
# 引数と返り値で型が変わる場合, 変換して生成されるもの  
obj.generate()

# 例えば tree から list を生成
tree.generate_list()
# 引数の値をもとに全く別のオブジェクトを作り出す場合  
obj.create()

# 年齢、学籍番号を元に学生を生成する
create_student(age, register_id)

# でも、普通ならコンストラクタ使うか
# ClassName(parameters)
Student(age, register_id) 

# そう考えると create とコンストラクタは等価な関係やな.. 

What is the difference between create and generate and make ? | HiNative

sorted 関数

実は結構この組み込み関数の命名は、若干異質です。

sorted_list = make_sorted_list(list_)

sorted_list = sorted(list_)

make とか使った、やたら長い関数名に出くわした時...

# やたら長い関数名

次の2つを考慮すると...

  1. make_done_return_value(parameter) だと関数名が長くなる。
  2. 副作用の無い関数, メソッドは原則「名詞」を使うのが望ましい。

f:id:domodomodomo:20171117002534j:plain

ソフトウェア工学 | プログラミング作法





return_value = done(parameter) という命名方法が出現する。

# Python の組み込み関数 sorted
sorted_list = sorted(list_obj)





Python で sorted という関数をみて思いました。
sorted_object = sorted(sortable_object)

返り値=過去分詞(引数)という関数の命名はよくあるやり方なのか。"はてな" で質問して見たら、swift とかで若干あったりするらしいが、多くはないというお話をいただく。
なぜ Python では sorted 関数を sorted と命名したのでしょうか?

変数名に引数名を含めるかどうか

考え方: フルネームで記載する。自明なものを削る。

関数名に引数名をつけ加えるのはひどく冗長な感じがする。

1. 同様の機能を持つものが他になければ

例1

def add_a_and_b(a, b):
  return a + b

2つのものを足すのは明らかななので

def add(a, b):
  return a + b

例2

def insert_int_to_list(lst, ii):
  lst.append(i)
# 不要
def insert(lst, i):
  lst.append(i)

今後の拡張を考えれば、たとえ直近で不要であっても事前に分けておくことも、ひとつの手かもれない。

2. 同様の機能を持つものが2つ以上あれば

Java と違って、メソッドのオーバーロードが無い。型宣言がないが故に逆に、型を意識してコーディングしないといけない。

def insert(dct, integer):
  ...

def insert(lst, integer):
  ...
# 関数名で分ける。
# 関数名を付けるのも異なるところまでで
def insert_to_list(lst, integer):
  ...

def insert_to_dct(dct, integer)
  ...

あるいは __init__ で場合分けとかも手かもしれない... https://stackoverflow.com/questions/6434482/python-function-overloading

codic 新人プログラマーに読ませて 欲しいネーミングの大切さ

for 文

list を複数形の名詞で表現した時に for 文で要素を取り出した時の命名に困ることがある。

例えば members とすると for 文では for member in members となり s がついてるか、ついてないかだけの違いしかでなくて読みづらい。for 文の中だけで スコープが小さいからこれでいいのかもしれない。

接頭辞に next をつけてしまう。e = next(members) なのだから。next じゃなくて current やろーとか思ったけど、確かに iterator 呼び出してる時点でそやな..。参考文献がええのやろか...。

def average_age(members):
    # 初期値
    sum_member_age = 0
    for next_member in members:
        sum_member_age = sum_member_age + next_member[2]

プログラミング歴ゼロの31歳ジャニヲタ、Pythonを学ぶ。超初心者向けの練習問題を5問紹介。 | Saya’s Blog

ただ自分の場合は for 文で回される方を複数形にしてしまう。例えば members なら member_list に。list_of_members, list members の方が適切なのかもしれないけど..

若干ハンガリアン記法になってしまうのでそこも引っかかる。ただ for 文の中で next という文言を考えたく無い.. というだけ。

def average_age(member_list):
    # 初期値
    sum_member_age = 0
    for member in member_list:
        sum_member_age = sum_member_age + member[2]

同じ型をもつ2つの引数、変数を使う関数、メソッド

変数名に a, b を使う。

operator overload などで self, other などの変数名を使うと属性名より self, other が長くなって何と何を比較しているかぱっと見不明瞭になる。

そもそも self, other 自体が何をさしているか、ぱっと見では不明瞭なので a, b にしたところで大きな impact はないか。

通常の規約みたいなのから外れてしまうので、ためらってしまうが。

    def __eq__(self, other):
        """Check rectangles are same, or not."""
        a, b = self, other
        return a.x1 == b.x1 \
            and a.y1 == b.y1 \
            and a.x2 == b.x2 \
            and a.y2 == b.y2
# 代入が行われれば返り値のある関数だと判断できる..
value = verb(param) 
-->