Pythonやそのライブラリを含む他の要素においても、バージョンアップが行われるたびに、これまでの書き方が非推奨とされるケースが相当あります。ただし、インターネット上には古いコードや非推奨の情報が存在しています。それが非推奨であるということを知らない場合には、新しい書き方があるにもかかわらず古い書き方を使用してしまうケースが考えられます。
「この書き方は何だ?見たことないぞ」と思って調査してみると、現在では非推奨になった昔ながらの書き方だったりすることがあります。時間を費やして調査した結果、それが非推奨だったりすると困るわけです。ムダな時間を省くためにも、そのような「現在は使えない、または将来的に使えなくなる(非推奨)」の書き方についてメモします。
とはいえ、気付いた時に追記する予定ですので、増えすぎることはないでしょう。
%
を使った文字列の書式設定文字列のフォーマットを定義する際、format()
やf文字列
を使った記法が現在の主流です。ただ、C言語のprintf()
に準拠したような演算子を使った記法で表現する方法もあります。
%
name = "山田"
age = 30
print("私の名前は%sで、%d歳です。" % (name, age))
name = "山田"
age = 30
print(f"私の名前は{name}で、{age}歳です。")
str.format()
name = "山田"
age = 30
print("私の名前は{}で、{}歳です。".format(name, age))
C言語のprintf()
では、任意の文字列において「値を出力する位置にどんな型で出力するか」をパーセント付の識別子で表現します。%s
だった場合、文字列を指定された箇所に出力する、といった具合です。この記法がPythonでも使えます。
ただ、「せっかく動的型付け言語なのに、文字列編集をするときに型を気にしないといけないのは面倒だぜ!」と思ったのかはわかりませんが、前述のとおりf-stringsが主流だと思います。こっちは読みやすく、式の評価もサポートしているため、f"結果: {2 * 3}"
のように直接計算結果を埋め込むことができます。format()
関数も一応見かけますね、%
ほどは廃れていない印象。
f = open("example.txt", "r")
content = f.read()
f.close() # 忘れると問題が発生する可能性あり
with open("example.txt", "r") as f:
content = f.read()
# 自動的にクローズされる
with
はそのブロックを抜けるときに、close
メソッドを勝手に呼び出してクローズしてくれるので、クローズ忘れがなくなりますしコードも読みやすくなります。しかし、with
には更なる利点があります。
ファイルオブジェクトを扱うときに with キーワードを使うのは良い習慣です。 その利点は、処理中に例外が発生しても必ず最後にファイルをちゃんと閉じることです。
オフィシャルのドキュメントに書いてある上記の点だけを鑑みても、with
を利用するほうが良いと判断できます。
pd.np
pd.np
経由でNumPy関数にアクセスimport pandas as pd
result = pd.np.sqrt(4) # 非推奨
import pandas as pd
import numpy as np
result = np.sqrt(4) # 推奨
pandasをインポートすると、同時にNumPyもインポートされます。このとき、pd.np
という書き方をすることで明示的にNumPyをインポートしていなくてもNumPyが持つ機能にアクセスできるようになります。import numpy
を書かなくてもいいという、メリット?うーん、メリットかなぁこれ。
ただ、NumPyの関数などを使うならちゃんとインポートした方がコードの保守性が高いと思われたのか、現在では非推奨です。そのうち、この機能が削除されると思います。
dict.has_key()
d = {"key": "value"}
if d.has_key("key"): # Python 3では削除済み
print("キーが存在します")
in
演算子d = {"key": "value"}
if "key" in d:
print("キーが存在します")
さすがに古すぎる話題ですが、Python2には辞書に任意のキーが存在するかをチェックするhas_key()
が存在していました。Python3系ではこいつは削除されており、そもそもエラーになります。現在はin
を利用します。
xrange
はもうないぞrange
とxrange
# Python 2
for i in range(1000000): # メモリを大量に消費
pass
for i in xrange(1000000): # メモリ効率が良い
pass
range
(Python 3)Python 3では、range()
はイテレータになり、xrange()
は削除されました。
# Python 3
for i in range(1000000): # メモリ効率が良い
pass
Python2では、range()
はリストを生成し、xrange()
はイテレータを生成していました。Python3ではxrange()
がなくなり、range()
に統合されました。
__init__
、__repr__
などの実装class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __repr__(self):
return f"Person(name={self.name}, age={self.age})"
def __eq__(self, other):
if not isinstance(other, Person):
return False
return self.name == other.name and self.age == other.age
@dataclass
デコレータの使用 (Python 3.7以降)from dataclasses import dataclass
@dataclass
class Person:
name: str
age: int
# __init__, __repr__, __eq__などが自動的に生成される
dataclassデコレータを使えば、__init__()
で引数をわざわざインスタンス変数に代入したり、__eq__()
を手で書く必要がなくなりました。Python3.7以降で利用できます。
axis
mean()
などの関数にaxis
パラメータなしで使用mean_value = df.mean() # 警告なしだが、axis=0を暗黙的に使用
厳密に「古い方法」かまでははっきりしなかったものの、こういう書き方は多くはないものの見かける。確かに省略できるけども、パッと見で「どっち?」ってなるんだよなぁ。
axis
を指定# 列ごとの平均
mean_value = df.mean(axis=0)
# 行ごとの平均
mean_value = df.mean(axis=1)
単純にこっちの書き方が省略されるよりわかりやすいので、axis
は省略できるとしても書いておいたほうがいいと思います。