![見出し画像](https://assets.st-note.com/production/uploads/images/20560671/rectangle_large_type_2_22593be39ca4bc2fabdd71379ab81dd8.png?width=1200)
Python実践入門 ──言語の力を引き出し、開発効率を高める(第8章組み込み関数と特殊メソッド)
■組み込み関数
何もインポートすることなくいつでも利用できるPythonの関数
■特殊メソッド
メソッド名の前後に_がついているメソッドで、
Pythonから暗黙的に呼び出されます。
■今回勉強に利用した本
8.1組み込み関数 -いつでも利用できる関数-
オブジェクトの型を調べる関数
isInstance(), issubclass() - 動的な型判定
>>> d = {}
>>> isinstance(d, dict)
True
>>> isinstance(d, object)
True
>>> issubclass(dict, object)
True
>>> issubclass(bool, (list, int, dict))
True
callable() - 呼び出し可能オブジェクトを判定
>>> callable(isinstance)
True
>>> callable(Exception)
True
>>> callable("".split)
True
オブジェクトの属性に関する関数
hasattr() - オブジェクトの属性の有無を判定
>>> import json
>>> import os
>>>
>>> def is_package(module_or_package):
... return hasattr(module_or_package, '__path__')
...
>>>
>>> is_package(json)
True
>>> is_package(os)
False
getattr(), setattr(), delattr() - オブジェクトの属性を操作する
>>> class Mutable:
... def __init__(self, attr_map):
... for k, v in attr_map.items():
... setattr(self, str(k), v)
...
>>> m = Mutable({'a':1, 'b':2})
>>> m.a
1
>>>
>>> attr = 'b'
>>> getattr(m, attr)
2
>>>
>>> delattr(m, 'a')
>>> m.a
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Mutable' object has no attribute 'a'
イテラブルなオブジェクトを受け取る関数
zip() - 複数のイテラブルの要素を同時に返す。
>>> x = [1,2,3]
>>> y = [4,5,6]
>>> zip(x,y)
<zip object at 0x7f65deca9f00>
>>> list(zip(x,y))
[(1, 4), (2, 5), (3, 6)]
sorted() - イテラブルの要素を並べ替える。
>>> x = [1,4,3,5,2]
>>> y = [1,4,3,5,2]
>>>
>>> x.sort()
>>> x
[1, 2, 3, 4, 5]
>>>
>>> sorted(y)
[1, 2, 3, 4, 5]
>>> y
[1, 4, 3, 5, 2]
>>>
>>> sorted(y, reverse=True)
[5, 4, 3, 2, 1]
>>>
filter() - イテラブルの要素を絞り込む
>>> x = (1,4,3,5,2)
>>> list(filter(lambda i:i>3,x))
[4, 5]
>>>
>>> x = (1,0,None,2,[],'python')
>>> list(filter(None,x))
[1, 2, 'python']
>>> from operator import itemgetter
>>> d = {'word': 'python', 'count': 3}
>>> f = itemgetter('count')
>>> f(d)
3 # d['count']を返す
>>> f = itemgetter('count', 'word')
>>> f(d)
(3, 'python') # (d['count'], d['word'])を返す
all(), any() - 真理値を返す
>>> all(['python', 'practice', 'book'])
True
>>> all(['python', 'practice', ''])
False
>>> any(['python', '', ''])
True
# 真の値がないのでFalse
>>> any(['', '', ''])
False
8.2特殊メソッド - Pythonが暗黙的に呼び出す特殊メソッド
■目印
メソッド名の前後に_が2つついています。__メソッド名__
__str__(),__repr__() - オブジェクトを文字列で表現する。
>>> s = 'string'
# オブジェクト名のみを入力した際は__repr__()が呼ばれます。
>>> s
'string'
組み込み関数print()に渡された際は__str__()が呼ばれます。
>>> print(s)
string
__bool__() - オブジェクトを真理値で評価する
>>> class QueryParams:
... def __init__(self, params):
... self.params = params
... def __bool__(self):
... return bool(self.params)
...
>>> query = QueryParams({})
>>> bool(query)
False
>>> query = QueryParams({'key': 'value'})
>>> bool(query)
True
__call__() - インスタンスを関数のように扱う
>>> class Adder:
... def __init__(self):
... self._values = []
... def add(self, x):
... self._values.append(x)
... def __call__(self):
... return sum(self._values)
...
>>> adder = Adder()
>>> adder.add(1)
>>> adder.add(3)
>>> adder()
4
>>> adder.add(5)
>>> adder()
9
# 関数を作成すると、自ずと__call__()が実装されている。
>>> def f():
... return 1
...
>>> dir(f)
['__annotations__', '__call__', '__class__', ...]
>>> type(f)
<class 'function'>
属性への動的なアクセス
__setattr__() - 属性への代入で呼び出される
__setattr__()の内部で自分自身に属性を追加する際は、必ず組み込み関数super()を使って基底クラスの__setattr__()を呼び出す。
>>> class Point:
... def __init__(self, x, y):
... self.x = x
... self.y = y
... def __setattr__(self, name, value):
... if name not in ('x', 'y'):
... raise AttributeError('Not allowed')
... super().__setattr__(name, value)
...
>>> p = Point(1, 2)
>>> p.z = 3
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 7, in __setattr__
AttributeError: Not allowed
>>> p.x = 3
>>> p.x
3
__delattr() - 属性の削除で呼び出される
>>> class Point:
... def __init__(self, x, y):
... self.x = x
... self.y = y
... def __delattr__(self, name):
... if name in ('x', 'y'):
... raise AttributeError('Not allowed')
... super().__delattr__(name)
...
>>> p = Point(1, 2)
>>> del p.x
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 7, in __delattr__
AttributeError: Not allowed
__getattr__(), __getattribute__() - 属性アクセスで呼び出される
>>> class Point:
... pass
...
>>> p = Point()
>>> p.__dict__
{}
# p.__dict__['x'] = 1 に変換される
>>> p.x = 1
>>> p.__dict__
{'x': 1}
# __dict__は直接書き込み可能
>>> p.__dict__['y'] = 2
>>> p.y
2
イテラブルなオブジェクトとして振る舞う
__iter()__ - イテレータオブジェクトを返す。
■for i in x
for文はxの__iter__()を呼び出し、その戻り値を利用します
>>> class Iterable:
... def __init__(self, num):
... self.num = num
... def __iter__(self):
... return iter(range(self.num))
...
>>> [val for val in Iterable(3)]
[0, 1, 2]
__next__() - 次の要素を返す。
■イテレータ
特殊メソッドの__iter__()と__next__()を実装したオブジェクトのこと。
>>> class Reverser:
... def __init__(self, x):
... self.x = x
... def __iter__(self):
... return self
... def __next__(self):
... try:
... return self.x.pop()
... except IndexError:
... raise StopIteration()
...
>>> [val for val in Reverser([1, 2, 3])]
[3, 2, 1]
イテラブルとイテレータの違い
・イテラブル
__iter__()を実装したオブジェクト
__iter__()の戻り値は任意のイテレータ
・イテレータ
__iter__()と__next__()を実装したオブジェクト
__iter__()の戻り値は自分自身(self)
コンテナオブジェクトとして振る舞う
■コンテナオブジェクト(以下、コンテナ)
リストやタプル、辞書などほかのオブジェクトへの参照を持つオブジェクトです。
__getitem__(), __setItem__() - インデックスやキーによる操作
>>> from collections import defaultdict
>>> class CountDict:
... def __init__(self):
... self._data = {}
... self._get_count = defaultdict(int)
... self._set_count = defaultdict(int)
... def __getitem__(self, key):
... # c['x'] など参照時に呼ばれる
... self._get_count[key] += 1
... return self._data[key]
... def __setitem__(self, key, value):
... # c['x'] = 1 など代入時に呼ばれる
... self._set_count[key] += 1
... self._data[key] = value
... @property
... def count(self):
... return {
... 'set': list(self._set_count.items()),
... 'get': list(self._get_count.items()),
... }
...
>>> c = CountDict()
>>> c['x'] = 1
>>> c['x']
1
>>> c['x'] = 2
>>> c['y'] = 3
# 参照、代入された回数を返す
>>> c.count
{'set': [('x', 2), ('y', 1)], 'get': [('x', 1)]}
__contains__() - オブジェクトの有無を判定
>>> class OddNumbers:
... def __contains__(self, item):
... try:
... return item % 2 == 1
... except:
... return False
...
>>> odds = OddNumbers()
>>> 1 in odds
True
>>> 4 in odds
False
まとめ
久々にPythonを利用すると、特殊メソッドを忘れることが多かったので、最低限知らないと他人のコードが読めないよって部分を抑えることができたので、非常に感謝です。
Pythonをメインに利用してる人って、この特殊メソッドの利用がうまいんだろうなーー。。。Python力を上げるためにも自分も利用しようと思いました。
この記事が参加している募集
この記事が気に入ったらサポートをしてみませんか?