この記事はNuco Advent Calendar 2023の5日目の記事です。
はじめに
Pythonは、世界中で広く使われているプログラミング言語の一つです。Pythonの特徴の一つは、豊富な組み込み関数を持っていることです。
Pythonの組み込み関数は、2023年12月現在、全71件あります。しかし、それらを完璧に使いこなせている人はどれくらいいるでしょうか?
この記事では、Pythonの組み込み関数全71件を、実際のコード例も踏まえて完全解説します。この記事を読めば、Pythonの組み込み関数について、一から十まで理解できるでしょう。
それでは、早速見ていきましょう。
弊社Nucoでは、他にも様々なお役立ち記事を公開しています。よかったら、Organizationのページも覗いてみてください。
また、Nucoでは一緒に働く仲間も募集しています!興味をお持ちいただける方は、こちらまで。
組み込み関数の一覧
(1)abs()
引数の絶対値を返します。
num = -5
assert abs(num) == 5
- 注意点
引数が数値以外のオブジェクトの場合、__abs__()
メソッドが定義されている必要があります。
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def __abs__(self):
return (self.x ** 2 + self.y ** 2) ** 0.5
v = Vector(3, 4)
assert abs(v) == 5
この関数を知らないと…
絶対値を求める際に、不要な条件分岐の実装や、不要なモジュールのインポートが発生します。
import math
num = -5
if num < 0:
num = -num
assert num == 5
num = -5
num = math.fabs(num)
assert num == 5
(2)aiter()
引数に指定した非同期イテラブルオブジェクトを非同期イテレータに変換します。非同期イテラブルオブジェクトとは、__aiter__()
メソッドを持つオブジェクトで、非同期イテレータを返すものです。非同期イテレータとは、__anext__()
メソッドを持つオブジェクトで、非同期ジェネレータを返すものです。
import asyncio
async def async_gen():
for i in range(3):
yield i
await asyncio.sleep(1)
async def main():
async for i in aiter(async_gen()):
print(i)
asyncio.run(main()) # 0, 1, 2を1秒ごとに出力
- 注意点
aiter()
は非同期イテラブルオブジェクトに対してのみ有効です。通常のイテラブルオブジェクトに対してはTypeError
を発生させます。
aiter([1, 2, 3]) # TypeError: 'list' object is not an async iterable
この関数を知らないと…
非同期イテラブルオブジェクトをfor文で回す際に、async for
を使わなければなりません。しかし、async for
はawait式の中で使えません。その場合、aiter関数を使って非同期イテレータに変換し、anext関数で要素を取り出すことができます。
import asyncio
async def async_gen():
for i in range(3):
yield i
await asyncio.sleep(1)
async def main():
async_iter = aiter(async_gen())
while True:
try:
i = await anext(async_iter)
print(i)
except StopAsyncIteration:
break
asyncio.run(main())
(3)all()
引数(イテラブルオブジェクト)の全ての要素がTrue
ならば、True
を返します。
arr = [True, True]
assert all(arr) is True
arr = [True, False]
assert all(arr) is False
- 注意点
引数の要素が空の場合にはTrue
を返します。
arr = []
assert all(arr) is True
この関数を知らないと…
複数条件の比較の際にand
を連発して冗長なコードを書いてしまいます。
sample_1 = True
sample_2 = True
sample_3 = False
sample_4 = True
sample_5 = False
assert (sample_1 is True and sample_2 is True and sample_3 is True and sample_4 is True and sample_5 is True) is True
all関数を使うと以下のように書くことができます。
sample_1 = True
sample_2 = True
sample_3 = False
sample_4 = True
sample_5 = False
arr = [sample_1, sample_2, sample_3, sample_4, sample_5]
assert all(arr) is True
(4)anext()
引数に指定した非同期イテレータから次の要素を取得します。戻り値は非同期ジェネレータです。引数にデフォルト値を指定した場合、非同期イテレータが終了したときにその値を返します。デフォルト値を指定しない場合、非同期イテレータが終了したときにStopAsyncIterationException
を発生させます。
import asyncio
async def async_gen():
for i in range(3):
yield i
await asyncio.sleep(1)
async def main():
it = aiter(async_gen())
print(await anext(it)) # 0
print(await anext(it)) # 1
print(await anext(it)) # 2
print(await anext(it, 'end')) # end
asyncio.run(main())
- 注意点
anext()
は非同期イテレータに対してのみ有効です。通常のイテレータに対してはTypeError
を発生させます。
anext(iter([1, 2, 3])) # TypeError: 'list_iterator' object is not an async iterator
こういうときに便利
非同期イテレータから要素を取り出す際に、特定の条件を満たす要素だけを選択したいときに便利です。例えば、以下のコードでは、非同期イテレータから奇数だけを取り出しています。
import asyncio
async def async_gen():
for i in range(10):
yield i
await asyncio.sleep(1)
async def main():
async_iter = aiter(async_gen())
while True:
try:
i = await anext(async_iter)
if i % 2 == 1:
print(i)
except StopAsyncIteration:
break
asyncio.run(main())
(5)any()
引数(イテラブルオブジェクト)のいずれかの要素がTrue
ならば、True
を返します。
arr = [True, False]
assert any(arr) is True
arr = [False, False]
assert any(arr) is False
- 注意点
引数の要素が空の場合にはFalse
を返します。
arr = []
assert any(arr) is False
この関数を知らないと…
複数条件の比較の際にor
を連発して冗長なコードを書いてしまいます。
sample_1 = True
sample_2 = False
sample_3 = False
sample_4 = False
sample_5 = False
assert (sample_1 is True or sample_2 is True or sample_3 is True or sample_4 is True or sample_5 is True) is True
any関数を使うと以下のように書くことができます。
sample_1 = True
sample_2 = False
sample_3 = False
sample_4 = False
sample_5 = False
arr = [sample_1, sample_2, sample_3, sample_4, sample_5]
assert any(arr) is True
(6)ascii()
引数(オブジェクト)のASCII表現を文字列として返します。
s = 'こんにちは'
assert ascii(s) == "'\\u3053\\u3093\\u306b\\u3061\\u306f'"
- 注意点
引数のオブジェクトがASCII文字のみで構成されている場合には、そのままの文字列を返します。
s = 'Hello'
assert ascii(s) == "'Hello'"
こういうときに便利
非ASCII文字を含むオブジェクトをファイルに書き込んだり、他のプログラムに渡したりするときに、ascii関数を使って文字列に変換すると便利です。例えば、以下のように書くことができます。
s = 'こんにちは'
with open('test.txt', 'w') as f:
f.write(ascii(s))
# test.txtには'\u3053\u3093\u306b\u3061\u306f'と書かれる
import json
s = 'こんにちは'
data = {'message': ascii(s)}
json_data = json.dumps(data)
# json_dataは'{"message": "\\u3053\\u3093\\u306b\\u3061\\u306f"}'となる
(7)bin()
引数の整数を2進数の文字列に変換して返します。
num = 10
assert bin(num) == '0b1010'
- 注意点
整数以外のオブジェクトに対しては、__index__()
メソッドが定義されている必要があります。
class Bit:
def __init__(self, value):
self.value = value
def __index__(self):
return self.value
b = Bit(10)
assert bin(b) == '0b1010'
この関数を知らないと…
2進数の文字列に変換する際に、自分でビット演算や文字列操作を行う必要があります。
num = 10
result = ''
while num > 0:
result = str(num % 2) + result
num //= 2
result = '0b' + result
assert result == '0b1010'
bin関数を使うと以下のように書くことができます。
num = 10
result = bin(num)
assert result == '0b1010'
(8)bool()
引数を真偽値に変換して返します。引数が真とみなされる場合はTrue
、偽とみなされる場合はFalse
を返します。
assert bool(1) is True
assert bool(0) is False
assert bool('Hello') is True
assert bool('') is False
- 注意点
引数がない場合にはFalse
を返します。
assert bool() is False
こういうときに便利
条件分岐やループの制御にbool関数を使って、引数の真偽値を判定すると便利です。
x = input('Enter something: ')
if bool(x):
print('You entered:', x)
else:
print('You entered nothing')
arr = [1, 2, 3, 0, 4, 5]
for x in arr:
if bool(x):
print(x, 'is True')
else:
print(x, 'is False')
(9)breakpoint()
プログラムの実行を一時停止してデバッガに制御を渡す関数です。Python 3.7以降で導入されました。
def factorial(n, sum=0):
if n == 0:
return sum
# デバッグポイントを設定
breakpoint()
sum += n
print(sum)
return factorial(n-1, sum)
if __name__ == '__main__':
factorial(5)
- 注意点
breakpoint関数は、環境変数PYTHONBREAKPOINT
に設定されたデバッガを呼び出します。デフォルトではpdbモジュールが使用されますが、他のデバッガを指定することもできます。
# ipdbモジュールを使用する場合
import os
os.environ['PYTHONBREAKPOINT'] = 'ipdb.set_trace'
この関数を知らないと…
プログラムの実行中に変数の値や実行のフローを確認するために、print関数やpdbモジュールを直接コードに挿入してしまいます。これはコードの可読性や保守性を低下させる可能性があります。
def factorial(n, sum=0):
if n == 0:
return sum
# print関数で変数の値を確認
print('n:', n, 'sum:', sum)
# pdbモジュールでデバッグポイントを設定
import pdb; pdb.set_trace()
sum += n
print(sum)
return factorial(n-1, sum)
if __name__ == '__main__':
factorial(5)
breakpoint関数を使うと以下のように書くことができます。
def factorial(n, sum=0):
if n == 0:
return sum
# breakpoint関数でデバッグポイントを設定
breakpoint()
sum += n
print(sum)
return factorial(n-1, sum)
if __name__ == '__main__':
factorial(5)
(10)bytearray()
引数によって指定されたバイト列を表す可変なシーケンスオブジェクトを返します。
# 引数が整数の場合、その長さのゼロで埋められたバイト列を作ります。
ba = bytearray(5)
print(ba) # bytearray(b'\x00\x00\x00\x00\x00')
# 引数が文字列の場合、エンコーディングを指定してバイト列に変換します。
ba = bytearray("Hello", "utf-8")
print(ba) # bytearray(b'Hello')
# 引数がイテラブルオブジェクトの場合、その要素をバイト値として使用します。
ba = bytearray([65, 66, 67])
print(ba) # bytearray(b'ABC')
- 注意点
bytearrayオブジェクトは可変なので、要素の追加や削除、スライスの代入などができます。しかし、要素は0から255の範囲の整数でなければなりません。
ba = bytearray(b"Hello")
ba[0] = 74 # b'H'をb'J'に変更
print(ba) # bytearray(b'Jello')
ba.append(33) # b'!'を追加
print(ba) # bytearray(b'Jello!')
ba[1:4] = b"ohn" # b'ell'をb'ohn'に置き換え
print(ba) # bytearray(b'John!')
ba[0] = 256 # 0から255の範囲外の値はエラーになる
# ValueError: byte must be in range(0, 256)
この関数を知らないと…
バイト列を扱うときに、bytesオブジェクトを使ってしまいます。bytesオブジェクトは不変なので、要素の変更や追加ができません。そのため、新しいバイト列を作るためには、毎回bytesオブジェクトを作り直す必要があります。これは非効率的で、メモリの無駄になります。
b = b"Hello"
b[0] = 74 # bytesオブジェクトは不変なのでエラーになる
# TypeError: 'bytes' object does not support item assignment
b += b"!" # 新しいbytesオブジェクトを作って連結する
print(b) # b'Hello!'
bytearray関数を使うと、バイト列を簡単に変更できます。
ba = bytearray(b"Hello")
ba[0] = 74 # bytearrayオブジェクトは可変なので変更できる
print(ba) # bytearray(b'Jello')
ba += b"!" # 既存のbytearrayオブジェクトに追加できる
print(ba) # bytearray(b'Jello!')
(11)bytes()
引数によって指定されたバイト列を表す不変なシーケンスオブジェクトを返します。
# 引数が整数の場合、その長さのゼロで埋められたバイト列を作ります。
b = bytes(5)
print(b) # b'\x00\x00\x00\x00\x00'
# 引数が文字列の場合、エンコーディングを指定してバイト列に変換します。
b = bytes("Hello", "utf-8")
print(b) # b'Hello'
# 引数がイテラブルオブジェクトの場合、その要素をバイト値として使用します。
b = bytes([65, 66, 67])
print(b) # b'ABC'
- 注意点
bytesオブジェクトは不変なので、要素の変更や追加、削除などができません。そのため、新しいバイト列を作るためには、別のbytesオブジェクトと連結したり、bytearrayオブジェクトに変換したりする必要があります。
b = b"Hello"
b[0] = 74 # bytesオブジェクトは不変なのでエラーになる
# TypeError: 'bytes' object does not support item assignment
b += b"!" # 新しいbytesオブジェクトを作って連結する
print(b) # b'Hello!'
ba = bytearray(b) # bytearrayオブジェクトに変換する
ba[0] = 74 # bytearrayオブジェクトは可変なので変更できる
print(ba) # bytearray(b'Jello!')
この関数を知らないと…
バイト列を扱うときに、文字列を使ってしまいます。文字列はエンコーディングに依存するので、バイナリデータとして扱うことができません。そのため、ファイルの読み書きやネットワークの通信などで問題が発生する可能性があります。
s = "Hello"
f = open("test.txt", "w") # テキストモードでファイルを開く
f.write(s) # 文字列を書き込む
f.close()
f = open("test.txt", "rb") # バイナリモードでファイルを開く
b = f.read() # バイト列を読み込む
f.close()
print(b) # b'Hello'
s = "こんにちは"
f = open("test.txt", "w") # テキストモードでファイルを開く
f.write(s) # 文字列を書き込む
f.close()
f = open("test.txt", "rb") # バイナリモードでファイルを開く
b = f.read() # バイト列を読み込む
f.close()
print(b) # b'\xe3\x81\x93\xe3\x82\x93\xe3\x81\xab\xe3\x81\xa1\xe3\x81\xaf'
bytes関数を使うと、文字列をバイト列に変換できます。
s = "Hello"
b = bytes(s, "utf-8") # 文字列をバイト列に変換
f = open("test.txt", "wb") # バイナリモードでファイルを開く
f.write(b) # バイト列を書き込む
f.close()
f = open("test.txt", "rb") # バイナリモードでファイルを開く
b = f.read() # バイト列を読み込む
f.close()
print(b) # b'Hello'
s = "こんにちは"
b = bytes(s, "utf-8") # 文字列をバイト列に変換
f = open("test.txt", "wb") # バイナリモードでファイルを開く
f.write(b) # バイト列を書き込む
f.close()
f = open("test.txt", "rb") # バイナリモードでファイルを開く
b = f.read() # バイト列を読み込む
f.close()
print(b) # b'\xe3\x81\x93\xe3\x82\x93\xe3\x81\xab\xe3\x81\xa1\xe3\x81\xaf'
(12)callable()
引数が呼び出し可能なオブジェクト(関数やメソッドなど)であればTrue
を、そうでなければFalse
を返します。
def add(x, y):
return x + y
print(callable(add)) # True
print(callable(3)) # False
print(callable(print)) # True
print(callable("Hello")) # False
- 注意点
callable関数は、オブジェクトが呼び出し可能であるかどうかを判定するだけで、実際に呼び出すことはできません。呼び出し可能なオブジェクトを実際に呼び出すには、カッコと引数を付けて実行します。
def add(x, y):
return x + y
callable(add) # True
add(3, 4) # 7
callable(3) # False
3(5) # エラーになる
# TypeError: 'int' object is not callable
この関数を知らないと…
オブジェクトが呼び出し可能かどうかを確認するときに、try-except文を使ってエラーを捕捉してしまいます。これは冗長で、パフォーマンスに影響する可能性があります。
def add(x, y):
return x + y
def is_callable(obj):
try:
obj()
return True
except TypeError:
return False
print(is_callable(add)) # True
print(is_callable(3)) # False
callable関数を使うと、簡潔に書くことができます。
def add(x, y):
return x + y
print(callable(add)) # True
print(callable(3)) # False
(13)chr()
引数に指定されたUnicodeコードポイントに対応する文字を返します。
print(chr(65)) # A
print(chr(97)) # a
print(chr(12354)) # あ
print(chr(128512)) # 😀
- 注意点
引数は0から1114111の範囲の整数でなければなりません。それ以外の値はエラーになります。
print(chr(-1)) # エラーになる
# ValueError: chr() arg not in range(0x110000)
print(chr(1114112)) # エラーになる
# ValueError: chr() arg not in range(0x110000)
この関数を知らないと…
Unicodeコードポイントから文字を得るために、エンコーディングやバイト列を使って変換してしまいます。これは複雑で、エラーが発生しやすいです。
# UTF-8エンコーディングを使ってコードポイントから文字を得る
def codepoint_to_char(codepoint):
b = codepoint.to_bytes(4, "big") # コードポイントをバイト列に変換
b = b.lstrip(b"\x00") # 先頭のゼロを除去
return b.decode("utf-8") # バイト列を文字列に変換
print(codepoint_to_char(65)) # A
print(codepoint_to_char(97)) # a
print(codepoint_to_char(12354)) # あ
print(codepoint_to_char(128512)) # 😀
chr関数を使うと、簡単に文字を得ることができます。
print(chr(65)) # A
print(chr(97)) # a
print(chr(12354)) # あ
print(chr(128512)) # 😀
(14)classmethod()
引数に指定された関数をクラスメソッドに変換して返します。クラスメソッドとは、クラスオブジェクト自身を第一引数として受け取るメソッドのことです。クラスメソッドは、インスタンス化されたオブジェクトではなく、クラスオブジェクトから直接呼び出すことができます。
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
@classmethod # クラスメソッドにするためのデコレータ
def from_birth_year(cls, name, birth_year): # 第一引数にクラスオブジェクトを受け取る
age = 2023 - birth_year # 年齢を計算する
return cls(name, age) # クラスオブジェクトを使ってインスタンスを作る
p1 = Person("Alice", 25) # 通常の方法でインスタンスを作る
p2 = Person.from_birth_year("Bob", 1998) # クラスメソッドを使ってインスタンスを作る
print(p1.name, p1.age) # Alice 25
print(p2.name, p2.age) # Bob 25
こういうときに便利
クラスメソッドは、クラスのインスタンスを作成するための別のコンストラクタとして使うことができます。
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
@classmethod
def from_birth_year(cls, name, birth_year):
age = 2023 - birth_year
return cls(name, age)
p1 = Person("Alice", 25)
p2 = Person.from_birth_year("Bob", 1998)
print(p1.name, p1.age) # Alice 25
print(p2.name, p2.age) # Bob 25
このように、クラスメソッドを使うと、引数の形式に応じてインスタンスを作ることができます。また、クラスメソッドは継承されたクラスでも使えます。
class Student(Person):
def __init__(self, name, age, school):
super().__init__(name, age)
self.school = school
@classmethod
def from_birth_year(cls, name, birth_year, school):
age = 2023 - birth_year
return cls(name, age, school)
s1 = Student("Charlie", 18, "Tokyo University")
s2 = Student.from_birth_year("David", 2005, "Tokyo High School")
print(s1.name, s1.age, s1.school) # Charlie 18 Tokyo University
print(s2.name, s2.age, s2.school) # David 18 Tokyo High School
このように、クラスメソッドを使うと、継承したクラスでも親クラスと同じようにインスタンスを作ることができます。
(15)compile()
引数に指定されたソースコード(文字列やバイト列)をコードオブジェクトに変換して返します。コードオブジェクトとは、Pythonのインタプリタが実行できる形式のコードのことです。compile関数は、ソースコードを動的に評価したり、ファイルに保存したりするときに使われます。
# 引数にはソースコード、ファイル名、モードを指定する
# モードは、'exec'(文の列)、'eval'(式)、'single'(対話的な式)のいずれか
code = compile("x = 3\ny = 4\nprint(x + y)", "<string>", "exec") # 文の列をコードオブジェクトに変換
exec(code) # コードオブジェクトを実行する
# 7
code = compile("x * y", "<string>", "eval") # 式をコードオブジェクトに変換
x = 3
y = 4
result = eval(code) # コードオブジェクトを評価する
print(result) # 12
code = compile("x + y\n", "<string>", "single") # 対話的な式をコードオブジェクトに変換
x = 3
y = 4
exec(code) # コードオブジェクトを実行する
# 7
- 注意点
compile関数は、ソースコードをコードオブジェクトに変換するだけで、実際に実行することはできません。コードオブジェクトを実際に実行するには、exec関数やeval関数を使います。
code = compile("print('Hello')", "<string>", "exec") # 文をコードオブジェクトに変換
code # <code object <module> at 0x7f9f5c0a6c90, file "<string>", line 1>
code() # コードオブジェクトは呼び出し可能ではない
# TypeError: 'code' object is not callable
exec(code) # コードオブジェクトを実行する
# Hello
この関数を知らないと…
ソースコードを動的に評価するときに、exec関数やeval関数に直接渡してしまいます。これはセキュリティ上のリスクがあり、パフォーマンスに影響する可能性があります。
# exec関数に直接ソースコードを渡す
exec("x = 3\ny = 4\nprint(x + y)") # 7
# eval関数に直接ソースコードを渡す
x = 3
y = 4
result = eval("x * y") # 12
compile関数を使うと、ソースコードを事前にコードオブジェクトに変換しておくことができます。これは、同じソースコードを繰り返し実行する場合に効率的です。また、compile関数にはオプション引数として最適化レベルやフラグを指定することができます。これにより、ソースコードの構文チェックやデバッグ情報の削除などを行うことができます。
# compile関数を使ってソースコードをコードオブジェクトに変換
code = compile("x = 3\ny = 4\nprint(x + y)", "<string>", "exec")
exec(code) # 7
# オプション引数を指定してコードオブジェクトを作る
# optimize=2 は最適化レベルを最大にする
# dont_inherit=True は現在のスコープのフラグを無視する
code = compile("x = 3\ny = 4\nprint(x + y)", "<string>", "exec", optimize=2, dont_inherit=True)
exec(code) # 7
(16)complex()
引数に指定された実数部と虚数部から複素数を作って返します。複素数とは、実数と虚数の和で表される数のことです。虚数とは、平方根が負の数になる数のことで、iという記号で表されます。例えば、2 + 3iは複素数で、2は実数部、3は虚数部です。
# 引数には実数部と虚数部を指定する
c = complex(2, 3) # 2 + 3i
print(c) # (2+3j)
print(c.real) # 2.0
print(c.imag) # 3.0
# 引数が一つの場合、実数部として扱われる
c = complex(5) # 5 + 0i
print(c) # (5+0j)
# 引数が文字列の場合、複素数の表記として解釈される
c = complex("2+3j") # 2 + 3i
print(c) # (2+3j)
- 注意点
引数は数値か文字列でなければなりません。それ以外の型はエラーになります。
c = complex([1, 2]) # リストはエラーになる
# TypeError: complex() first argument must be a string or a number, not 'list'
引数が文字列の場合、複素数の表記として正しい形式でなければなりません。空白や不要な記号があるとエラーになります。
c = complex("2 + 3j") # 空白があるとエラーになる
# ValueError: complex() arg is a malformed string
c = complex("2+3i") # iではなくjでなければならない
# ValueError: complex() arg is a malformed string
この関数を知らないと…
複素数を扱うときに、実数部と虚数部を別々に管理してしまいます。これは複雑で、エラーが発生しやすいです。
# 実数部と虚数部を別々に管理する
real = 2
imag = 3
print(f"{real} + {imag}i") # 2 + 3i
# 複素数の演算をするときには、実数部と虚数部をそれぞれ計算する必要がある
real2 = 4
imag2 = 5
# (2 + 3i) + (4 + 5i) = (6 + 8i)
real_sum = real + real2
imag_sum = imag + imag2
print(f"{real_sum} + {imag_sum}i") # 6 + 8i
complex関数を使うと、複素数を一つのオブジェクトとして扱うことができます。
# 複素数を一つのオブジェクトとして扱う
c1 = complex(2, 3) # 2 + 3i
print(c1) # (2+3j)
# 複素数の演算をするときには、オブジェクト同士の演算でよい
c2 = complex(4, 5) # 4 + 5i
# (2 + 3i) + (4 + 5i) = (6 + 8i)
c_sum = c1 + c2
print(c_sum) # (6+8j)
(17)delattr()
引数に指定されたオブジェクトから、名前に対応する属性を削除します。属性とは、オブジェクトに紐づけられた変数や関数のことです。
class Person:
def __init__(self, name, age):
self.name = name # 属性
self.age = age # 属性
def greet(self): # 属性
print(f"Hello, I'm {self.name}.")
p = Person("Alice", 25) # オブジェクトを作る
p.greet() # Hello, I'm Alice.
print(p.age) # 25
delattr(p, "age") # オブジェクトから属性を削除する
print(p.age) # 属性がなくなったのでエラーになる
# AttributeError: 'Person' object has no attribute 'age'
- 注意点
引数にはオブジェクトと属性の名前を指定する必要があります。属性の値やオブジェクトの属性ではなく、属性の名前を文字列で渡さなければなりません。
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
p = Person("Alice", 25)
delattr(p, p.age) # 属性の値ではなく、属性の名前を渡さなければならない
# TypeError: attribute name must be string
delattr(p, p.name) # オブジェクトの属性ではなく、属性の名前を渡さなければならない
# TypeError: attribute name must be string
こういうときに便利
delattr関数は、オブジェクトから属性を削除することに特化した関数であるため、コードの意図を明確にすることに役立ちます。
del文を使う事もできますが、del文はオブジェクトから属性を削除するだけでなく、変数やリストの要素なども削除できるため、delattr関数はより特化的な関数として扱うことができます。
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
p = Person("Alice", 25)
del p.age # del文を使ってオブジェクトから属性を削除する
print(p.age) # 属性がなくなったのでエラーになる
# AttributeError: 'Person' object has no attribute 'age'
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
p = Person("Alice", 25)
delattr(p, "age") # delattr関数を使ってオブジェクトから属性を削除する
print(p.age) # 属性がなくなったのでエラーになる
# AttributeError: 'Person' object has no attribute 'age'
(18)dict()
引数に指定されたキーと値のペアから辞書を作って返します。
# 引数にはキーと値のペアを指定する
d = dict(name="Alice", age=25) # キーワード引数で指定する
print(d) # {'name': 'Alice', 'age': 25}
d = dict([("name", "Alice"), ("age", 25)]) # イテラブルオブジェクトで指定する
print(d) # {'name': 'Alice', 'age': 25}
d = dict({"name": "Alice", "age": 25}) # 既存の辞書で指定する
print(d) # {'name': 'Alice', 'age': 25}
- 注意点
引数はキーと値のペアでなければなりません。キーと値のペアがない場合や、キーが重複している場合はエラーになります。
d = dict(3) # キーと値のペアがないとエラーになる
# TypeError: cannot convert dictionary update sequence element #0 to a sequence
d = dict(name="Alice", name="Bob") # キーが重複しているとエラーになる
# TypeError: dict() got multiple values for keyword argument 'name'
この関数を知らないと…
辞書を作るときに、リテラル表記を使ってしまいます。リテラル表記とは、辞書を{}で囲んで、キーと値のペアを:
で区切って表す方法のことです。リテラル表記は、辞書を直接記述するときに便利ですが、キーと値のペアを動的に生成するときには不便です。
# リテラル表記を使って辞書を作る
d = {"name": "Alice", "age": 25}
print(d) # {'name': 'Alice', 'age': 25}
# キーと値のペアを動的に生成するときには不便
keys = ["name", "age"]
values = ["Alice", 25]
d = {} # 空の辞書を作る
for i in range(len(keys)): # インデックスを使ってループする
d[keys[i]] = values[i] # キーと値のペアを追加する
print(d) # {'name': 'Alice', 'age': 25}
dict関数を使うと、キーと値のペアを引数として渡すことができます。これは、キーと値のペアを動的に生成するときに便利です。
# dict関数を使って辞書を作る
d = dict(name="Alice", age=25)
print(d) # {'name': 'Alice', 'age': 25}
# キーと値のペアを動的に生成するときに便利
keys = ["name", "age"]
values = ["Alice", 25]
d = dict(zip(keys, values)) # zip関数でキーと値のペアを作る
print(d) # {'name': 'Alice', 'age': 25}
(19)dir()
引数に指定したオブジェクトの属性やメソッドの名前をリストとして返します。引数を省略した場合は、現在のローカルスコープの名前をリストとして返します。
class Sample:
def __init__(self, name):
self.name = name
def hello(self):
print(f"Hello, {self.name}!")
sample = Sample("Bing")
print(dir(sample))
# ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'hello', 'name']
print(dir())
# ['Sample', '__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'sample']
- 注意点
dir関数はオブジェクトの属性やメソッドの名前をリストとして返しますが、そのリストは必ずしも完全ではありません。オブジェクトが__dir__()
を提供しない場合、その型オブジェクトと、定義されていればオブジェクトの__dict__
属性から、できるだけ情報を集めようとするためです。
この関数を知らないと…
オブジェクトの属性やメソッドを調べるときに、help関数やインターネットで検索するなどの手間がかかります。dir関数を使うと、簡単にオブジェクトの属性やメソッドの名前を確認できます。
(20)divmod()
引数に指定した2つの数値の商と余りをタプルとして返します。引数は整数または浮動小数点数でなければなりません。
print(divmod(7, 3))
# (2, 1)
print(divmod(7.5, 3))
# (2.0, 1.5)
- 注意点
引数のどちらかが浮動小数点数の場合は、商と余りも浮動小数点数になります。また、引数のどちらかが0の場合は、ZeroDivisionError
が発生します。
この関数を知らないと…
商と余りを求めるときに、/や%などの演算子を使って別々に計算する必要があります。divmod関数を使うと、一度に商と余りを求めることができます。
x = 7
y = 3
quotient = x // y
remainder = x % y
result = (quotient, remainder)
print(result)
# (2, 1)
divmod関数を使うと以下のように書くことができます。
x = 7
y = 3
result = divmod(x, y)
print(result)
# (2, 1)
(21)enumerate()
引数に指定したイテラブルオブジェクトの要素とインデックスをタプルとして返すイテレータを作成します。インデックスは0から始まりますが、startパラメータで変更することができます。
fruits = ["apple", "banana", "cherry"]
for i, fruit in enumerate(fruits):
print(i, fruit)
# 0 apple
# 1 banana
# 2 cherry
for i, fruit in enumerate(fruits, start=1):
print(i, fruit)
# 1 apple
# 2 banana
# 3 cherry
- 注意点
引数のイテラブルオブジェクトが空の場合は、空のイテレータを返します。また、引数のイテラブルオブジェクトが変更されると、イテレータの挙動は保証されません。
この関数を知らないと…
イテラブルオブジェクトの要素とインデックスを同時に取得するときに、ループの中でインデックスを管理するために別の変数を用意してインクリメントする必要があります。
arr = ["apple", "banana", "cherry"]
i = 0
for x in arr:
print(i, x)
i += 1
enumerate関数を使うと、簡単にイテラブルオブジェクトの要素とインデックスをタプルとして取得できます。
arr = ["apple", "banana", "cherry"]
for i, x in enumerate(arr):
print(i, x)
(22)eval()
引数に与えられた文字列をPythonの式として評価し、その結果を返す関数です。
x = 2
y = 3
result = eval("x + y")
print(result) # 5
- 注意点
引数には式だけを指定できます。文や複合文を指定するとエラーになります。
eval("print('Hello')") # SyntaxError: invalid syntax
引数には信頼できる文字列だけを指定してください。悪意のあるコードを実行される可能性があります。
eval("os.system('rm -rf /')") # 危険!
引数に変数や関数を含む文字列を指定する場合、その変数や関数がスコープ内に存在する必要があります。存在しない場合はエラーになります。
def square(x):
return x ** 2
eval("square(4)") # 16
eval("cube(3)") # NameError: name 'cube' is not defined
この関数を知らないと…
文字列として表された式を動的に評価する必要がある場合に、手動でパースしたり、exec関数を使って無駄な処理を実行してしまいます。
# 文字列をパースして計算する例
expression = "2 * 3 + 4"
tokens = expression.split()
result = int(tokens[0]) * int(tokens[2]) + int(tokens[4])
print(result) # 10
# exec関数を使って評価する例
expression = "2 * 3 + 4"
exec(f"result = {expression}")
print(result) # 10
eval関数を使うと以下のように書くことができます。
expression = "2 * 3 + 4"
result = eval(expression)
print(result) # 10
(23)exec()
引数に与えられた文字列をPythonの文として実行する関数です。
code = """
x = 2
y = 3
print(x + y)
"""
exec(code) # 5
- 注意点
引数には文や複合文を指定できますが、式は指定できません。式を指定するとエラーになります。
exec("x + y") # SyntaxError: Missing parentheses in call to 'exec'
引数には信頼できる文字列だけを指定してください。悪意のあるコードを実行される可能性があります。
exec("os.system('rm -rf /')") # 危険!
引数に変数や関数を含む文字列を指定する場合、その変数や関数がスコープ内に存在する必要があります。存在しない場合はエラーになります。
def square(x):
return x ** 2
exec("print(square(4))") # 16
exec("print(cube(3))") # NameError: name 'cube' is not defined
exec関数は戻り値を返しません。Noneが返されます。
result = exec("print('Hello')")
print(result) # None
exec関数はグローバルやローカルの名前空間を指定することができます。名前空間は辞書として渡します。
exec("print(x + y)", {"x": 2, "y": 3}) # 5
z = 4
exec("print(x + y + z)", {"x": 2, "y": 3}, {"z": z}) # 9
この関数を知らないと…
文字列として表された文を動的に実行する必要がある場合に、eval関数を使って無効な式を評価したり、手動でパースしたりしてしまいます。
# eval関数を使って文を評価する例
code = "print('Hello')"
eval(code) # SyntaxError: invalid syntax
# 文字列をパースして実行する例
code = "x = 2; y = 3; print(x + y)"
tokens = code.split(";")
for token in tokens:
exec(token.strip()) # 5
exec関数を使うと以下のように書くことができます。
code = "x = 2; y = 3; print(x + y)"
exec(code) # 5
(24)filter()
引数に与えられたイテラブルオブジェクトから、条件に合う要素だけを取り出す関数です。
def is_even(x):
return x % 2 == 0
numbers = [1, 2, 3, 4, 5, 6]
evens = filter(is_even, numbers)
print(list(evens)) # [2, 4, 6]
- 注意点
引数には関数とイテラブルオブジェクトを指定します。関数はイテラブルオブジェクトの各要素を引数にとり、真偽値を返すものでなければなりません。
def add_one(x):
return x + 1
numbers = [1, 2, 3, 4, 5, 6]
result = filter(add_one, numbers) # TypeError: 'int' object is not iterable
filter関数はイテレータオブジェクトを返します。リストやタプルなどに変換するには、list()
やtuple()
などの関数を使います。
def is_even(x):
return x % 2 == 0
numbers = [1, 2, 3, 4, 5, 6]
evens = filter(is_even, numbers)
print(evens) # <filter object at 0x000001E8B0A9F7F0>
print(list(evens)) # [2, 4, 6]
引数の関数には無名関数(lambda式)を使うこともできます。これはコードを簡潔に書くために便利です。
numbers = [1, 2, 3, 4, 5, 6]
evens = filter(lambda x: x % 2 == 0, numbers)
print(list(evens)) # [2, 4, 6]
この関数を知らないと…
イテラブルオブジェクトから条件に合う要素を取り出す場合に、for文やif文を使って手動でフィルタリングしたり、リスト内包表記を使って冗長なコードを書いてしまいます。
# for文とif文を使ってフィルタリングする例
def is_even(x):
return x % 2 == 0
numbers = [1, 2, 3, 4, 5, 6]
evens = []
for n in numbers:
if is_even(n):
evens.append(n)
print(evens) # [2, 4, 6]
# リスト内包表記を使ってフィルタリングする例
def is_even(x):
return x % 2 == 0
numbers = [1, 2, 3, 4, 5, 6]
evens = [n for n in numbers if is_even(n)]
print(evens) # [2, 4, 6]
filter関数を使うと以下のように書くことができます。
def is_even(x):
return x % 2 == 0
numbers = [1, 2, 3, 4, 5, 6]
evens = filter(is_even, numbers)
print(list(evens)) # [2, 4, 6]
(25)float()
引数に指定した数値または文字列を浮動小数点数に変換して返します。
x = float(10) # 整数を浮動小数点数に変換
print(x) # 10.0
y = float("3.14") # 文字列を浮動小数点数に変換
print(y) # 3.14
z = float("nan") # 特殊な値を表す文字列も変換できる
print(z) # nan
- 注意点
引数を省略した場合は0.0を返します。
x = float()
print(x) # 0.0
引数に浮動小数点数を表すことができない文字列を指定した場合はValueError
を発生させます。
x = float("abc") # エラー
この関数を知らないと…
数値の計算や比較を行う際に型の不一致によるエラーやバグを引き起こす可能性があります。
x = 3
y = "3.14"
z = x + y
print(z)
# TypeError: unsupported operand type(s) for +: 'int' and 'str'
float関数を使うと以下のように書くことができます。
x = 3
y = "3.14"
z = x + float(y)
print(z) # 6.14
(26)format()
引数に指定した値を書式化した文字列を返します。書式化の方法は、第二引数に指定することができます。
x = format(12345, ",") # 3桁ごとにカンマを入れる
print(x) # 12,345
y = format(0.1234, ".2%") # パーセント表示にして小数点以下2桁にする
print(y) # 12.34%
z = format(255, "x") # 16進数に変換する
print(z) # ff
- 注意点
第二引数を省略した場合は、str関数と同じ結果を返します。
x = format(12345)
print(x) # 12345
第二引数に無効な書式を指定した場合はValueError
を発生させます。
x = format(12345, "a") # エラー
この関数を知らないと…
文字列の連結やフォーマットを行う際に+や%などの演算子を使って複雑なコードを書いてしまいます。
name = "Alice"
age = 20
message = "Hello, my name is " + name + " and I am " + str(age) + " years old."
print(message)
# Hello, my name is Alice and I am 20 years old.
format関数を使うと以下のように書くことができます。
name = "Alice"
age = 20
message = "Hello, my name is {} and I am {} years old.".format(name, age)
print(message)
# Hello, my name is Alice and I am 20 years old.
(27)frozenset()
引数に指定したイテラブルオブジェクトから、要素の追加や削除ができない集合を作成して返します。
x = frozenset([1, 2, 3, 4]) # リストからfrozensetを作成
print(x) # frozenset({1, 2, 3, 4})
y = frozenset("hello") # 文字列からfrozensetを作成
print(y) # frozenset({'h', 'e', 'l', 'o'})
z = frozenset() # 空のfrozensetを作成
print(z) # frozenset()
- 注意点
frozensetはイミュータブルなオブジェクトなので、要素の追加や削除を行おうとするとAttributeError
を発生させます。
x = frozenset([1, 2, 3, 4])
x.add(5) # エラー
x.remove(4) # エラー
frozensetは集合演算を行うことができます。集合演算とは、和集合、積集合、差集合、対称差集合などの演算のことです。
x = frozenset([1, 2, 3, 4])
y = frozenset([3, 4, 5, 6])
z = x | y # 和集合
print(z) # frozenset({1, 2, 3, 4, 5, 6})
w = x & y # 積集合
print(w) # frozenset({3, 4})
v = x - y # 差集合
print(v) # frozenset({1, 2})
u = x ^ y # 対称差集合
print(u) # frozenset({1, 2, 5, 6})
この関数を知らないと…
イテラブルオブジェクトから重複を除くためにset関数を使っても、変更可能なオブジェクトとして扱われるために、辞書のキーや集合の要素になることができません。
s = set({1, 2, 3, 4, 5})
d = {s: "Hello"}
print(d)
# TypeError: unhashable type: 'set'
frozenset関数を使うと以下のように書くことができます。
s = frozenset({1, 2, 3, 4, 5})
d = {s: "Hello"}
print(d)
# {frozenset({1, 2, 3, 4, 5}): 'Hello'}
(28) getattr()
オブジェクトの属性を取得する関数です。第一引数にオブジェクト、第二引数に属性名を文字列で指定します。第三引数にデフォルト値を指定することもできます。属性が存在しない場合には、デフォルト値を返すか、AttributeError
を発生させます。
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
p = Person("Alice", 20)
print(getattr(p, "name")) # Alice
print(getattr(p, "age")) # 20
print(getattr(p, "gender", "unknown")) # unknown
print(getattr(p, "height")) # AttributeError: 'Person' object has no attribute 'height'
- 注意点
属性名は文字列で指定する必要があります。変数や式を使うことはできません。
attr = "name"
print(getattr(p, attr)) # Alice
print(getattr(p, "na" + "me")) # Alice
print(getattr(p, 3)) # TypeError: getattr(): attribute name must be string
この関数を知らないと…
オブジェクトの属性を動的に取得することができません。例えば、ユーザーからの入力に応じてオブジェクトの属性を表示するようなプログラムを作る場合には、getattr関数が便利です。
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
p = Person("Alice", 20)
while True:
attr = input("Enter an attribute name: ")
if attr == "quit":
break
value = getattr(p, attr, None)
if value is None:
print("No such attribute")
else:
print(value)
(29) globals()
現在のグローバルスコープにある変数や関数などのシンボルを辞書として返す関数です。この辞書は実行時に変更可能であり、グローバルスコープに影響を与えます。
x = 10
y = 20
def foo():
print("Hello")
g = globals()
print(g["x"]) # 10
print(g["y"]) # 20
print(g["foo"]) # <function foo at 0x000001E0F8C0A1F0>
g["x"] = 100 # グローバル変数xの値を変更
g["z"] = 30 # グローバル変数zを追加
g["bar"] = lambda: print("World") # グローバル関数barを追加
print(x) # 100
print(z) # 30
foo() # Hello
bar() # World
- 注意点
globals関数は辞書を返すので、その辞書に対して変更を加えると、グローバルシンボルテーブルにも反映されます。
# グローバル変数を定義
x = 10
y = 20
# globals関数の戻り値を変数に代入
g = globals()
# gに対して変更を加える
g['x'] = 100
g['z'] = 30
# グローバルシンボルテーブルが変更されていることを確認
print(x) # 100
print(z) # 30
この関数を知らないと…
グローバルスコープにあるシンボルを動的に参照したり、変更したり、追加したりすることができません。例えば、ユーザーからの入力に応じてグローバル変数の値を表示したり、グローバル関数を呼び出したりするようなプログラムを作る場合には、globals関数が便利です。
x = 10
y = 20
def foo():
print("Hello")
def bar():
print("World")
while True:
name = input("Enter a global symbol name: ")
if name == "quit":
break
g = globals()
if name in g:
value = g[name]
if callable(value):
value() # グローバル関数を呼び出す
else:
print(value) # グローバル変数の値を表示する
else:
print("No such symbol")
(30) hasattr()
オブジェクトが指定した属性を持っているかどうかを真偽値で返す関数です。第一引数にオブジェクト、第二引数に属性名を文字列で指定します。属性が存在する場合にはTrue
を返し、存在しない場合にはFalse
を返します。
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
p = Person("Alice", 20)
print(hasattr(p, "name")) # True
print(hasattr(p, "age")) # True
print(hasattr(p, "gender")) # False
print(hasattr(p, "height")) # False
- 注意点
属性名は文字列で指定する必要があります。変数や式を使うことはできません。
attr = "name"
print(hasattr(p, attr)) # True
print(hasattr(p, "na" + "me")) # True
print(hasattr(p, 3)) # TypeError: hasattr(): attribute name must be string
この関数を知らないと…
オブジェクトの属性の有無を確認するために、例外処理を書く必要があり、コードが冗長になります。例えば、オブジェクトの属性を表示する前に、その属性が存在するかどうかをチェックするようなプログラムを作る場合には、hasattr関数が便利です。
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
p = Person("Alice", 20)
while True:
attr = input("Enter an attribute name: ")
if attr == "quit":
break
if hasattr(p, attr):
print(getattr(p, attr))
else:
print("No such attribute")
(31)hash()
引数に渡したオブジェクトのハッシュ値を返します。ハッシュ値とは、オブジェクトの内容や識別子に基づいて計算される整数のことです。ハッシュ値は、辞書型のキーの比較や集合型の要素の検索などに用いられます。
# 文字列のハッシュ値
s = "Hello, world!"
print(hash(s)) # 5980307948332718216
# 数値のハッシュ値
n = 42
print(hash(n)) # 42
# リストのハッシュ値
l = [1, 2, 3]
print(hash(l)) # TypeError: unhashable type: 'list'
- 注意点
ハッシュ値は、オブジェクトの内容が変更されないことが保証されている場合にのみ有効です。そのため、ミュータブルなオブジェクト(内容を変更できるオブジェクト)はハッシュ可能ではありません。例えば、リストや辞書はハッシュ不可能なオブジェクトです。ハッシュ不可能なオブジェクトに対してhash関数を呼び出すと、TypeError
が発生します。
この関数を知らないと…
オブジェクトの同一性や等価性を判定するのに、==
やis
などの演算子を使ってしまいます。しかし、これらの演算子は、オブジェクトの内容や識別子を直接比較するので、時間やメモリの効率が悪くなります。
# 二つの文字列を比較
s1 = "Hello, world!"
s2 = "Hello, world!"
print(s1 == s2) # True
print(s1 is s2) # False
# 二つの数値を比較
n1 = 42
n2 = 42
print(n1 == n2) # True
print(n1 is n2) # True
hash関数を使うと以下のように書くことができます。
# 二つの文字列のハッシュ値を比較
s1 = "Hello, world!"
s2 = "Hello, world!"
print(hash(s1) == hash(s2)) # True
# 二つの数値のハッシュ値を比較
n1 = 42
n2 = 42
print(hash(n1) == hash(n2)) # True
(32)help()
引数(オブジェクト)に関するヘルプ情報を表示します。引数がない場合は、対話的なヘルプシステムを起動します。ヘルプ情報には、オブジェクトの型、メソッド、属性、ドキュメントなどが含まれます。
# 文字列に関するヘルプ情報を表示する
help(str)
# 対話的なヘルプシステムを起動する
help()
- 注意点
ヘルプ情報は、オブジェクトの定義に基づいて生成されます。そのため、オブジェクトがカスタマイズされている場合や、ドキュメントが不十分な場合は、ヘルプ情報が正確でない場合があります。
# カスタマイズされたクラスのヘルプ情報を表示する
class MyList(list):
def __init__(self, *args):
super().__init__(*args)
self.name = "MyList"
help(MyList)
# ヘルプ情報には、name属性についての説明がない
この関数を知らないと…
オブジェクトに関する情報を得るために、インターネットで検索したり、ソースコードを読んだりする必要があります。しかし、help関数を使えば、簡単にオブジェクトのヘルプ情報を確認することができます。
# インターネットで検索する
# https://docs.python.org/ja/3/library/functions.html#abs
# ソースコードを読む
# https://github.com/python/cpython/blob/master/Python/bltinmodule.c#L2140
# help関数を使う
help(abs)
(33)hex()
引数(整数)を16進数の文字列に変換して返します。16進数とは、0から9までの数字とAからFまでのアルファベットを使って数を表現する方法です。16進数の文字列は、先頭に"0x"が付きます。
n = 255
assert hex(n) == "0xff"
- 注意点
hex関数は、整数以外の数値に対しては使えません。浮動小数点数や複素数に対しては、hex関数を使うとエラーが発生します。浮動小数点数や複素数を16進数に変換するには、別の方法を使う必要があります。
# 浮動小数点数に対してhex関数を使うとエラーが発生する
f = 3.14
hex(f)
# TypeError: 'float' object cannot be interpreted as an integer
# 複素数に対してhex関数を使うとエラーが発生する
c = 1 + 2j
hex(c)
# TypeError: can't convert complex to int
この関数を知らないと…
整数を16進数に変換する際に、自分で計算したり、フォーマット文字列を使ったりする必要があります。しかし、hex関数を使えば、簡単に整数を16進数に変換することができます。
# 自分で計算する
n = 255
digits = "0123456789abcdef"
hex_str = ""
while n > 0:
hex_str = digits[n % 16] + hex_str
n //= 16
hex_str = "0x" + hex_str
assert hex_str == "0xff"
# フォーマット文字列を使う
n = 255
hex_str = f"0x{n:x}"
assert hex_str == "0xff"
# hex関数を使う
n = 255
hex_str = hex(n)
assert hex_str == "0xff"
(34)id()
引数(オブジェクト)の識別子を返します。識別子とは、オブジェクトがメモリ上に存在する場所を表す数値です。識別子は、オブジェクトのライフタイム中に一定であり、同じオブジェクトに対しては常に同じ値を返します。
s = "Hello"
assert id(s) == 140664372249680 # 識別子は実行環境によって異なる場合があります
- 注意点
識別子は、オブジェクトの内容や型とは関係ありません。同じ内容や型のオブジェクトでも、異なる識別子を持つ場合があります。識別子は、オブジェクトの同一性を判定するために使われますが、オブジェクトの等価性を判定するために使われることはありません。
# 同じ内容のオブジェクトでも、異なる識別子を持つ場合がある
s1 = "Hello"
s2 = "Hello"
assert s1 == s2 # True
assert id(s1) != id(s2) # True
# 同じ型のオブジェクトでも、異なる識別子を持つ場合がある
n1 = 1
n2 = 1
assert n1 == n2 # True
assert id(n1) != id(n2) # True
こういうときに便利
オブジェクトの識別値を使って、オブジェクトのコピーの種類を判別することができます。オブジェクトのコピーには、浅いコピーと深いコピーの二種類があります。浅いコピーは、オブジェクトの参照をコピーするだけで、オブジェクトの内容は共有されます。深いコピーは、オブジェクトの内容を完全にコピーするので、オリジナルとコピーは独立したオブジェクトになります。例えば、以下のコードを見てみましょう。
# リストを定義
l = [1, 2, 3]
# 浅いコピーを作成
import copy
l1 = copy.copy(l)
# 深いコピーを作成
l2 = copy.deepcopy(l)
# オリジナルとコピーの識別値を比較
print(id(l) == id(l1)) # False
print(id(l) == id(l2)) # False
# オリジナルとコピーの要素の識別値を比較
print(id(l[0]) == id(l1[0])) # True
print(id(l[0]) == id(l2[0])) # True
# オリジナルの要素を変更
l[0] = 100
# コピーの要素が変更されたか確認
print(l1[0]) # 100
print(l2[0]) # 1
このコードでは、リストlを浅いコピーと深いコピーに分けています。オリジナルとコピーの識別値は異なりますが、オリジナルと浅いコピーの要素の識別値は同じです。これは、浅いコピーがオリジナルの参照をコピーしていることを示しています。そのため、オリジナルの要素を変更すると、浅いコピーの要素も変更されます。一方、オリジナルと深いコピーの要素の識別値は同じですが、オリジナルの要素を変更しても、深いコピーの要素は変更されません。このように、id関数を使って、オブジェクトのコピーの種類を判別することができます。
(35)input()
引数(文字列)を標準出力に表示し、ユーザーからの入力を受け取って返します。引数がない場合は、何も表示しません。ユーザーが入力した文字列は、改行文字を除いて返されます。
# 引数を指定する
name = input("What is your name? ")
print(f"Hello, {name}!")
# 引数を指定しない
s = input()
print(f"You entered: {s}")
- 注意点
input関数は、ユーザーが入力した文字列をそのまま返します。そのため、数値や真偽値などの他の型に変換する必要がある場合は、適切な関数を使ってキャストする必要があります。また、ユーザーが入力をキャンセルした場合や、無効な入力をした場合は、エラーが発生する可能性があります。そのため、input関数を使う際は、エラー処理を行うことが推奨されます。
# 数値に変換する
n = input("Enter a number: ")
n = int(n) # キャストする
print(f"The square of {n} is {n**2}")
# 真偽値に変換する
b = input("Enter True or False: ")
b = bool(b) # キャストする
print(f"The opposite of {b} is {not b}")
# エラー処理を行う
try:
s = input("Enter something: ")
print(f"You entered: {s}")
except EOFError:
print("You cancelled the input")
except Exception as e:
print(f"An error occurred: {e}")
この関数を知らないと…
ユーザーからの入力を受け取るために、標準入力を直接読み込んだり、GUIを作成したりする必要があります。しかし、input関数を使えば、簡単にユーザーからの入力を受け取ることができます。
# 標準入力を直接読み込む
import sys
s = sys.stdin.readline()
print(f"You entered: {s}")
# GUIを作成する
import tkinter as tk
window = tk.Tk()
entry = tk.Entry(window)
entry.pack()
button = tk.Button(window, text="Submit", command=lambda: print(f"You entered: {entry.get()}"))
button.pack()
window.mainloop()
# input関数を使う
s = input("Enter something: ")
print(f"You entered: {s}")
(36)int()
引数(オブジェクト)を整数に変換して返します。引数が数値の場合は、その数値を整数に切り捨てます。引数が文字列の場合は、その文字列を整数として解釈します。引数がない場合は、0を返します。第二引数(基数)を指定すると、その基数に従って引数を整数に変換します。基数とは、数を表現する際に使う記号の種類を表す数値です。基数は、2から36までの整数で指定できます。
# 数値を整数に変換する
f = 3.14
assert int(f) == 3
# 文字列を整数に変換する
s = "123"
assert int(s) == 123
# 引数を指定しない
assert int() == 0
# 基数を指定する
s = "ff"
assert int(s, 16) == 255
- 注意点
int関数は、引数が整数に変換できる場合にのみ使えます。引数が整数に変換できない場合は、エラーが発生します。整数に変換できない場合とは、以下のような場合です。- 引数が数値でも文字列でもない場合
- 引数が文字列であっても、整数として解釈できない場合
- 引数が文字列であっても、基数として指定した値に対応しない場合
# 引数が数値でも文字列でもない場合
l = [1, 2, 3]
int(l)
# TypeError: int() argument must be a string, a bytes-like object or a number, not 'list'
# 引数が文字列であっても、整数として解釈できない場合
s = "Hello"
int(s)
# ValueError: invalid literal for int() with base 10: 'Hello'
# 引数が文字列であっても、基数として指定した値に対応しない場合
s = "ff"
int(s, 2)
# ValueError: invalid literal for int() with base 2: 'ff'
この関数を知らないと…
整数に変換するために、自分で計算したり、正規表現を使ったりする必要があります。しかし、int関数を使えば、簡単に整数に変換することができます。
(37)isinstance()
引数(オブジェクト, クラス)が指定したクラスのインスタンスであるかどうかを真偽値で返します。第二引数には、クラスやクラスのタプルを指定できます。第二引数にクラスのタプルを指定した場合は、そのいずれかのクラスのインスタンスであるかどうかを判定します。
# クラスを定義する
class Animal:
def __init__(self, name):
self.name = name
class Dog(Animal):
def __init__(self, name, breed):
super().__init__(name)
self.breed = breed
# クラスのインスタンスを作成する
a = Animal("Tom")
d = Dog("Bob", "Poodle")
# クラスのインスタンスであるかどうかを判定する
assert isinstance(a, Animal) == True
assert isinstance(d, Dog) == True
assert isinstance(d, Animal) == True # 継承関係にある場合もTrueになる
assert isinstance(a, Dog) == False
- 注意点
isinstance関数は、オブジェクトの型を判定するために使われますが、オブジェクトの内容や振る舞いを判定するために使われることはありません。オブジェクトの内容や振る舞いを判定するには、他の方法を使う必要があります。
# オブジェクトの内容を判定する
s = "Hello"
assert isinstance(s, str) == True # 型を判定する
assert s == "Hello" == True # 内容を判定する
# オブジェクトの振る舞いを判定する
l = [1, 2, 3]
assert isinstance(l, list) == True # 型を判定する
assert hasattr(l, "append") == True # メソッドを判定する
こういうときに便利…
isinstance関数は、オブジェクトの型に応じて処理を分岐させたいときに便利です。 例えば、関数の引数に複数の型のオブジェクトを受け付ける場合に、isinstance関数を使って型チェックを行うことができます。 以下のコードは、引数に文字列や数値、リストなどを受け取り、それぞれに応じたメッセージを出力する関数の例です。
def print_message(obj):
if isinstance(obj, str):
print("This is a string: " + obj)
elif isinstance(obj, (int, float)):
print("This is a number: " + str(obj))
elif isinstance(obj, list):
print("This is a list: " + str(obj))
else:
print("This is something else: " + str(obj))
print_message("Hello") # This is a string: Hello
print_message(3.14) # This is a number: 3.14
print_message([1, 2, 3]) # This is a list: [1, 2, 3]
print_message(True) # This is something else: True
isinstance関数は、第二引数にタプルを渡すことで、複数の型との比較ができます。 この例では、int型とfloat型のどちらかであれば、同じメッセージを出力しています。 また、isinstance関数は、サブクラスのインスタンスも真と判定します。 この例では、bool型はint型のサブクラスであるため、数値として扱われません。 このように、isinstance関数を使うと、オブジェクトの型に応じて処理を分岐させることができます。
(38)issubclass()
引数(クラス1, クラス2)が指定したクラスのサブクラスであるかどうかを真偽値で返します。サブクラスとは、他のクラスから継承したクラスのことです。第二引数には、クラスやクラスのタプルを指定できます。第二引数にクラスのタプルを指定した場合は、そのいずれかのクラスのサブクラスであるかどうかを判定します。
# クラスを定義する
class Animal:
def __init__(self, name):
self.name = name
class Dog(Animal):
def __init__(self, name, breed):
super().__init__(name)
self.breed = breed
class Cat(Animal):
def __init__(self, name, color):
super().__init__(name)
self.color = color
# クラスのサブクラスであるかどうかを判定する
assert issubclass(Dog, Animal) == True
assert issubclass(Cat, Animal) == True
assert issubclass(Dog, Cat) == False
assert issubclass(Dog, (Animal, Cat)) == True # タプルを指定する
- 注意点
issubclass関数は、クラスの継承関係を判定するために使われますが、クラスのインスタンス関係を判定するために使われることはありません。クラスのインスタンス関係を判定するには、isinstance関数を使う必要があります。
# クラスの継承関係を判定する
assert issubclass(Dog, Animal) == True
# クラスのインスタンス関係を判定する
d = Dog("Bob", "Poodle")
assert isinstance(d, Dog) == True
assert isinstance(d, Animal) == True
この関数を知らないと…
クラスの継承関係を判定するために、クラスの属性やメソッドを調べたり、ソースコードを読んだりする必要があります。しかし、issubclass関数を使えば、簡単にクラスの継承関係を判定することができます。
# クラスの属性やメソッドを調べる
assert hasattr(Dog, "breed") == True # Dogクラスにbreed属性がある
assert hasattr(Dog, "name") == True # Dogクラスにname属性がある
assert hasattr(Animal, "breed") == False # Animalクラスにbreed属性がない
assert hasattr(Animal, "name") == True # Animalクラスにname属性がある
# ソースコードを読む
# class Dog(Animal): # DogクラスはAnimalクラスを継承している
# issubclass関数を使う
assert issubclass(Dog, Animal) == True
(39)iter()
引数(オブジェクト)をイテレータに変換して返します。イテレータとは、要素を一つずつ返すことができるオブジェクトのことです。引数には、イテラブルなオブジェクトや呼び出し可能なオブジェクト(関数やメソッドなど)を指定できます。第二引数(終了値)を指定すると、第一引数の呼び出し結果が第二引数と等しくなったときに、イテレータが終了するようになります。
# 呼び出し可能なオブジェクトをイテレータに変換する
import random
it = iter(random.random, 0.5) # random.randomは0から1までの乱数を返す関数
assert next(it) < 0.5 # イテレータから要素を一つ取り出す
assert next(it) < 0.5
# assert next(it) # イテレータが終了した
- 注意点
iter関数は、オブジェクトをイテレータに変換するために使われますが、イテレータをイテラブルに変換するために使われることはありません。イテレータをイテラブルに変換するには、他の方法を使う必要があります。
# イテレータをイテラブルに変換する
it = iter([1, 2, 3])
l = list(it) # リストに変換する
print(l) # [1, 2, 3]
この関数を知らないと…
オブジェクトをイテレータに変換するために、自分でイテレータクラスを定義したり、ジェネレータを使ったりする必要があります。しかし、iter関数を使えば、簡単にオブジェクトをイテレータに変換することができます。
# 自分でイテレータクラスを定義する
class MyIterator:
def __init__(self, iterable):
self.iterable = iterable
self.index = 0
def __next__(self):
if self.index < len(self.iterable):
value = self.iterable[self.index]
self.index += 1
return value
else:
raise StopIteration
l = [1, 2, 3]
it = MyIterator(l)
assert next(it) == 1
assert next(it) == 2
assert next(it) == 3
# assert next(it) # イテレータが終了した
# ジェネレータを使う
def my_iterator(iterable):
for value in iterable:
yield value
l = [1, 2, 3]
it = my_iterator(l)
assert next(it) == 1
assert next(it) == 2
assert next(it) == 3
# assert next(it) # イテレータが終了した
# iter関数を使う
l = [1, 2, 3]
it = iter(l)
assert next(it) == 1
assert next(it) == 2
assert next(it) == 3
# assert next(it) # イテレータが終了した
(40)len()
引数(オブジェクト)の長さを返します。長さとは、オブジェクトが持つ要素の数や文字の数などのことです。引数には、長さを持つことができるオブジェクトを指定できます。長さを持つことができるオブジェクトには、イテラブルなオブジェクトや文字列やバイト列などのように、要素や文字を順番に取り出すことができるオブジェクトが該当します。
# イテラブルなオブジェクトの長さを返す
l = [1, 2, 3]
assert len(l) == 3
# 文字列の長さを返す
s = "Hello"
assert len(s) == 5
# バイト列の長さを返す
b = b"Hello"
assert len(b) == 5
- 注意点
len関数は、オブジェクトの長さを返すために使われますが、オブジェクトの大きさや容量を返すために使われることはありません。オブジェクトの大きさや容量を返すには、他の方法を使う必要があります。
# オブジェクトの大きさを返す
import sys
l = [1, 2, 3]
assert len(l) == 3 # 長さを返す
assert sys.getsizeof(l) == 88 # バイト単位で大きさを返す
# オブジェクトの容量を返す
import array
a = array.array('i', [1, 2, 3])
assert len(a) == 3 # 長さを返す
assert a.itemsize == 4 # 一つの要素が占めるバイト数を返す
assert a.buffer_info()[1] == 3 # 実際に使われている要素の数を返す
assert a.buffer_info()[0] == 140664372249680 # メモリアドレスを返す
この関数を知らないと…
オブジェクトの長さを得るために、自分でカウントしたり、ループを使ったりする必要があります。しかし、len関数を使えば、簡単にオブジェクトの長さを得ることができます。
# 自分でカウントする
s = "Hello"
count = 0
for c in s:
count += 1
assert count == 5
# ループを使う
s = "Hello"
count = 0
while s:
s = s[1:]
count += 1
assert count == 5
# len関数を使う
s = "Hello"
assert len(s) == 5
(41)list()
引数(イテラブルオブジェクト)からリストを作成します。
arr = list(range(5))
print(arr) # [0, 1, 2, 3, 4]
str = list("Hello")
print(str) # ['H', 'e', 'l', 'l', 'o']
- 注意点
引数がない場合には空のリストを返します。
arr = list()
print(arr) # []
この関数を知らないと…
イテラブルオブジェクトをリストに変換する際に、for文やappendメソッドを使って無駄なコードを書いてしまいます。
arr = []
for i in range(5):
arr.append(i)
print(arr) # [0, 1, 2, 3, 4]
list関数を使うと以下のように書くことができます。
arr = list(range(5))
print(arr) # [0, 1, 2, 3, 4]
(42)locals()
現在のローカルスコープにある変数の辞書を返します。
def func():
x = 1
y = 2
print(locals()) # {'x': 1, 'y': 2}
func()
- 注意点
グローバルスコープでは、locals()
とglobals()
は同じ辞書を返します。
x = 1
y = 2
print(locals()) # {'x': 1, 'y': 2, '__name__': '__main__', ...}
print(globals()) # {'x': 1, 'y': 2, '__name__': '__main__', ...}
この関数を知らないと…
ローカルスコープにある変数を確認する際に、個別にprint文を書いてしまいます。
def func():
x = 1
y = 2
print(x) # 1
print(y) # 2
func()
locals関数を使うと以下のように書くことができます。
def func():
x = 1
y = 2
print(locals()) # {'x': 1, 'y': 2}
func()
(43)map()
第一引数(関数)を第二引数(イテラブルオブジェクト)の各要素に適用した結果を返します。
def square(x):
return x ** 2
arr = [1, 2, 3, 4, 5]
result = map(square, arr)
print(list(result)) # [1, 4, 9, 16, 25]
- 注意点
map関数はイテレータを返すので、リストに変換するにはlist関数を使います。
def square(x):
return x ** 2
arr = [1, 2, 3, 4, 5]
result = map(square, arr)
print(result) # <map object at 0x000001E8F1A6B9A0>
print(list(result)) # [1, 4, 9, 16, 25]
この関数を知らないと…
イテラブルオブジェクトの各要素に関数を適用する際に、for文やリスト内包表記を使った冗長なコードを書くことになります。
def square(x):
return x ** 2
arr = [1, 2, 3, 4, 5]
result = []
for x in arr:
result.append(square(x))
print(result) # [1, 4, 9, 16, 25]
map関数を使うと以下のように書くことができます。
def square(x):
return x ** 2
arr = [1, 2, 3, 4, 5]
result = map(square, arr)
print(list(result)) # [1, 4, 9, 16, 25]
(44)max()
引数(イテラブルオブジェクト)の中で最大の要素を返します。
arr = [1, 2, 3, 4, 5]
print(max(arr)) # 5
str = "Hello"
print(max(str)) # o
- 注意点
引数が空の場合にはValueError
を発生させます。
arr = []
print(max(arr)) # ValueError: max() arg is an empty sequence
この関数を知らないと…
イテラブルオブジェクトの中で最大の要素を探す際に、for文やif文を使った冗長なコードを書くことになります。
arr = [1, 2, 3, 4, 5]
max = arr[0]
for x in arr:
if x > max:
max = x
print(max) # 5
max関数を使うと以下のように書くことができます。
arr = [1, 2, 3, 4, 5]
print(max(arr)) # 5
(45)memoryview()
引数(バイト列オブジェクト)のメモリビューを返します。メモリビューは、オブジェクトの内部データを直接アクセスすることができるオブジェクトです。
arr = bytearray(b"Hello")
mv = memoryview(arr)
print(mv) # <memory at 0x000001E8F1A6B9A0>
print(mv[0]) # 72
print(mv[-1]) # 111
- 注意点
メモリビューはイミュータブルなオブジェクトではなく、元のオブジェクトのデータを変更することができます。
arr = bytearray(b"Hello")
mv = memoryview(arr)
mv[0] = 74
print(arr) # bytearray(b'Jello')
こういうときに便利
メモリビューオブジェクトを使うことで、メモリ上のデータを直接参照して操作することができます。これにより、データのコピーを省略してメモリやパフォーマンスを節約することができます。
例えば、画像や音声などのバイナリデータを扱う場合、メモリビューオブジェクトを使ってデータの一部を切り出したり、変換したりすることができます。以下のコードは、Pillowという画像処理ライブラリを使って、画像ファイルをメモリビューオブジェクトに変換し、その一部を別の画像に貼り付ける例です。
from PIL import Image
# 画像ファイルを読み込む
img1 = Image.open('cat.jpg')
img2 = Image.open('dog.jpg')
# 画像をメモリビューオブジェクトに変換する
mv1 = memoryview(img1.tobytes())
mv2 = memoryview(img2.tobytes())
# メモリビューオブジェクトの一部を切り出す
mv1_part = mv1[:100000] # cat.jpgの最初の10万バイト
mv2_part = mv2[100000:200000] # dog.jpgの10万バイト目から20万バイト目
# メモリビューオブジェクトの一部を入れ替える
mv1[:100000] = mv2_part
mv2[100000:200000] = mv1_part
# メモリビューオブジェクトを画像に戻す
img1_new = Image.frombytes(img1.mode, img1.size, mv1)
img2_new = Image.frombytes(img2.mode, img2.size, mv2)
# 画像を保存する
img1_new.save('cat_new.jpg')
img2_new.save('dog_new.jpg')
このように、メモリビューオブジェクトを使うと、画像の一部を簡単に入れ替えることができます。もちろん、他のデータ形式や操作にも応用できます。メモリビューオブジェクトは、メモリ上のデータを効率的に扱うための便利な関数です。
(46)min()
引数(イテラブルオブジェクト)の中で最小の要素を返します。
arr = [1, 2, 3, 4, 5]
print(min(arr)) # 1
str = "Hello"
print(min(str)) # H
- 注意点
引数が空の場合にはValueError
を発生させます。
arr = []
print(min(arr)) # ValueError: min() arg is an empty sequence
この関数を知らないと…
イテラブルオブジェクトの中で最小の要素を探す際に、for文やif文を使った冗長なコードを書いてしまいます。
arr = [1, 2, 3, 4, 5]
min = arr[0]
for x in arr:
if x < min:
min = x
print(min) # 1
min関数を使うと以下のように書くことができます。
arr = [1, 2, 3, 4, 5]
print(min(arr)) # 1
(47)next()
引数(イテレータ)の次の要素を返します。
arr = [1, 2, 3, 4, 5]
it = iter(arr)
print(next(it)) # 1
print(next(it)) # 2
print(next(it)) # 3
- 注意点
引数がイテレータでない場合にはTypeError
を発生させます。
arr = [1, 2, 3, 4, 5]
print(next(arr)) # TypeError: 'list' object is not an iterator
イテレータの要素がなくなった場合にはStopIteration
を発生させます。
arr = [1, 2, 3, 4, 5]
it = iter(arr)
for i in range(6):
print(next(it)) # 1, 2, 3, 4, 5, StopIteration
この関数を知らないと…
イテレータから要素を取り出す際に、for文を使わなければなりません。しかし、for文はイテレータの全要素を回すので、特定の要素だけを取り出したい場合には不便です。その場合、next関数を使って要素を取り出すことができます。
arr = [1, 2, 3, 4, 5]
it = iter(arr)
for x in it:
print(x) # 1, 2, 3, 4, 5
next関数を使うと以下のように書くことができます。
arr = [1, 2, 3, 4, 5]
it = iter(arr)
print(next(it)) # 1
print(next(it)) # 2
print(next(it)) # 3
(48)object()
新しいオブジェクトを作成します。objectはPythonのすべてのクラスの基底クラスです。
obj = object()
print(obj) # <object object at 0x000001E8F1A6B9A0>
print(type(obj)) # <class 'object'>
- 注意点
objectクラスは属性やメソッドを持たないので、オブジェクトに対して操作を行うことはできません。
obj = object()
obj.x = 1 # AttributeError: 'object' object has no attribute 'x'
obj.__str__() # AttributeError: 'object' object has no attribute '__str__'
この関数を知らないと…
自分でクラスを定義するときに、objectクラスを継承しないと、Python 2では新スタイルクラスと古いスタイルクラスの違いによって予期しない動作を引き起こす可能性があります。なお、Python 3では、すべてのクラスが暗黙的にobjectクラスを継承するので、この問題はありません。
# Python 2
class A: # 古いスタイルクラス
pass
class B(object): # 新スタイルクラス
pass
print type(A) # <type 'classobj'>
print type(B) # <type 'type'>
object関数を使うと、以下のように書くことができます。
# Python 2
class A(object): # 新スタイルクラス
pass
class B(object): # 新スタイルクラス
pass
print type(A) # <type 'type'>
print type(B) # <type 'type'>
(49)oct()
引数(整数)を8進数の文字列に変換して返します。
num = 10
print(oct(num)) # 0o12
num = -10
print(oct(num)) # -0o12
- 注意点
引数が整数でない場合にはTypeError
を発生させます。
num = 3.14
print(oct(num)) # TypeError: 'float' object cannot be interpreted as an integer
こういうときに便利
- 8進数で表されたデータを扱うとき、oct関数を使うと、10進数から8進数に簡単に変換できます。
# ファイルのパーミッションを8進数で表示する
import os
file = "test.txt"
mode = os.stat(file).st_mode # 10進数でパーミッションを取得
print(Oct(mode)) # 8進数に変換して表示
# 100644
- 2進数や16進数との相互変換をするとき。8進数は、2進数の3桁ごとに1桁になるので、2進数との変換が容易です。また、16進数は、8進数の2桁ごとに1桁になるので、16進数との変換も容易です。oct関数を使うと、10進数から8進数に変換できるので、2進数や16進数との相互変換に便利です。
# 2進数と8進数の相互変換
bin = "10101010" # 2進数
dec = int(bin, 2) # 10進数に変換
oct = Oct(dec) # 8進数に変換
print(bin, oct) # 2進数と8進数を表示
# 10101010 252
oct = "252" # 8進数
dec = int(oct, 8) # 10進数に変換
bin = bin(dec) # 2進数に変換
print(oct, bin) # 8進数と2進数を表示
# 252 0b10101010
# 16進数と8進数の相互変換
hex = "FF" # 16進数
dec = int(hex, 16) # 10進数に変換
oct = Oct(dec) # 8進数に変換
print(hex, oct) # 16進数と8進数を表示
# FF 377
oct = "377" # 8進数
dec = int(oct, 8) # 10進数に変換
hex = hex(dec) # 16進数に変換
print(oct, hex) # 8進数と16進数を表示
# 377 0xff
(50)open()
引数(ファイル名)を開いてファイルオブジェクトを返します。オプションでモードやエンコーディングなどを指定することができます。
f = open("test.txt", "w", encoding="utf-8")
f.write("Hello, world!")
f.close()
- 注意点
ファイルを開く際には、必ずcloseメソッドを呼び出してファイルを閉じる必要があります。そうしないと、ファイルに対する変更が保存されなかったり、他のプログラムからファイルにアクセスできなかったりする可能性があります。
f = open("test.txt", "w", encoding="utf-8")
f.write("Hello, world!")
# f.close() # 忘れてしまった
with文を使うと、ファイルを自動的に閉じることができます。
with open("test.txt", "w", encoding="utf-8") as f:
f.write("Hello, world!")
# ファイルが自動的に閉じられる
この関数を知らないと…
ファイルを操作する際に、不要なモジュールのインポートが発生します。
import os
os.system("echo Hello, world! > test.txt")
open関数を使うと以下のように書くことができます。
f = open("test.txt", "w", encoding="utf-8")
f.write("Hello, world!")
f.close()
(51)ord()
引数(一文字の文字列)のUnicodeコードポイントを整数として返します。
char = "A"
print(ord(char)) # 65
char = "あ"
print(ord(char)) # 12354
- 注意点
引数が一文字の文字列でない場合にはTypeError
を発生させます。
char = "AB"
print(ord(char)) # TypeError: ord() expected a character, but string of length 2 found
この関数を知らないと…
文字のUnicodeコードポイントを取得する際に、encodeメソッドやint関数を使った冗長なコードを書いてしまいます。
char = "A"
print(int.from_bytes(char.encode("utf-8"), "big")) # 65
ord関数を使うと以下のように書くことができます。
char = "A"
print(ord(char)) # 65
(52)pow()
第一引数(数値)を第二引数(数値)乗した結果を返します。オプションで第三引数(数値)を指定すると、その数値で割った余りを返します。
x = 2
y = 3
print(pow(x, y)) # 8
x = 2
y = 3
z = 5
print(pow(x, y, z)) # 3
- 注意点
第三引数が指定された場合には、第一引数と第二引数は整数でなければなりません。そうでない場合にはTypeError
を発生させます。
x = 2.0
y = 3
z = 5
print(pow(x, y, z)) # TypeError: pow() 3rd argument not allowed unless all arguments are integers
こういうときに便利
この関数は、べき乗や剰余の計算をするときに便利です。例えば、暗号化や復号化のアルゴリズムによく使われます。RSA暗号やエルガマル暗号などの公開鍵暗号では、pow関数を使って秘密鍵や公開鍵を生成したり、メッセージを暗号化、復号化します。pow関数は、**
演算子よりも高速に計算できるので、大きな数を扱うときに有効です。
(53)print()
引数(任意のオブジェクト)を標準出力に表示します。オプションで区切り文字や改行文字などを指定することができます。
print("Hello, world!") # Hello, world!
x = 1
y = 2
print(x, y) # 1 2
x = 1
y = 2
print(x, y, sep=", ") # 1, 2
x = 1
y = 2
print(x, y, end="\n\n") # 1 2
- 注意点
引数がない場合には、空白の行を出力します。
print() #
この関数を知らないと…
オブジェクトを標準出力に表示する際に、sysモジュールやstrメソッドを使った冗長なコードを書いてしまいます。
import sys
x = 1
y = 2
sys.stdout.write(str(x) + " " + str(y) + "\n") # 1 2
print関数を使うと以下のように書くことができます。
x = 1
y = 2
print(x, y) # 1 2
(54)property()
引数(ゲッター関数、セッター関数、デリーター関数、ドキュメント文字列)からプロパティオブジェクトを作成します。プロパティオブジェクトは、クラスの属性に対してゲッター、セッター、デリーター、ドキュメンテーションの動作を定義することができます。
class Person:
def __init__(self, name):
self._name = name
def get_name(self):
return self._name
def set_name(self, value):
self._name = value
def del_name(self):
del self._name
name = property(get_name, set_name, del_name, "name property")
p = Person("Alice")
print(p.name) # Alice
p.name = "Bob"
print(p.name) # Bob
del p.name
print(p.name) # AttributeError: 'Person' object has no attribute '_name'
- 注意点
引数はすべてオプションですが、少なくともゲッター関数かセッター関数のどちらかは指定する必要があります。そうでない場合にはTypeError
を発生させます。
class Person:
def __init__(self, name):
self._name = name
name = property() # TypeError: property expected at least 1 argument, got 0
p = Person("Alice")
この関数を知らないと…
クラスの属性に対して、直接アクセスや変更を許可してしまうと、不正な値や予期せぬエラーが発生する可能性があります。また、属性の値を取得や設定するために、わざわざメソッドを呼び出す必要があります。property関数を使うと、属性のアクセスを制御しつつ、メソッドを呼び出さずに属性のように扱うことができます。
(55)range()
引数(開始値、終了値、ステップ値)から範囲オブジェクトを作成します。範囲オブジェクトは、開始値から終了値までのステップ値ごとの整数のシーケンスを表します。
r = range(10)
print(r) # range(0, 10)
print(list(r)) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
r = range(1, 10, 2)
print(r) # range(1, 10, 2)
print(list(r)) # [1, 3, 5, 7, 9]
- 注意点
引数はすべて整数でなければなりません。そうでない場合にはTypeError
を発生させます。
r = range(1.0, 10.0, 0.5) # TypeError: 'float' object cannot be interpreted as an integer
範囲オブジェクトはイテラブルですが、イテレータではありません。そのため、next関数を使って次の要素を取得することはできません。
r = range(10)
print(next(r)) # TypeError: 'range' object is not an iterator
この関数を知らないと…
整数のシーケンスを作成する際に、リスト内包表記やfor文を使った冗長なコードを書いてしまいます。
r = [x for x in range(10)]
print(r) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
r = []
for x in range(10):
r.append(x)
print(r) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
range関数を使うと以下のように書くことができます。
r = range(10)
print(r) # range(0, 10)
print(list(r)) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
(56)repr()
引数(object)のオブジェクトを、Pythonが復元できる文字列に変換して返します。reprはrepresentationの略です。この関数は、デバッグやログ出力などに使われます。
x = [1, 2, 3]
y = "Hello, world!"
z = 3.14
print(repr(x)) # '[1, 2, 3]'
print(repr(y)) # "'Hello, world!'"
print(repr(z)) # '3.14'
- 注意点
repr関数は、可能であれば、eval関数で評価すると元のオブジェクトに戻るような文字列を返すべきと定義されています。eval関数は、引数の文字列をPythonの式として実行する関数です。
x = [1, 2, 3]
s = repr(x) # '[1, 2, 3]'
x2 = eval(s) # [1, 2, 3]
print(x == x2) # True
ただし、repr関数が必ずしもeval関数で復元できる文字列を返すとは限りません。例えば、組み込みのdatetimeモジュールのdateクラスのオブジェクトをrepr関数で変換すると、以下のようになります。
import datetime
d = datetime.date(2023, 4, 20)
print(repr(d)) # 'datetime.date(2023, 4, 20)'
この文字列は、eval関数で評価するとエラーになります。なぜなら、datetimeモジュールがインポートされていないと、datetime.date
という名前が認識されないからです。
s = repr(d) # 'datetime.date(2023, 4, 20)'
d2 = eval(s) # NameError: name 'datetime' is not defined
このように、repr関数が返す文字列は、オブジェクトの型や内容を表すものであって、必ずしもPythonの式として有効なものではありません。そのため、repr関数を使うときは、そのオブジェクトがどのような文字列表現になるかを確認することが重要です。
この関数を知らないと…
オブジェクトの内容や型を確認するときに、str関数やprint関数だけを使ってしまうと、オブジェクトの正確な表現がわからないことがあります。例えば、文字列オブジェクトをstr関数やprint関数で変換すると、クオーテーションマークが省略されます。
s = "Hello, world!"
print(str(s)) # Hello, world!
print(s) # Hello, world!
これでは、sが文字列オブジェクトであることがわかりにくいです。repr関数を使うと、クオーテーションマークが付いて、文字列オブジェクトであることが明確になります。
s = "Hello, world!"
print(repr(s)) # 'Hello, world!'
(57)reversed()
引数(シーケンスオブジェクト)の逆順のイテレータを返します。
arr = [1, 2, 3, 4, 5]
it = reversed(arr)
print(it) # <list_reverseiterator object at 0x000001E8F1A6B9A0>
print(list(it)) # [5, 4, 3, 2, 1]
str = "Hello"
it = reversed(str)
print(it) # <reversed object at 0x000001E8F1A6B9A0>
print("".join(it)) # olleH
- 注意点
引数がシーケンスオブジェクトでない場合にはTypeError
を発生させます。
num = 12345
it = reversed(num) # TypeError: 'int' object is not reversible
この関数を知らないと…
シーケンスオブジェクトの逆順のイテレータを作成する際に、スライスやfor文を使うこととなり、可読性が低下します。
arr = [1, 2, 3, 4, 5]
it = iter(arr[::-1])
print(it) # <list_iterator object at 0x000001E8F1A6B9A0>
print(list(it)) # [5, 4, 3, 2, 1]
str = "Hello"
it = ""
for x in str:
it = x + it
print(it) # olleH
reversed関数を使うと以下のように書くことができます。
arr = [1, 2, 3, 4, 5]
it = reversed(arr)
print(it) # <list_reverseiterator object at 0x000001E8F1A6B9A0>
print(list(it)) # [5, 4, 3, 2, 1]
str = "Hello"
it = reversed(str)
print(it) # <reversed object at 0x000001E8F1A6B9A0>
print("".join(it)) # olleH
(58)round()
第一引数(数値)を第二引数(整数)で指定した桁数に丸めた結果を返します。第二引数が指定されない場合には、整数に丸めます。
num = 3.14159
print(round(num)) # 3
num = 3.14159
digits = 2
print(round(num, digits)) # 3.14
- 注意点
第二引数が負の場合には、10のべき乗の位に丸めます。
num = 12345
digits = -2
print(round(num, digits)) # 12300
この関数を知らないと…
数値を四捨五入する際に、10のべき乗をかけたり割ったりして煩雑なコードを書いてしまいます。
num = 3.14159
assert int(num + 0.5) == 3
assert int(num * 100 + 0.5) / 100 == 3.14
round関数を使うと以下のように書くことができます。
num = 3.14159
assert round(num) == 3
assert round(num, 2) == 3.14
(59)set()
引数(イテラブルオブジェクト)から重複を除いた集合を作成します。
arr = [1, 2, 3, 4, 4, 5]
s = set(arr)
print(s) # {1, 2, 3, 4, 5}
- 注意点
集合は順序がないので、インデックスやスライスで要素にアクセスすることはできません。
s = {1, 2, 3, 4, 5}
print(s[0]) # TypeError: 'set' object is not subscriptable
この関数を知らないと…
リストやタプルなどのイテラブルオブジェクトから重複を除くために、ループやif文を使って複雑な処理をする必要があります。
arr = [1, 2, 3, 4, 4, 5]
result = []
for x in arr:
if x not in result:
result.append(x)
print(result) # [1, 2, 3, 4, 5]
set関数を使うと以下のように書くことができます。
arr = [1, 2, 3, 4, 4, 5]
result = set(arr)
print(result) # {1, 2, 3, 4, 5}
(60)setattr()
オブジェクトに指定した名前の属性を設定します。属性が存在しない場合は新しく作成されます。
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
p = Person("Alice", 20)
setattr(p, "gender", "female") # p.gender = "female" と同じ
print(p.gender) # female
- 注意点
属性名は文字列で指定する必要があります。変数や式では指定できません。
p = Person("Alice", 20)
attr = "gender"
setattr(p, attr, "female") # OK
setattr(p, "gen" + "der", "female") # OK
setattr(p, attr + 1, "female") # TypeError: can only concatenate str (not "int") to str
この関数を知らないと…
オブジェクトの属性を動的に設定することができません。属性名をハードコードする必要があります。
p = Person("Alice", 20)
p.gender = "female" # OK
p.attr = "female" # NG (attrという属性が作成される)
setattr関数を使うと以下のように書くことができます。
p = Person("Alice", 20)
attr = "gender"
setattr(p, attr, "female") # OK (p.gender = "female" と同じ)
(61)slice()
引数(シーケンス)を指定した範囲で切り出したスライスオブジェクトを返します。
s = "Hello, world!"
sl = slice(7, 12) # インデックス7から12(終端の前まで)の範囲を指定
print(s[sl]) # スライスオブジェクトをインデックスとして使用
# 出力: World
- 注意点
slice関数は、スライスオブジェクトを作成するだけで、シーケンスを切り出すわけではありません。切り出すには、スライスオブジェクトをシーケンスのインデックスとして使用する必要があります。
s = "Hello, world!"
sl = slice(7, 12)
print(sl) # スライスオブジェクトをそのまま出力
# 出力: slice(7, 12, None)
この関数を知らないと…
スライス操作を行う際に、コロンを使った記法を使わざるを得ません。しかし、コロンを使った記法は、スライスの範囲を動的に変更することができません。例えば、以下のようなコードはエラーになります。
s = "Hello, world!"
start = 7
end = 12
print(s[start:end]) # これは正常に動作する
# 出力: World
print(s[start:]) # これも正常に動作する
# 出力: world!
print(s[start::2]) # これも正常に動作する
# 出力: Wrd
print(s[start::end]) # これはエラーになる
# 出力: SyntaxError: invalid syntax
slice関数を使うと、以下のように書くことができます。
s = "Hello, world!"
start = 7
end = 12
sl1 = slice(start, end) # ステップなし
sl2 = slice(start, None) # 終端なし
sl3 = slice(start, None, 2) # 終端なし、ステップ2
sl4 = slice(start, None, end) # 終端なし、ステップend
print(s[sl1]) # これは正常に動作する
# 出力: World
print(s[sl2]) # これも正常に動作する
# 出力: world!
print(s[sl3]) # これも正常に動作する
# 出力: Wrd
print(s[sl4]) # これも正常に動作する
# 出力: W
slice関数は、スライス操作をより柔軟に行うための便利な関数です。スライスオブジェクトを作成して、シーケンスのインデックスとして使用することで、シーケンスの一部を切り出すことができます。
(62)sorted()
引数(イテラブルオブジェクト)の要素をソートした新しいリストを返します。
arr = [5, 2, 4, 1, 3]
result = sorted(arr)
print(result) # [1, 2, 3, 4, 5]
- 注意点
sorted関数は引数のオブジェクトを変更しません。新しいリストを作成して返します。引数のオブジェクトを変更するには、sortメソッドを使います。
arr = [5, 2, 4, 1, 3]
result = sorted(arr)
print(arr) # [5, 2, 4, 1, 3]
print(result) # [1, 2, 3, 4, 5]
arr.sort()
print(arr) # [1, 2, 3, 4, 5]
この関数を知らないと…
イテラブルオブジェクトの要素をソートするために、ループやif文を使って複雑な処理を行う必要があります。また、ソートした結果を別のリストに保存するために、コピーを作る必要があります。
arr = [5, 2, 4, 1, 3]
result = arr.copy()
for i in range(len(result)):
for j in range(i + 1, len(result)):
if result[i] > result[j]:
result[i], result[j] = result[j], result[i]
print(arr) # [5, 2, 4, 1, 3]
print(result) # [1, 2, 3, 4, 5]
sorted関数を使うと以下のように書くことができます。
arr = [5, 2, 4, 1, 3]
result = sorted(arr)
print(arr) # [5, 2, 4, 1, 3]
print(result) # [1, 2, 3, 4, 5]
(63)staticmethod()
メソッドを静的メソッドに変換します。静的メソッドは、クラスやインスタンスに依存しないメソッドです。静的メソッドは、クラス名やインスタンスから呼び出すことができますが、第一引数にself
やcls
を受け取りません。
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
@staticmethod
def say_hello():
print("Hello")
p = Person("Alice", 20)
Person.say_hello() # Hello
p.say_hello() # Hello
- 注意点
静的メソッドは、クラスの属性やメソッドにアクセスすることができません。クラスの属性やメソッドにアクセスするには、クラスメソッドを使います。
class Person:
count = 0
def __init__(self, name, age):
self.name = name
self.age = age
Person.count += 1
@staticmethod
def get_count():
return Person.count # クラス名を明示的に指定する必要がある
@classmethod
def get_count2(cls):
return cls.count # clsを使ってクラスの属性にアクセスできる
p = Person("Alice", 20)
print(Person.get_count()) # 1
print(Person.get_count2()) # 1
この関数を知らないと…
クラスやインスタンスに関係なく共通の処理を行うメソッドを作ることができません。クラスやインスタンスの属性やメソッドを使わないメソッドを定義すると、不要なself
やcls
を引数に受け取る必要があります。
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def say_hello(self): # selfを引数に受け取る必要がある
print("Hello")
p = Person("Alice", 20)
p.say_hello() # Hello
staticmethod関数を使うと以下のように書くことができます。
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
@staticmethod
def say_hello(): # selfを引数に受け取らない
print("Hello")
p = Person("Alice", 20)
p.say_hello() # Hello
(64)str()
引数(オブジェクト)を文字列に変換します。
num = 123
s = str(num)
print(s) # '123'
print(type(s)) # <class 'str'>
- 注意点
str関数は引数のオブジェクトの__str__メソッドを呼び出して文字列を返します。__str__メソッドはオブジェクトの「非公式な」文字列表現を返すメソッドです。__str__メソッドが定義されていない場合は、__repr__メソッドが呼び出されます。__repr__メソッドはオブジェクトの「公式な」文字列表現を返すメソッドです。
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return f"{self.name} is {self.age} years old."
def __repr__(self):
return f"Person(name='{self.name}', age={self.age})"
p = Person("Alice", 20)
print(str(p)) # Alice is 20 years old.
print(repr(p)) # Person(name='Alice', age=20)
この関数を知らないと…
オブジェクトを文字列に変換することができません。文字列として扱いたい場合に、エラーが発生する可能性があります。
num = 123
print("The number is " + num) # TypeError: can only concatenate str (not "int") to str
str関数を使うと以下のように書くことができます。
num = 123
print("The number is " + str(num)) # The number is 123
(65)sum()
引数(イテラブルオブジェクト)の要素の合計を返します。オプションで、第二引数に初期値を指定できます。
arr = [1, 2, 3, 4, 5]
result = sum(arr)
print(result) # 15
result = sum(arr, 10) # 初期値を10に指定
print(result) # 25
- 注意点
引数の要素は数値でなければなりません。文字列や他の型の要素を含む場合は、エラーが発生します。
arr = [1, 2, "3", 4, 5]
result = sum(arr) # TypeError: unsupported operand type(s) for +: 'int' and 'str'
この関数を知らないと…
イテラブルオブジェクトの要素の合計を求めるために、ループや変数を使って冗長なコードを書くことになります。
arr = [1, 2, 3, 4, 5]
result = 0
for x in arr:
result += x
print(result) # 15
sum関数を使うと以下のように書くことができます。
arr = [1, 2, 3, 4, 5]
result = sum(arr)
print(result) # 15
(66)super()
親クラスのオブジェクトを返します。親クラスのオブジェクトは、サブクラスのオブジェクトから親クラスの属性やメソッドにアクセスするために使われます。
class Animal:
def __init__(self, name):
self.name = name
def sound(self):
print("...")
class Dog(Animal):
def __init__(self, name, breed):
super().__init__(name) # 親クラスの__init__メソッドを呼び出す
self.breed = breed
def sound(self):
super().sound() # 親クラスのsoundメソッドを呼び出す
print("Woof")
d = Dog("Spot", "Labrador")
d.sound() # ... Woof
- 注意点
super関数は、クラスの継承関係に基づいて親クラスのオブジェクトを返します。引数にクラスやインスタンスを指定することもできますが、通常は引数なしで使われます。
class Animal:
def __init__(self, name):
self.name = name
def sound(self):
print("...")
class Dog(Animal):
def __init__(self, name, breed):
Animal.__init__(self, name) # 親クラスの__init__メソッドを直接呼び出す
self.breed = breed
def sound(self):
Animal.sound(self) # 親クラスのsoundメソッドを直接呼び出す
print("Woof")
d = Dog("Spot", "Labrador")
d.sound() # ... Woof
この関数を知らないと…
サブクラスのオブジェクトから親クラスの属性やメソッドにアクセスすることができません。親クラスの名前やインスタンスを明示的に指定する必要があります。
class Animal:
def __init__(self, name):
self.name = name
def sound(self):
print("...")
class Dog(Animal):
def __init__(self, name, breed):
self.name = name # 親クラスの属性を直接設定する
self.breed = breed
def sound(self):
print("...") # 親クラスのメソッドをコピーする
print("Woof")
d = Dog("Spot", "Labrador")
d.sound() # ... Woof
super関数を使うと以下のように書くことができます。
class Animal:
def __init__(self, name):
self.name = name
def sound(self):
print("...")
class Dog(Animal):
def __init__(self, name, breed):
super().__init__(name) # 親クラスの__init__メソッドを呼び出す
self.breed = breed
def sound(self):
super().sound() # 親クラスのsoundメソッドを呼び出す
print("Woof")
d = Dog("Spot", "Labrador")
d.sound() # ... Woof
(67)tuple()
引数(イテラブルオブジェクト)からタプルを作成します。タプルは、変更できない順序付きのコレクションです。
arr = [1, 2, 3, 4, 5]
t = tuple(arr)
print(t) # (1, 2, 3, 4, 5)
print(type(t)) # <class 'tuple'>
- 注意点
タプルは変更できないので、要素の追加や削除、変更などの操作はできません。
t = (1, 2, 3, 4, 5)
t[0] = 10 # TypeError: 'tuple' object does not support item assignment
t.append(6) # AttributeError: 'tuple' object has no attribute 'append'
t.remove(5) # AttributeError: 'tuple' object has no attribute 'remove'
この関数を知らないと…
イテラブルオブジェクトからタプルを作ることができません。タプルとして扱いたい場合に、エラーが発生する可能性があります。
arr = [1, 2, 3, 4, 5]
print(arr + (6, 7)) # TypeError: can only concatenate list (not "tuple") to list
tuple関数を使うと以下のように書くことができます。
arr = [1, 2, 3, 4, 5]
t = tuple(arr)
print(t + (6, 7)) # (1, 2, 3, 4, 5, 6, 7)
(68)type()
引数(オブジェクト)の型を返します。型とは、オブジェクトの種類や特徴を表すものです。
num = 123
s = "Hello"
t = (1, 2, 3)
print(type(num)) # <class 'int'>
print(type(s)) # <class 'str'>
print(type(t)) # <class 'tuple'>
- 注意点
type関数は、引数が一つの場合は型を返しますが、引数が三つの場合は新しい型を作成します。引数が三つの場合は、第一引数に型の名前、第二引数に基底クラスのタプル、第三引数に属性やメソッドの辞書を指定します。
# 引数が一つの場合
num = 123
print(type(num)) # <class 'int'>
# 引数が三つの場合
Person = type("Person", (object,), {"name": "Alice", "age": 20, "say_hello": lambda self: print(f"Hello, I'm {self.name}.")})
p = Person()
print(type(p)) # <class '__main__.Person'>
print(p.name) # Alice
print(p.age) # 20
p.say_hello() # Hello, I'm Alice.
この関数を知らないと…
オブジェクトの型を調べることができません。型によってオブジェクトの振る舞いや操作が異なるので、エラーが発生する可能性があります。
num = 123
s = "Hello"
print(num + s) # TypeError: unsupported operand type(s) for +: 'int' and 'str'
type関数を使うと以下のように書くことができます。
num = 123
s = "Hello"
print(type(num)) # <class 'int'>
print(type(s)) # <class 'str'>
print(str(num) + s) # 123Hello
(69)vars()
引数に指定したオブジェクトの属性と値の辞書を返します。引数を省略した場合は、現在のローカルシンボルテーブルを返します。
class Sample:
def __init__(self, x, y):
self.x = x
self.y = y
s = Sample(1, 2)
print(vars(s)) # {'x': 1, 'y': 2}
print(vars()) # 現在のローカルシンボルテーブルを表示
- 注意点
vars()はモジュール、クラス、インスタンスなどの属性を持つオブジェクトに対して有効ですが、数値や文字列などの属性を持たないオブジェクトに対してはTypeError
を発生させます。
print(vars(1)) # TypeError: vars() argument must have __dict__ attribute
この関数は、オブジェクトの内部状態を調べたり、動的に属性を追加したりするときに便利です。
class Sample:
def __init__(self, x, y):
self.x = x
self.y = y
obj = Sample(1, 2)
print(vars(obj))
# {'x': 1, 'y': 2}
# 動的に属性を追加
vars(obj)['z'] = 3
print(vars(obj))
# {'x': 1, 'y': 2, 'z': 3}
# オブジェクトの属性を辞書として扱える
for key, value in vars(obj).items():
print(f"{key} = {value}")
# x = 1
# y = 2
# z = 3
このように、vars関数を使うと、オブジェクトの属性を辞書として扱うことができます。これは、オブジェクト指向プログラミングの柔軟性を高めるのに役立ちます。
(70)zip()
複数のイテラブルオブジェクトを引数にとり、それらの要素をまとめたイテレータを返します。イテレータの要素は、引数のイテラブルオブジェクトの要素を対応させたタプルになります。
a = [1, 2, 3]
b = ['a', 'b', 'c']
c = zip(a, b) # イテレータを返す
print(list(c)) # [(1, 'a'), (2, 'b'), (3, 'c')]
- 注意点
引数のイテラブルオブジェクトの長さが異なる場合、zip()
は最も短いイテラブルオブジェクトが終了するまで要素をまとめます。残りの要素は無視されます。
a = [1, 2, 3, 4]
b = ['a', 'b', 'c']
c = zip(a, b) # イテレータを返す
print(list(c)) # [(1, 'a'), (2, 'b'), (3, 'c')]
この関数を知らないと…
複数のイテラブルオブジェクトの要素をまとめるためには、for文やリスト内包表記などを使って実装する必要がありますが、これはコードが冗長になります。
a = [1, 2, 3]
b = ['a', 'b', 'c']
c = []
for i in range(min(len(a), len(b))):
c.append((a[i], b[i]))
print(c) # [(1, 'a'), (2, 'b'), (3, 'c')]
zip関数を使うと以下のように書くことができます。
a = [1, 2, 3]
b = ['a', 'b', 'c']
c = zip(a, b) # イテレータを返す
print(list(c)) # [(1, 'a'), (2, 'b'), (3, 'c')]
(71)__import__()
引数に指定したモジュール名の文字列に対応するモジュールをインポートします。戻り値はインポートされたモジュールオブジェクトです。
math = __import__('math') # mathモジュールをインポート
print(math.pi) # 3.141592653589793
- 注意点
__import__()
は低レベルな関数であり、通常はimport文を使ってモジュールをインポートすることが推奨されます。__import__()
は主にモジュール名が動的に決まる場合や、カスタマイズされたインポート機構を実装する場合に使われます。
module_name = input('Enter a module name: ') # モジュール名を入力
module = __import__(module_name) # 入力されたモジュールをインポート
この関数を知らないと…
モジュール名が文字列として与えられた場合、import文ではモジュールをインポートすることができません。代わりに、importlibモジュールのimport_module関数を使うことができますが、これは内部的に__import__()
を呼び出しています。
import importlib
math = importlib.import_module('math') # mathモジュールをインポート
print(math.pi) # 3.141592653589793
__import__()
関数を使うと以下のように書くことができます。
math = __import__('math') # mathモジュールをインポート
print(math.pi) # 3.141592653589793
おわりに
最後までお読みいただきありがとうございます。
各関数の機能や注意点、使いどころを理解することで、Pythonのコードをより効率的に、簡潔に、美しく書くことができます。
Pythonは、データ分析や機械学習、ウェブ開発やゲーム開発など、様々な分野で活躍できるプログラミング言語です。Pythonの組み込み関数を使いこなすことは、Pythonの基礎を固めることにつながります。Pythonの組み込み関数を使って、素敵なコードを書いてください。それでは、また。
弊社Nucoでは、他にも様々なお役立ち記事を公開しています。よかったら、Organizationのページも覗いてみてください。
また、Nucoでは一緒に働く仲間も募集しています!興味をお持ちいただける方は、こちらまで。