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()  


もしディスクリプタを使えば、より自然に getter, setter を表現できます。 Effective Python の 「4 章 メタクラスと属性」で説明されています。

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

# 新しいオブジェクト, identity を生成しない。    
obj.noun()
# 新しいオブジェクト, identity を生成する。  
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

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

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

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

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 新人プログラマーに読ませて 欲しいネーミングの大切さ

オブジェクトの集まりを表現する変数名

特に list を複数形の名詞で表現した時に for 文で要素を取り出した時に困ります。 例えば members とすると for 文では for member in members となり s がついてるか、ついてないかだけの違いしかでなくて読みづらい。

◯ 集合を表現する変数名

たぶん、これが一番いいと思う。

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

ハンガリアン記法

もし無いならハンガリアン記法で妥協 orz

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


あるいは集合を表す汎用的な表現として container があります。 set, tuple, list, dict などは container と総称することがあります。 でも、 member_container ってのは、ちょっと変な感じがします。

◯ 複数形の s をつける, for 文で回すときは接頭辞に next をつける。

接頭辞に next をつけてしまう。複数形の s を外すだけだとわかりづらいので

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

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


for 文はじつは、イテレータで、このように実行されている。

def average_age(members):
  # 初期値
  sum_member_age = 0
  while True:
    try:
      next_member = next(members)
    except StopIteration:
      break
  sum_member_age = sum_member_age + next_member[AGE]

Python のイテレータ


イテレータで next 取り出したものは、next じゃなくて current やないかなとも思ったりもするけど。今度もう少し考えてみよう。

三人称の s, 複数形の s は、日本人にとって "は" と "わ" と同じくらい間違えると違和感がある。 このへんのコーディングをするときの温度感とかどうなのかなーと思ったりする。next という接頭辞さえいらないのかな...

英語の母語話者にとって複数形の s の有無って、大きな違いと感じるのだろうか.. もしそうなら諦めるか.. 英語圏のコードを意識しながら読んでみよう..

sorted 関数と list.sort メソッド

◯ sorted 関数

sorted(iterable) という、この組み込み関数の命名は、若干命名が異質です。というのも過去分詞の形容詞的用法になっています。

# 使い方
sorted(iterable)

# 日本語で表現するなら
ソートされた(iterable)


おそらくイメージ的には

# これを
sorted_list = make_sorted_list(list_)

# 省略した感じ
sorted_list = sorted(list_)

◯ list.sort メソッド

このように書いた理由は、おそらく list.sort メソッドとの名前がかぶるのを避けるためだと思われます。

list_object.sort()


また、命名規則だけでなく、動作も異なり list.sort メソッドは sorted 関数と異なり計算した結果を返しません。

なぜ list.sort() はソートされたリストを返さないのですか?
パフォーマンスが問題となる状況では、ソートするためだけにリストのコピーを作るのは無駄が多いです。そこで、 list.sort() はインプレースにリストをソートします。

このことを忘れないため、この関数はソートされたリストを返しません。こうすることで、ソートされたコピーが必要で、ソートされていないものも残しておきたいときに、うっかり上書きしてしまうようなことがなくなります。

命名規則についてもう少し...

# やたら長い関数名
make_done_return_value(obj)

# こんな感じで "逃げる"
# ただし、一般的な書き方ではない。
# done された obj みたいな意味合いで
done(obj)


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


f:id:domodomodomo:20171117002534j:plain ソフトウェア工学 | プログラミング作法



命名方法が出現する。

return_value = done(parameter)


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