以下の内容はhttps://shikaku-sh.hatenablog.com/entry/python-practice-ioより取得しました。


python 入出力 学習

Python チュートリアルを読んで気になったところをメモ。

str と repr の違い

よくある疑問なんだと思うけど、自分用に整理。

基本的には、どちらも様々な型のデータを文字列に変換するための関数です。で、どういうときにどっちを使うのか?

  • repr(obj)
    • 開発者向けの文字列を出力する
    • 原則として eval(repr(obj)) == obj が成り立つように設計されている
    • デバッグやログで eval() 評価の結果の値を「正確な情報」として知ることができる
  • str(obj)
    • ユーザー向けの文字列表現
    • 通常のフォーマットとして出力される

実際の話だと repr() を、ユーザーが str() ほど直接的に利用するのかというと、そこまで多いわけではないと思います。利用回数が多くなるのは、おそらく str() になるのが殆どのケースのはず。(基本的に repr は representation = 「表示」の意味のはずです)

個人的な用途のポイントとしては 改行文字 が含まれる可能性のある文字列は repr() を使って、出力やデバッグしたほうがよいケースはあると思う。もちろん、改行したほうが読みやすいケースもあったり、文字列だと '' で括られたりもする癖は eval() の都合だと思うけど開発用途だと留意は必要。

s = "hello\nworld"
print(s)
print(repr(s))  # 'hello\nworld'

内部的に利用されているケースが考えられるけど、その内部的な動きを意識しないと困るケースは少ないと思う。

また、ライブラリを作るときに __repr__ を定義しておく必要があるかというと C#[DebuggerDisplay] 属性を付ける必要があるかどうかと、考え方は似ていると思う。(ベストプラクティスとしては、どちらもセットで実装するべき)

class Sample:
    def __init__(self, id, name):
        self.id = id
        self.name = name

    def __repr__(self):
        return f"<Sample id={self.id}, name='{self.name}'>"

    def __str__(self):
        return f"{self.name} (#{self.id})"

# テストコード
s = Sample(1, "Alice")

