はい。その2を書いたのが250日前、という感じですが、唐突にその3が始まります。
Twitterで、
というお話があったので、経験した中で書いていきます。
間違っていたらごめんなさい。
メモリ管理
C#、というか.NETでは、メモリをヒープ、スタック、静的領域と分けます。
が、PythonではPythonの領域としてはヒープを使う、とのことです。
ただ、CythonならC言語に、Iron Pythonなら.NETに依存する形で、メモリ管理はなされるように感じています。
まあ、普通に使う分には気にしなくて良いことかと思います。
詳細は、リンクをご覧いただきたいところです。
数値型、参照型
これらの型ですが、C#と同じく、object
を継承します。
Javaのように、「基本データ型」扱いとなったりもしません。
普通に、int
がメソッドを持っていたりします。
ただ、数値型、文字型、タプルは、値変更不可となり、特殊なオブジェクトな扱いは受けます。
数値型
4. 組み込み型 — Python 3.6.4 ドキュメント
Pythonの数値と呼ばれるものですが…
型(省略形) | 意味 |
---|---|
int | 整数 |
float | 浮動小数点数 |
complex | 複素数 |
の3つしかありません。
型(省略形) | 意味 |
---|---|
byte | 8ビット整数 |
short | 16ビット整数 |
int | 32ビット整数 |
long | 64ビット整数 |
のように、4つもあります。
これは、どこに書いてあったか忘れたのですが、理由を意訳すると
CPU都合で数値型を分けるのって、プログラマー的には面倒じゃね?
という感じだったと思います。
なお、int
の最大値は以下の文で取得できます。
import sys print(sys.maxsize)
私の環境(Windows10 64bit)だと、
9223372036854775807*2
となります。
また、10進数を扱うためにdecimal
というモジュールがあるため、金額計算等を行う場合は、そちらを使うべきかと思われます。ここはC#等でも一緒です。
9.4. decimal — 十進固定及び浮動小数点数の算術演算 — Python 3.6.4 ドキュメント
型の解釈
さて、静的型付き言語であるC#と、動的型付き言語であるPythonの、最も違うと思われる部分です。
まず、一般的には、
種類 | 意味 |
---|---|
静的型付き言語 | コンパイル時に型が決定される |
動的型付き言語 | 実行時に型が決定される |
という違いが、両者にはあります。
C#でいう
public int Plus(int x, int y) { return x + y; }
は、Pythonの
def plus(x, y): return x + y
と同じに見えます。
しかし、Pythonでは、
plus(2, 3) # 結果は「5」 plus("a", "b") #結果は「"ab"」
のように、処理ができれば型は関係ないです。
今は加算演算を例*3に出しましたが、メソッド呼び出しでも同様です。
型推論
C#でいうところのvar
を、Pythonではどう扱うのか、です。
C#の型推論*4は、あくまで「型をわざわざ指定しなくて良い」だけの機能で、結局はコンパイル時に型は決まります。
そのため、Visual Studioの型ヘルプを出すと、型が推論できない場合*5を除いて、型名が表示されます。
これは、メソッドの結果が、どういう型で返ってくるか決まっているため、当然の帰結です。
Pythonは、あるメソッドが複数の型を返す可能性があります*6。
有名なところでは、pandas
で列指定で返す際、1列ならSeries
、複数列ならDataFrame
が返ってくるという動きが良い例です。
import pandas as pd import numpy as np # 元になるDataFrame df = pd.DataFrame(np.random.random([100, 3]), columns=['foo', 'bar', 'baz']) one = df["foo"] two = df[["foo", "bar"]] print(type(one)) print(type(two))
実行結果は、
のようになります。
まあ、上のような定義はC#でも可能*7ですが、Pythonはオーバーロードができないので、引数の型可変、戻り値の型可変という定義になります。
Pythonの型アノテーション
Python3.5から、型アノテーションという機能が追加されました。
def plus(x: int, y: int) -> int: return x + y
Pythonでも、上のように書くことで、型ヒントを出せます。
しかし、動作時は無視されるため、別にstr
型であっても呼び出せます。
まあ、Python自体は動的言語で、その挙動は邪魔しないけど、利用者には型を意識させたい、という場合に使えます。
使ってみて思うこと
C#みたいに、静的な「比較的堅い」言語を使った後に、Pythonのように「柔らかい言語」を使うと、特にメソッドの戻り値の型が分からない場合に、混乱するように思います。
pandas
を使っていて、そこが一番混乱しました。
しかし、逆に言えば、そこまで型を意識しなくても作れるということでもあります。
利点となるか欠点となるかは…用途と状況次第ですね。
なお、動的であるが故に、単体テストの重要性は非常に高いといえます。
おわりに
継承とか、ディスクリプタとか絡めて、Pythonの面白い型機能を述べるのもよいと思っていますが、そのあたりはまとめるのも(私からしたら)難しい印象です。
インターフェイスに近い用法などもあるので、そのような部分も、また別の記事で述べたいと思います。