パソコンでプログラミングしよう ウィンドウズC++プログラミング環境の構築
1.6.3.6(15)
Python

Pythonはインタープリタ型の高水準汎用プログラミング言語である。

その他の外部情報

本サイトでの解釈

今や書店での勢力図はPython≫C++だが、2000年頃はC++≫Pythonだった。C++と全く異なる構文を取り、C++が望んでも得られない機能を当たり前に備え、それでいてC++的ニュアンスを感じる不思議なインタープリタ言語だった。本サイトはPythonを主題としないものの、C++の静的プログラミング言語としての定めに対比する動的プログラミング言語として参照する。サンプルコードはmingw32/mingw64ターミナルからPythonの標準統合開発環境であるidleを起動して実行確認できる。[File|New File]で開く空白のエディタウィンドウにコピーアンドペーストしてエディタウィンドウ[File|Save as]で拡張子pyを持つ適当なファイルに保存し、[Run|Run Module]で実行する。

動的型付け

get_object関数はtype_name文字列に従い様々なオブジェクトを返す。関数やクラスもオブジェクトとして扱える。

#!/usr/bin/env python3.exe
def get_object(type_name):
match type_name:
case 'numeric':
return 10
case 'string':
return 'Hello world!'
case 'function':
def func(x):
return x*x
return func
case 'class':
class cls:
def mem_func(self,x):
return x*x*x
return cls
case _:
return None
if __name__=="__main__":
print(get_object('numeric'))
print(get_object('string'))
my_function=get_object('function')
print(my_function(10))
my_class=get_object('class')
my_class_instance=my_class()
print(my_class_instance.mem_func(10))

ダックタイピング

my_class_1クラスとmy_class_2クラスは同名のmem_funcメンバ関数を持ち動的多態性を実現する。これをC++で実現するには抽象/具象クラス、すなわちクラス継承と仮想メンバ関数を必要とする。

#!/usr/bin/env python3.exe
class my_class_1:
def mem_func(self):
print('Hello world!')
class my_class_2:
def mem_func(self):
print('Are you happy?')
if __name__=="__main__":
for my_class in my_class_1,my_class_2:
my_class_instance=my_class()
my_class_instance.mem_func()

モンキーパッチ

my_classクラスのインスタンスであるmy_class_instanceは構築後にnew_strメンバ変数を追加する。さらにmy_classにnew_mem_funcメンバ関数を追加し、my_class_instanceは追加されたnew_mem_funcをコールできる。なおmy_classが__slots__を持つ場合はmy_class_instanceへのメンバ追加はできない。

#!/usr/bin/env python3.exe
class my_class:
def __init__(self):
self.str='Hello world!'
if __name__=="__main__":
my_class_instance=my_class()
print(my_class_instance.str)
my_class_instance.new_str='Are you happy?'
print(my_class_instance.new_str)
def mem_func(self):
print(self.str+' I\'m badly happy!')
my_class.new_mem_func=mem_func
my_class_instance.new_mem_func()

参照セマンティクス

静的/動的プログラミング言語とは無関係ながらC++とPythonの差異を表すもう一つの特質がある。変数が対象を保持する方法として値セマンティクスと参照セマンティクスがある。前者は値として対象をそのまま保持し、後者は何処かに存在する対象への参照を保持する。C++の原則は値セマンティクスであり、ポインタを保持すれば参照セマンティクスとして振る舞う事もできる。Pythonは常に参照セマンティクスである。my_classクラスのインスタンスである(より厳密にはインスタンスを参照する変数である)my_class_instance_1をmy_class_instance_2へコピーする。my_class_instance_1.strを変更するが、my_class_instance_2はmy_class_instance_1と同じ対象(Pythonオブジェクト)を参照してmy_class_instance_2.strも変更される。

#!/usr/bin/env python3.exe
class my_class:
def __init__(self):
self.str='Hello world!'
if __name__=="__main__":
my_class_instance_1=my_class()
my_class_instance_2=my_class_instance_1
my_class_instance_1.str='Are you happy?'
print(my_class_instance_1.str)
print(my_class_instance_2.str)

Pythonオブジェクトは参照不可となればガーベッジコレクション(不要になったメモリ領域を自動的に解放する機能)が解体するかもしれないが、いつ解体するかは予測できず、つまり決定論的解体(deterministic destruction)は期待できない。MSYS2の供給するPython実装(CPython)に限れば参照カウントゼロで解体するが(The Python Language Reference 3.1. Objects, values and types)、循環参照が残ればガーベッジコレクション頼みに変わりない。

#!/usr/bin/env python3.exe
class my_class:
def __init__(self):
print('Create the object')
def __del__(self):
print('Delete the object')
if __name__=="__main__":
print('Create first reference to the object.')
my_class_instance_1=my_class()
print('Copy first reference to second reference.')
my_class_instance_2=my_class_instance_1
print('Delete first reference')
del my_class_instance_1
print('Delete second reference')
del my_class_instance_2