print(s)
print(repr(s))
Alice (#1)
<Sample id=1, name='Alice'>

基本的にはデバッグの操作をやりやすくするための機能として repr() を使用する。

出力フォーマット

以下の変数をフォーマット化して出力する公式の例ですが、「-」を付ける意味がよくわからなかったので確認したが、結局、意味ないように思う。

yes_votes = -42_572_654
total_votes = 85_705_149
percentage = yes_votes / total_votes

a = '{:-12} YES votes  {:2.2%}'.format(yes_votes, percentage)
b = '{:12} YES votes  {:2.2%}'.format(yes_votes, percentage)

print(a)
print(b)
   -42572654 YES votes  -49.67%
   -42572654 YES votes  -49.67%

この例は、負数のときだけ「-」を付けることを明示しているけど、実際的な話として出力結果に差はない。ただし「+」の場合は違いがある。

yes_votes = 42_572_654
total_votes = 85_705_149
percentage = yes_votes / total_votes

a = '{:+12} YES votes  {:2.2%}'.format(yes_votes, percentage)
b = '{:12} YES votes  {:2.2%}'.format(yes_votes, percentage)

print(a)
print(b)
   +42572654 YES votes  49.67%
    42572654 YES votes  49.67%

これは sign に説明してあるとおり - はデフォルトの振る舞いなので付ける意味が特にない。その一方で + はデフォルトでは付かない。また C# の出力のように正数・負数・ゼロをまとめてフォーマットを処理できるわけでもない。

int pos = 42;
int neg = -42;
int zero = 0;

Console.WriteLine("{0:#;(#);Zero}", pos);   // "42"
Console.WriteLine("{0:#;(#);Zero}", neg);   // "(42)"
Console.WriteLine("{0:#;(#);Zero}", zero);  // "Zero"

なので python で書式に - をつけるのは、本当にただの冗長的な意味しかないと思う。(下記のように負数の場合にのみ記号を付けてる、という説明になっているけど、サンプルは正数だし、負数に記号がつくのはデフォルトの動作だし、ちょっと微妙な内容ではないかと思う)

Notice how the yes_votes are padded with spaces and a negative sign only for negative numbers.

クラス

名前とオブジェクトについての整理。pythonC# のように「変数の中に値が入る」というイメージではない。その逆で、「オブジェクト(値)」があって、それに「名前(ラベル)」を貼り付けしているイメージになる。

基本的に、この考えかただと C# の参照型と同じようなイメージを持つことになると思う。(文中でもポインタについて言及があるけど)

ただし、基本的な型である数値 int や、文字列 str は immutable なオブジェクトのタイプで、ラベルに新しいオブジェクトを割り当てる動きになる。

a = 10
b = a  # b は a と同じオブジェクトを指す
b = 20   # b に別の数を代入すると、b に新しいオブジェクトを割り当てるだけ
print(a)  # 10  (a は変わらず 10 のオブジェクトが割り当たっている)

一方で list だと以下のようになる。変数の考え方は C#python でちょっと違う点は注意しないといけない。

a = [1,2,3]
b = a  # b は a と同じオブジェクトを指す
b.append(4)  # b が割り当たっているオブジェクトに 4 を追加
print(a)  # [1,2,3,4] (a が割り当たっているオブジェクトは b と同じ)

で、最後に「これにより、 Pascal にあるような二つの引数渡し機構をもつ必要をなくしています。」という文で締められるけど、具体的には値渡し (call by value) と参照渡し (call by reference) のことですよね。

C# の例

// 値渡し
void Foo(int x) { x = 100; }
int a = 10;
Foo(a);
Console.WriteLine(a); // 10

// 参照渡し
void Foo(ref int x) { x = 100; }
int a = 10;
Foo(ref a);
Console.WriteLine(a); // 100

python の場合は、繰り返しだけど、「オブジェクト(値)」があって、それに「名前(ラベル)」を貼り付けしているイメージをする。この例では参照渡しのように動作するが a ラベルが指し示すオブジェクトを x として渡して、同じオブジェクトに 100 を append している。

def foo(x):
    x.append(100)

a = [1, 2, 3]
foo(a)
print(a)  # [1,2,3,100]

スコープと名前空間について

名前を解決するときは次の順番:

  1. Local
  2. Enclosing 外側の関数のスコープ(クロージャで使用)
  3. Global
  4. built-in 組み込み名前空間

python の変数スコープの概念として LEGB rule として知られているみたいです。参照する変数を変更する際は global や nonlocal などを変数名に指定することで、書き換えるオブジェクトを切り替えることができる。

x = "global"

def outer():
    x = "enclosing"
    def inner():
        x = "local"
        print(x)
    inner()

outer()

built-in は、最初から python に入っている名前空間をいいます。なので len()print() は組み込み関数なので built-in です。

import を使用したときの場合だと、例えば import math は global に追加される。モジュールレベルのスコープになるので built-in ではない。

import しなくても使える機能ということなので、重要度は高いものが(当然だけど)多いです。

import builtins
print(dir(builtins))

私の環境(のひとつ)では、以下の出力でした。この内容を整理しておきます。

['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BaseExceptionGroup', 'BlockingIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning', 'ChildProcessError', 'ConnectionAbortedError', 'ConnectionError', 'ConnectionRefusedError', 'ConnectionResetError', 'DeprecationWarning', 'EOFError', 'Ellipsis', 'EncodingWarning', 'EnvironmentError', 'Exception', 'ExceptionGroup', 'False', 'FileExistsError', 'FileNotFoundError', 'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning', 'IndentationError', 'IndexError', 'InterruptedError', 'IsADirectoryError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'ModuleNotFoundError', 'NameError', 'None', 'NotADirectoryError', 'NotImplemented', 'NotImplementedError', 'OSError', 'OverflowError', 'PendingDeprecationWarning', 'PermissionError', 'ProcessLookupError', 'RecursionError', 'ReferenceError', 'ResourceWarning', 'RuntimeError', 'RuntimeWarning', 'StopAsyncIteration', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'TimeoutError', 'True', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning', 'WindowsError', 'ZeroDivisionError', '__build_class__', '__debug__', '__doc__', '__import__', '__loader__', '__name__', '__package__', '__spec__', 'abs', 'aiter', 'all', 'anext', 'any', 'ascii', 'bin', 'bool', 'breakpoint', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'exec', 'exit', 'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'quit', 'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars', 'zip']

出力結果を整理します:

基底クラス

  • BaseException
  • Exception
  • BaseExceptionGroup
  • ExceptionGroup

よく使うエラー

  • ArithmeticError
  • AssertionError
  • AttributeError
  • BufferError
  • EOFError
  • FloatingPointError
  • IndentationError
  • ImportError
  • IndexError
  • KeyError
  • LookupError
  • MemoryError
  • NameError
  • NotImplementedError
  • OSError
  • OverflowError
  • RecursionError
  • ReferenceError
  • RuntimeError
  • SyntaxError
  • SystemError
  • TabError
  • TimeoutError
  • TypeError
  • UnboundLocalError
  • UnicodeDecodeError
  • UnicodeEncodeError
  • UnicodeTranslateError
  • UnicodeError
  • ValueError
  • WindowsError
  • ZeroDivisionError

OS/ IO 関連エラー

  • BlockingIOError
  • BrokenPipeError
  • ChildProcessError
  • ConnectionError(接続エラーの基底)
  • ConnectionAbortedError
  • ConnectionRefusedError
  • ConnectionResetError
  • EnvironmentError
  • FileExistsError
  • FileNotFoundError
  • IOError
  • InterruptedError
  • IsADirectoryError
  • ModuleNotFoundError
  • NotADirectoryError
  • PermissionError
  • ProcessLookupError

制御フロー用の特殊な例外

  • GeneratorExit
  • KeyboardInterrupt
  • StopAsyncIteration
  • StopIteration
  • SystemExit

Warning 関係

  • BytesWarning
  • DeprecationWarning
  • EncodingWarning
  • FutureWarning
  • ImportWarning
  • PendingDeprecationWarning
  • ResourceWarning
  • RuntimeWarning
  • SyntaxWarning
  • UnicodeWarning
  • UserWarning
  • Warning

定数

  • Ellipsis(...
  • False
  • None
  • NotImplemented
  • True

double underscore

dunder = double undersocre 一覧:

  • __build_class__
    • python が class 文を実行するときに内部で呼ばれる
    • 普段は直接使わないが python が class を作る仕組みのコア
  • __debug__
    • true または false を持つ組み込み定数
    • 最適化モード (-O オプション)で false になる(通常は true になる)
  • __doc__
    • オブジェクトの docstring に入る属性
  • __import__
    • import 文の実体
    • 普段は直接使わないが python が import 文の内部でこれを使う
  • __loader__
    • モジュールが import されたときにつかわれた loader object
    • どの方法でモジュールを load したのかが格納される
    • 通常は import をカスタマイズしたいときだけなので触らない
  • __name__
    • モジュールの名前が入る特別な変数
    • スクリプトとして直接実行された場合は "__name__" になる
  • __package__
    • モジュールが属するパッケージの名前
    • from . import xxxx のような相対 import に使ってるので、直接は触らない
  • __spec__
    • モジュールの import 情報(ModuleSpec)が入る
    • どのファイルから load されたのか、などのメタ情報
    • 使うとしてもツールを作る側

関数

名前 概要
abs(x) 絶対値を返す
aiter(obj) 非同期イテレータを返す
all(iterable) すべて真なら true
anext(async_iterator, default) 非同期イテレータで次の要素を返す
any(iterable) いずれか真なら true
ascii(obj) 非 ascii 文字をエスケープ文字に変換
bin(x) 整数を2進数の文字列に変換
bool(x) 真理値に変換(0, '', None = false)
breakpoint() デバッガを起動
bytearray(source) 可変バイト列型に変換
bytes(source) 不変バイト列型に変換
callable(obj) 呼び出し可能なら true
chr(i) unicode コードポイントから文字を返却(int to str)
classmethod(func) クラスメソッド化するデコレータ
compile(source, filename, mode) ソースをコードオブジェクトにコンパイル
complex(real, imag) 複素数を生成
copyright 著作権表示文字列を表示
credit 謝辞文字列を表示
delattr(obj, name) obj.name 属性を削除
dict(...) 辞書型を作成
dir(obj) 属性リストを返却
divmod(a, b) a // b, a % b の tuple を返却
enumerate(iterable, start=0) インデックス付きのイテレータを返す
eval(expr, globals, locals) 文字列を式として評価
exec(object, globals, locals) 文字列やコードオブジェクトを実行
exit 対話環境で終了するためのオブジェクト = quit
filter(func, iterable) 条件にあう要素だけ取り出すイテレータ
float(x) 浮動小数点の数に変換
format(value, format_spec) 文字列をフォーマット
frozenset(iterable) 不変集合型。set と違い要素変更不可
getattr(obj, name, default) obj.name を動的に取得
globals() グローバル名前空間の dict を返却
hasattr(obj, name) 属性が存在すれば true
hash(obj) オブジェクトのハッシュ値を返却
help(obj) ヘルプのシステムを起動
hex(i) 整数を16進数の文字列に変換
id(obj) オブジェクトの一意な ID
input(prompt) 標準入力から文字列を取得する
int(x, base) 整数に変換(基数を指定できる)
isinstance(obj, class_or_tuple) オブジェクトがその型かどうかをチェック
issubclass(cls, class_or_tuple) クラスがそのサブクラスかどうかをチェック
iter(obj, sentinel) イテレータを返却
len(obj) 素数を返却
license ライセンスを表示
list(iterable) リストを生成
locals() ローカル名前空間の dict を返却
map(func, iterable, ...) 各要素に関数を適用するイテレータ
max(iterable, *) 最大値を返す
memoryview(obj) バイト列のメモリビューを返却
min(iterable, *) 最小値を返す
next(iterator, default) イテレータから次の要素を返す
object すべてのクラスの基底
oct(x) 整数を8進数文字列に変換
open(file, mode='r', ...) ファイルを開く
ord(c) 文字の unicode コードポイントを返却
pow(x, y, mod) x**y(mod の指定で累乗剰余)
print(*args, sep=' ', end='\n') 標準出力に表示
property(fget, fset, fdel, doc) プロパティを作成するでスクリプタ
quit 対話環境を終了 = exit
range(start, stop, step) 数列イテレータを返却
repr(obj) obj の文字列表現を返却
reversed(seq) 逆順のイテレータを返却
round(number, ndigits) 四捨五入
set 集合を生成
setattr(obj, name, value) 属性を設定
slice(stop) スライスオブジェクトを生成(文字列のスライス)
sorted(iterable, *) ソートしたリストを返却
staticmethod(func) 静的メソッド化するデコレータ
str(obj) 文字列に変換
sum(iterable, start=0) 数値の合計を返却
super(type, obj) 親クラスのメソッドを呼び出す
tuple(iterable) tuple を生成
type(obj) オブジェクトの型を返却
vars(obj) オブジェクトの __dict__ を返す
zip(*iterables) 複数のイテラブルをまとめる

参考




以上の内容はhttps://shikaku-sh.hatenablog.com/entry/python-practice-ioより取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14