pythonのアンダーバーこれなんやねん


200407編集
230301編集(若干体裁整えました)

# はじめに
初心者丸出しの投稿ですみませんが同じように悩む初心者の方がいると信じて書きます。

# ちょいちょい出てくるアンダーバー
人のコードとか参考書とか読んでて，出てきませんか？
**このアンダーバーなんやねん！_みたいなアンダーバー**

```python:
H,W,_ = img.shape 
```
とか,まず

```python:
__main__
```
ってなんでアンダーバーいるねん。みたいな。
今回はそういうお話です。

今回も悩んで調べてる間に神記事見つけたのでそれをもとに肉付けしたり噛み砕いたりしてまとめようと思います。
悩み解決してくれた神記事はこちら

[「Pythonic色々」 Pythonのアンダースコア( _ )を使いこなそう!](https://medium.com/lsc-psd/pythonic%E8%89%B2%E3%80%85-python%E3%81%AE%E3%82%A2%E3%83%B3%E3%83%80%E3%83%BC%E3%82%B9%E3%82%B3%E3%82%A2-%E3%82%92%E4%BD%BF%E3%81%84%E3%81%93%E3%81%AA%E3%81%9D%E3%81%86-3c132842eeef)


# return値を無視するための `_`
```python:
H,W,_ = img.shape 
```
まさに最初に例に挙げたこれがそれにあたります。これがそれ．．．
これは.shapeの三番目のreturn値を無視するよーのアンダーバー
引用元が過不足説明してくださっているので引用
曰く
>Pythonはライブラリが沢山あって、関数をインポートして使う事が多いです。そういう時、もし関数からのreturn値が複数あって使わない部分があったらアンダースコアを使ってreturn値のメモリの占用をしないまま廃棄ができます

これで無駄なメモリを使わずにプログラムが組めるというわけなんですね。これが一番使いそう。

# 関数名についてる`_`
これ，場所によって４種類あるんだそうで．しかもPEP8コーディング規約で定義されてるとのこと。こんな定義があることも知らなかった。
[https://www.python.org/dev/peps/pep-0008/](https://www.python.org/dev/peps/pep-0008/)

PEP8>Naming Conventionに諸々詳しく書かれています。
それでは以下に4つまとめていきます


## `_function(x)`: 関数前に1つ
```python:
def _single_leading_underscore(x):
    return n
#weak "internal use" indicator. E.g. from M import *
#does not import objects whose names start with an underscore.
```
こう書くと，別のところからfrom func import*で呼ばれることがなくなるけど，classx._func()というようにclass内の関数としてはアンダーバー付きの関数を呼べるんだそうです。基本的に外部からの参照を受け付けない，ってものにはアンダーバーを1つつけるというのがpythonの習わしのようです。
これも読み込み対策ですかね。


## `function_(x)`： 関数後に1つ
```python:
def list_(x):
    return n
#used by convention to avoid conflicts with Python keyword
```
listやclassなどpythonの予約語をどーしても関数名に使いたい時には，後ろに１つ_つけてつかいわけろ，ということみたいです。

## `__function(x)`: クラス名の前に２つ
```python:
def __double_leading_underscore:
     return n
#when naming a class attribute, invokes name mangling 
#(inside class FooBar, __boo becomes _FooBar__boo; see below).
```
クラス内の関数の前にアンダーバー2つをつけると名前の**マングリング**を呼び出します。マングリングとは，名前修飾，の意で，要するに内部的に普通のものとして取り扱いませんよってことみたいです。
上の例に書いてるとおり，class FooBar内の変数\_\_booは，　FooBar.\_\_booでは呼び出せず，\_FooBar\_\_booとなるとしないと呼び出せないとのこと。
これも外部からのアクセスを受け付けませんよ対策の１つと言えるのではないかと思います。

## `__function__(x)`: 関数前後に2つずつ
```python:
def __double_leading_and_trailing_underscore__: 
    return n
# "magic" objects or attributes that live in user-controlled 
# namespaces. E.g. __init__, __import__ or __file__. Never invent 
# such names; only use them as documented.``
```

class内の関数の前後に2つずつアンダーバーをつけるとMagic Method(特殊メソッド)になります。特殊メソッドってなんやねーんって話ですが，オブジェクトの振る舞いを変更したり，クラスの性質にあった動きをさせたい時に使うものなんだそうです。
たとえば\_\_init\_\_は，渡された引数を使って．クラス定義で新しく作られたオブジェクトを初期化するものです。magic methodいっぱいありますよね。リスト載せてくださっていますがいっぱいです
[http://www.ops.dti.ne.jp/ironpython.beginner/method.html](http://www.ops.dti.ne.jp/ironpython.beginner/method.html)

## 数字を読みやすくする `_`
```python:
>>> 1_000_000
Out: 1000000
```
[参考](https://medium.com/lsc-psd/pythonic%E8%89%B2%E3%80%85-python%E3%81%AE%E3%82%A2%E3%83%B3%E3%83%80%E3%83%BC%E3%82%B9%E3%82%B3%E3%82%A2-%E3%82%92%E4%BD%BF%E3%81%84%E3%81%93%E3%81%AA%E3%81%9D%E3%81%86-3c132842eeef)曰く、
>Python 3.6以降では、数字を読みやすくする様にアンダースコアを数字内に加える事が出来ます。一般で使われてる3桁ごとにカンマを実現できます。

3桁ごとのカンマのかわりにアンダーバーを数値に打ち込んでもちゃんとした数値としてに認識してくれるみたいです。
桁の大きな数値入れ込みたい時は便利ですね。


## インタプリタで最後に表示された値を示す `_`
```python:
>>> 10
Out: 10
>>> _ * 3
Out: 30
>>> _ * 10
Out: 300
```
これは知らなかったのですが，pythonインタプリタを使っている時，アンダーバーで前に表示した数値を取得できるみたいです。

**追記0406**
コメントでご指摘いただいたのですが、\_を変数名として使うと、インタプリタで使用時も前に表示した数値ではなく変数に入れた値を表示するものとして働くみたいです。
詳しくはコメントを参照願います。
わかりやすく例を示してくださってます。ありがたい。


# じゃあ `if __name__ == '__main__'` って何
これは美しくまとめてくださっているサイトを見つけました
[Pythonのif \_\_name\_\_ == '\_\_main\_\_'の意味と使い方](https://note.nkmk.me/python-if-name-main/)

「該当のファイルがコマンドラインからスクリプトとして実行された場合にのみ以降の処理を実行する」ということになるみたいです。
つまりどこかから呼び出されたときには動かないということ

他人のコード読んでると，これがメインですよ〜ってのを示すために書かれてたりするような気がします。

# おわりに
美しいコードが書きたいもんですね。

# その他参考
[［Pythonチートシート］特殊メソッド編](https://www.atmarkit.co.jp/ait/articles/2002/18/news007.html)
[マークダウン記法でアンダースコアを入れる方法](http://www.tkoyama.com/archives/3542/)