# キレイなプログラムを書けましょう
- https://testdriven.io/blog/clean-code-python/
## キレイなコードは何だ?
- コードを読みやすくなって修正しやすくなるためのいくつのルール
:::info
コード書くのは簡単ですが、キレイなコードを書くのは非常に難しい
:::
## キレイなコードの重要性
- (他の人に対しても未来の自分に対しても)分かりやすい
- 迷わなく効率的にコードを書ける
- デバッグや修正が易くなる
## コードスタンダード(Code Standards)
- コードをどうやって書くのルール
- 強制力がないが、これを守るだけでコードキレイになる
### PEP 8 (Python Enhancement Proposal)
- https://peps.python.org/pep-0008/
- Pythonが最も使われているコードスタンダード
#### 命名の規則
- クラスは頭大文字のCamelCase(`MyClass`)
- 変数と関数は全部小文字のsnake_case(`first_name`、`quick_sort()`)
- 定数は全部大文字のSNAKE_CASE(`PI = 3.1415`)
- モジュールは全部小文字のsnake_case、なるべう短くにする(`numpy`)
- single quote(`''`)とdouble quote(`""`)のどちらでも良いですが、決めたら変えない
#### 一行の規則
- インデントの広さはspace四つ
- 一行は最長79文字
- 一行で複数の挙動をしない(`for i in range(1, 100): print(i*i)`→forとprintを同一行に書く)
- トップレベルの関数やクラスの上下が改行二回
- クラス内の関数は改行一回
```python=
class Student:
def __init__:
#...
def setName:
#...
def getName:
#...
class Teacher:
def __init__:
#...
func main():
student = Student()
teacher = Teacher()
return
```
#### スペースの規則
- `[]`と`{}`は余剰のスペースを入れない(`[ 1, 2, 3 ]`→`[1, 2, 3]`)
- 行の最後にスペースを入れない(`if i == 10: `→`if i == 10:`)
- 演算子(`=, +, -, etc.`)の周辺にスペースを入れる(`a == b`, `a != b`)
## The Zen of Python
- 禅
- 全てをわかるとあなたもPythonの達人
翻訳:[@IshitaTakeshi](https://qiita.com/IshitaTakeshi/items/e4145921c8dbf7ba57ef)
詳しい説明もあります。
:::spoiler
```
The Zen of Python, by Tim Peters
Beautiful is better than ugly.
醜いより美しいほうがいい。
Explicit is better than implicit.
暗示するより明示するほうがいい。
Simple is better than complex.
複雑であるよりは平易であるほうがいい。
Complex is better than complicated.
それでも、込み入っているよりは複雑であるほうがまし。
Flat is better than nested.
ネストは浅いほうがいい。
Sparse is better than dense.
密集しているよりは隙間があるほうがいい。
Readability counts.
読みやすいことは善である。
Special cases aren't special enough to break the rules.
特殊であることはルールを破る理由にならない。
Although practicality beats purity.
しかし、実用性を求めると純粋さが失われることがある。
Errors should never pass silently.
エラーは隠すな、無視するな。
Unless explicitly silenced.
ただし、わざと隠されているのなら見逃せ。
In the face of ambiguity, refuse the temptation to guess.
曖昧なものに出逢ったら、その意味を適当に推測してはいけない。
There should be one-- and preferably only one --obvious way to do it.
何かいいやり方があるはずだ。誰が見ても明らかな、たったひとつのやり方が。
Although that way may not be obvious at first unless you're Dutch.
そのやり方は一目見ただけではわかりにくいかもしれない。オランダ人にだけわかりやすいなんてこともあるかもしれない。
Now is better than never.
ずっとやらないでいるよりは、今やれ。
Although never is often better than *right* now.
でも、今"すぐ"にやるよりはやらないほうがマシなことが多い。
If the implementation is hard to explain, it's a bad idea.
コードの内容を説明するのが難しいのなら、それは悪い実装である。
If the implementation is easy to explain, it may be a good idea.
コードの内容を容易に説明できるのなら、おそらくそれはよい実装である。
Namespaces are one honking great idea -- let's do more of those!
名前空間は優れたアイデアであるため、積極的に利用すべきである。
```
:::
## 変数名の原則
1. 名詞にする
2. 名前をその変数の意味を表す
3. 読める名前にする
4. 略語にしない
5. 同じ単語を使う
6. 数字をそのまま使わない
7. 日本語にしない
```python=
# 2
c = 5
d = 12
city_counter = 5
elapsed_time_in_days = 12
# 3
genyyyymmddhhmmss = datetime.strptime('04/27/95 07:14:22', '%m/%d/%y %H:%M:%S')
generation_datetime = datetime.strptime('04/27/95 07:14:22', '%m/%d/%y %H:%M:%S')
# 4
fna = 'Bob'
cre_tmstp = 1621535852
first_name = 'Bob'
creation_timestamp = 1621535852
# 5
client_first_name = 'Bob'
customer_last_name = 'Smith'
client_first_name = 'Bob'
client_last_name = 'Smith'
# 6
def roll():
return random.randint(0, 36) # what is 36 supposed to represent?
ROULETTE_POCKET_COUNT = 36
def roll():
return random.randint(0, ROULETTE_POCKET_COUNT)
```
## 関数の原則
1. 動詞にする
2. 似ているようなことをする関数を同じの単語を使う
3. なるべく短くにする
4. 一つの関数は一つのことしかしない
5. 引数を最小限にする
```python=
# 2
def get_name(): pass
def fetch_age(): pass
def get_name(): pass
def get_age(): pass
# 4
def fetch_and_display_personnel():
data = # ...
for person in data:
print(person)
def fetch_personnel():
return # ...
def display_personnel(data):
for person in data:
print(person)
# 5
def render_blog_post(title, author, created_timestamp, updated_timestamp, content):
# ...
render_blog_post("Clean code", "Nik Tomazic", 1622148362, 1622148362, "...")
class BlogPost:
def __init__(self, title, author, created_timestamp, updated_timestamp, content):
self.title = title
self.author = author
self.created_timestamp = created_timestamp
self.updated_timestamp = updated_timestamp
self.content = content
blog_post1 = BlogPost("Clean code", "Nik Tomazic", 1622148362, 1622148362, "...")
def render_blog_post(blog_post):
# ...
render_blog_post(blog_post1)
```