Pythonの組み込み関数69個を制覇する 第4回 h～i

Pythonでは、非常に多くの組み込み関数(Built-in Functions)が用意されており、ライブラリをimportせずとも様々な処理を行うことができます。
基本に立ち返って、組み込み関数の使い方を整理して行きたいと思います。
尚、実行例はWindows Subsystem for LinuxのUbuntu18.04にインストールしたPython3.7.1で作成しています。

[Pythonの組み込み関数69個を制覇する 第1回 a～b](https://qiita.com/ichi_taro3/items/cd71a8e43040abb446a1)
[Pythonの組み込み関数69個を制覇する 第2回 c～d](https://qiita.com/ichi_taro3/items/696b355d79d01a810381)
[Pythonの組み込み関数69個を制覇する 第3回 e～g](https://qiita.com/ichi_taro3/items/c866b7124415464e8ef1)
[Pythonの組み込み関数69個を制覇する 第5回 l～o](https://qiita.com/ichi_taro3/items/f2cb744a879a084e49af)
[Pythonの組み込み関数69個を制覇する 第6回 p～r](https://qiita.com/ichi_taro3/items/2c2b399b762f5800fe82)


## 関数の使い方
各関数の使い方を記述していきます。詳細な使い方は他の記事に譲るとして、ここでは簡単な使用例を中心に掲載していきます。

#### hasattr()
オブジェクトに指定した属性が設定されているかを判定します。
第1引数に判定したいオブジェクトを、第2引数に判定したい属性名を渡します。

```Python
>>> class Sushi(object):
...     def __init__(self, neta, type):
...         self.neta = neta
...         self.type = type
...
>>> maguro = Sushi('maguro', 'nigiri')
>>> # 存在していたらTrue
... hasattr(maguro, 'neta')
True
>>> # 存在していなかったらFalse
... hasattr(maguro, 'taste')
False
>>> hasattr(maguro, 'type')
True
```

#### hash()
引数には任意のオブジェクトをとり、そのハッシュ値を返します。
通常、ハッシュ値はオブジェクトのもつ`__hash__()`メソッドの結果を利用します。

```Python
>>> hash(1)
1
>>> # 値が同じ場合はhash値は同じになる
... hash(1.0)
1
>>> hash(complex(1))
1
>>> # 文字列
... hash('key1')
7054912689230938466
>>> hash('key2')
4510368350215496904
>>> hash(object())
8771476958276
>>> # __hash__()を実装するとhash()の返り値をコントロールできる
... class Hashi(object):
...     def __hash__(self):
...         return 2
...
>>> chopsticks = Hashi()
>>> hash(chopsticks)
2
```

ハッシュはdictで利用されるのですが、どのように使われるかは[Python における hashable](https://qiita.com/yoichi22/items/ebf6ab3c6de26ddcc09a) などがわかりやすいです。

#### help()
Pythonオブジェクトの説明を見ることができる非常に便利な関数です。
主にPythonの対話コンソールで使用します。

引数なしで呼び出すと、対話的なヘルプが起動します。

```
>>> help()

Welcome to Python 3.7's help utility!

If this is your first time using Python, you should definitely check out
the tutorial on the Internet at https://docs.python.org/3.7/tutorial/.

Enter the name of any module, keyword, or topic to get help on writing
Python programs and using Python modules.  To quit this help utility and
return to the interpreter, just type "quit".

To get a list of available modules, keywords, symbols, or topics, type
"modules", "keywords", "symbols", or "topics".  Each module also comes
with a one-line summary of what it does; to list the modules whose name
or summary contain a given string such as "spam", type "modules spam".

help>
```

対話コンソールでは、オブジェクト名を入力することで、オブジェクトの説明文や持っているメソッド、属性などの情報を見ることができます。

```
help> str

Help on class str in module builtins:

class str(object)
 |  str(object='') -> str
 |  str(bytes_or_buffer[, encoding[, errors]]) -> str
 |
 |  Create a new string object from the given object. If encoding or
 |  errors is specified, then the object must expose a data buffer
 |  that will be decoded using the given encoding and error handler.
 |  Otherwise, returns the result of object.__str__() (if defined)
 |  or repr(object).
 |  encoding defaults to sys.getdefaultencoding().
 |  errors defaults to 'strict'.
 |
 |  Methods defined here:
(略)
```

私の環境では、ヘルプページはlessコマンドと同じように操作することができました。
矢印キーや`j` `k`キーでの移動、 `/`キーのあとに検索ワードを入力してドキュメント内の検索などができます。`q`キーでヘルプページから抜けます。

`help> `と表示されているときに`quit`または`q`と入力すると、ヘルプコンソールから抜けることができ、Pythonのプロンプトが表示されます。

```
help> quit

You are now leaving help and returning to the Python interpreter.
If you want to ask for help on a particular object directly from the
interpreter, you can type "help(object)".  Executing "help('string')"
has the same effect as typing a particular string at the help> prompt.
>>> 
```

help()の引数にオブジェクトを渡すことで、ヘルプを表示することもできます。

```
>>> help(sum)

Help on built-in function sum in module builtins:

sum(iterable, start=0, \)
    Return the sum of a 'start' value (default: 0) plus an iterable of numbers

    When the iterable is empty, return the start value.
    This function is intended specifically for use with numeric values and may
    reject non-numeric types.
```

help()関数は、オブジェクトの定義からヘルプドキュメントを生成しているので、自作の関数定義やクラス定義のヘルプを見ることもできます。

```Python
>>> class Fisherman(object):
...     """釣り人"""
...     def fish(self, feed:str) -> str:
...         """何かを釣り上げる"""
...         return 'can'
...
>>> help(Fisherman)
```

```
Help on class Fisherman in module __main__:

class Fisherman(builtins.object)
 |  釣り人
 |
 |  Methods defined here:
 |
 |  fish(self, feed: str) -> str
 |      何かを釣り上げる
 |
 |  ----------------------------------------------------------------------
 |  Data descriptors defined here:
 |
 |  __dict__
 |      dictionary for instance variables (if defined)
 |
 |  __weakref__
 |      list of weak references to the object (if defined)

```

#### hex()
引数に整数を渡すと、頭に`0x`をつけた16進数の文字列に変換します。

```Python
>>> hex(1)
'0x1'
>>> hex(16)
'0x10'
>>> hex(-99)
'-0x63'
>>> # floatはエラーになる
... hex(5.6)
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
TypeError: 'float' object cannot be interpreted as an integer
>>> # floatを16進数にしたい場合は、float.hex()メソッドを使う
... 5.6.hex()
'0x1.6666666666666p+2'
>>> # intに戻すときは第２引数に底16を渡す
... int(hex(-99), 16)
-99
```

#### id()
引数に渡したオブジェクトの識別値を返します。
そのオブジェクトが有効である間は、常に一意の定数になることが仕様で保証されています。従って、あるオブジェクトが生存しているときに同じidになるような２つの変数は同じオブジェクトを指していることになります。
`is`演算子が真になるのはidの値が同一になる場合です。

```Python
>>> # mutableなオブジェクトの例(int)
... x = 1
>>> id(1)
11151232
>>> id(x)
11151232
>>> x is 1
True
>>> x += 1
>>> # idが変わる
.... id(x)
11151264
>>> id(x) == id(2)
True
>>> x is 2
True
>>> # mutableなオブジェクトの例(list)
... y = []
>>> id(y)
140495409735688
>>> y.append(1)
>>> y
[1]
>>> id(y)
140495409735688
>>> # idが異なるので、別オブジェクト
... z = [1]
>>> id(z)
140495410036168
>>> y is z
False
```

CPythonの実装では、id値はメモリ上のアドレス値になるとのことです。

#### input()
プロンプトを表示してユーザーからの入力を受け付け、結果を文字列として返します。
プロンプトは、引数で文字列として指定することができます。

```Python
>>> result = input()
Hello
>>> print(result)
Hello
>>> name = input('名前を入力してね >>> ')
名前を入力してね >>> サブロー
>>> print(name)
サブロー
```

プログラム内でユーザーからの入力を受け付けることができるので非常に便利なinput()関数ですが、入力内容がプロンプトに表示されてしまうためパスワード入力には使えません。
パスワードの入力を対話的に行いたい場合は[getpassモジュール](https://docs.python.org/ja/3/library/getpass.html)を使うのが良いでしょう。

#### int()
整数型クラスのインスタンスオブジェクトを返却します。つまり、1や100や-9999などです。
引数には数値か、str, bytes, bytearrayといった文字列を扱うオブジェクトを渡すことができます。文字列の内容は`'100'`や`'-200'`といった [整数リテラル](https://docs.python.org/ja/3/reference/lexical_analysis.html#integers)である必要があります。

```Python
>>> # 何も渡さない場合は0
... int()
0
>>> # 数値
... int(100)
100
>>> int(45.0)
45
>>> int(30.5)
30
>>> int(-4.5555E3)
-4555
>>> # 文字列
... int('145')
145
>>> # bytes
... int(b'-490')
-490
>>> # bytearray
... int(bytearray('50', 'ascii'))
50
>>> # 第2引数に基数を渡すことができる
... # 2進数
... int('01001', 2)
9
>>> # 7進数
... int('555', 7)
285
>>> # 8進数
... int('0o555', 8)
365
>>> # 16進数
... int('FFFF', 16)
65535
```

引数に渡すオブジェクトに`__int__()`や`__trunc__()`が定義されていた場合、それらの実行結果がint()の結果として返却されます。

```Python
>>> # __int__()を実装する
... class MyInt(object):
...     def __int__(self):
...         return 42
...
>>> int(MyInt())
42
>>> # __trunc__()を実装する
... class MyFloat(float):
...     def __trunc__(self):
...         import math
...         return math.ceil(self)
...
>>> int(MyFloat(5.5))
5
>>> int(MyFloat(6.9))
6
```

#### isinstance()
指定したオブジェクトが、あるクラスのインスタンスかどうかを判定しTrue/Falseを返却します。親クラスや先祖クラスが比較対象の場合も同様に真を返します。
第１引数にオブジェクトを、第２引数にクラスを渡します。

```Python
>>> isinstance(1, int)
True
>>> isinstance(1, str)
False
>>> # intを継承したクラス
... class NewInt(int):
...     pass
...
>>> isinstance(NewInt(1), int)
True
>>> # 抽象基底クラス(Abstract Base Class)の場合
>>> from abc import ABC
>>> class MyABC(ABC):pass
...
>>> class DEF(object):pass
...
>>> isinstance(DEF(), MyABC)
False
>>> # 仮想クラスに登録すると、DEFはMyABCの子クラスとして認識される
... MyABC.register(DEF)
<class '__main__.DEF'>
>>> isinstance(DEF(), MyABC)
True
```

第２引数はクラスオブジェクトのタプルを渡すこともできます。その場合、要素のいずれかが対象の親(先祖)クラスであればTrueとなります。

```Python
>>> isinstance(10.5, (int, float, str))
True
>>> isinstance(10.5, (int, str))
False
>>> isinstance(10.5, ())
False
```

#### issubclass()
指定したクラスオブジェクトが、あるクラスのサブクラスかどうかを判定しTrue/Falseを返却します。親クラスや先祖クラスが比較対象の場合も同様に真を返します。
第１引数にクラスオブジェクトを、第２引数にクラスを渡します。

```Python
>>> issubclass(int, int)
True
>>> issubclass(NewInt, int)
True
>>> issubclass(NewInt, str)
False

```

#### iter()
iteratorオブジェクトを返します。
引数を一つまたは二つとり、それぞれのパターンで動きが変わるという少し癖のある関数です。
引数が一つの場合、`__iter__()`か`__getitem()__`をサポートしているオブジェクトである必要があります。forループの対象にできるものと考えれば問題ないでしょう。
iteratorオブジェクトをnext()関数に渡すと、要素を一つずつ返却し、最後の要素まで返却し終えるとStopIteration例外を送出します。大抵の場合は、forループで使用します。 

```Python
>>> i = iter([1, 2, 3])
>>> next(i)
1
>>> next(i)
2
>>> next(i)
3
>>> # 要素がなくなると例外
... next(i)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
>>> for taste in iter(('Tonkotsu', 'Miso', 'Shoyu', 'Shio',)):
...     print(taste, 'Ramen is Good.')
...
Tonkotsu Ramen is Good.
Miso Ramen is Good.
Shoyu Ramen is Good.
Shio Ramen is Good.
```

iter()には第二引数としてsentinel、つまり番兵を渡すことができます。
この場合、第一引数は呼び出し可能(callable)なオブジェクトである必要があります。
このとき返却されるイテレータオブジェクトでは、`__next__()`が呼び出されるたびに第一引数オブジェクトを引数無しで呼び出し、返却される値が第二引数の値と同一であると`StopIteration`を送出します。

```Python
>>> x = 0
>>> def counter():
...     global x
...     x += 1
...     return x
...
>>> # ループのたびにcounter()が呼び出され、返り値が5のときに終了する
>>> for i in iter(counter, 5):
...     print(i)
...
1
2
3
4
```
[標準ドキュメント](https://docs.python.org/ja/3/library/functions.html#iter) では、番兵を利用して、バイナリデータからブロックデータを読み込む方法を例として上げています。

## [第５回](https://qiita.com/ichi_taro3/items/f2cb744a879a084e49af)に続く
[次回](https://qiita.com/ichi_taro3/items/f2cb744a879a084e49af)はlen()から