Java頭からPython頭に切り替える(基礎編1)

# Java頭？Python頭？
5年間ぐらいJavaでお仕事をしていたのですが、次の会社ではPythonを使っているということで、入社前にPythonのお勉強をしています。
Javaの感覚をPythonの感覚に切り替えている最中です。
自分のメインスキルを他のものにするというタイミングが今までなかったので、このお勉強の時期に何を思ったのかという気持ちを新鮮なうちに書いておこうと思います。
Javaと比較をして、それに対する感想っていう内容です。
基礎編ということで、文法にフォーカスしていきます（環境構築とか実行とかは省略）
予定ではフレームワーク編と実践編（業務レベルでどう違ったか）を書くつもり🤔
https://github.com/kei3524848/python_practice

# このメモはこんな人にオススメ
* 同じ境遇の人(JavaからPythonに移行する人)
    * 一緒に勉強しよう！
* Java or Pythonを知っている人
    * 自分が知らない方の言語の雰囲気がわかる（はず）
* Java, Pythonは知らなくても、他のコンパイラ言語とスクリプト言語を知っている人(CとRubyは知ってるみたいな)
    * JavaとPythonの雰囲気がわかる（はず）
* 両方知っている人
    * マサカリを担げる

# お勉強で使っている本
[Pythonチュートリアル 第3版](https://www.amazon.co.jp/Python%E3%83%81%E3%83%A5%E3%83%BC%E3%83%88%E3%83%AA%E3%82%A2%E3%83%AB-%E7%AC%AC3%E7%89%88-Guido-van-Rossum/dp/4873117534/ref=sr_1_2?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=1GJETQCVV1Y7F&keywords=python+%E3%83%81%E3%83%A5%E3%83%BC%E3%83%88%E3%83%AA%E3%82%A2%E3%83%AB&qid=1665297859&qu=eyJxc2MiOiIxLjU5IiwicXNhIjoiMC41MyIsInFzcCI6IjAuNDkifQ%3D%3D&sprefix=python%E3%81%A1%E3%82%85%E3%83%BC%E3%81%A8%E3%82%8A%E3%81%82%E3%82%8B%2Caps%2C231&sr=8-2)です。
1つ前の版ですが、まあそんなに変わらんでしょう。

# バージョン
Java -> jdk-11.0.14
Python -> 3.10.7

## Hello World
```Java:Java
class A {
	public static void main(String[] args) {
		System.out.println("Hello world");
	}
}
```
```Python:Python
print("Hello World")
```
かんたん🙌
さすがLL言語。

## 数値
```Java:Java
  public static void main(String[] args) {
    System.out.println(2 + 2);
    System.out.println(50 - 5 * 6);
    System.out.println((50 - 5 * 6) / 4);
    System.out.println(17 / 3);
    System.out.println(17 % 3);
    System.out.println(Math.pow(5, 2));
  }
```
```
4
20
5
5
2
25.0
```
```Python:Python
print(2 + 2)
print(50 - 5 * 6)
print((50 - 5 * 6) / 4)
print(17 / 3)
print(17 % 3)
print(5 ** 2)
```
```
4
20
5.0
5.666666666666667
2
25
```
基本は変わりなし。
違いは割り算。Javaは型に基づいて結果を返すけど、Pythonはfloat型を返却している。
Javaならintだと切り捨て除算するが、Pythonの場合は```//```で同様の効果が得られる。
```Python:Python
print(17 // 3)
```
intとintだし答えもintでええやろ！か、割り算だから少数で返したろ！か。
今の感覚だと、多少コードが長くなっても型がコード中に書かれていたほうがわかりやすいんじゃないかな～って感じ。
```Java:Java
System.out.println(Float.valueOf(17) / Float.valueOf(3)); 
```

あとべき乗も演算子で書けるのも面白い。
ただ[pow関数](https://docs.python.org/ja/3/library/functions.html#pow)ちゃんともある。

Pythonの数値はint, float, complex(複素数)の3種類、複素数ってなんぞ？って感じだった。
short, long, doubleはなし。BigInteger, BigDecimalもなし。
Pythonで正確な計算をするには[Decimal](https://docs.python.org/ja/3/library/decimal.html)をimportして使用すると吉らしい。

## 文字列
```Java:Java
 public static void main(String[] args) {
    System.out.println("spam eggs");
    System.out.println("dosen\'t");
    System.out.println("First line. \nSecond line.");
    var sb = new StringBuilder();
    var n = 3;
    var str = "umium";
    while (n-- > 0) {
      sb.append(str);
    }
    System.out.println(sb);
  }
```
```Python:Python
print('spam eggs')
print('dosen\'t')
print("First line. \nSecond line.")
print("""\
    Usage: thingy [OPTIONS]
        -h              Display this usage message
        -H              Hostname to connect to
""")
print(3 * "um" + "ium")
```
Pythonのほうが柔軟だな～という印象。
Pythonにcharはなし。だからシングルクォーテーションでもダブルクオーテーションでもOK。
改行をコードそのままに出したい場合は```"""\```でできる。

一番驚いたのが文字列のリピート。計算式みたいにできるのすごい。
Javaだったらwhileなりforなりstreamなりでループ文書かないといけないので面倒。
まあこれ業務で使うタイミングあるのかってところだけど。

### 文字
```Java:Java
 public static void main(String[] args) {
    var word = "Java";
    System.out.println(word.charAt(0));
    System.out.println(word.charAt(-1)); // StringIndexOutOfBoundsException
    System.out.println(word.substring(0, 2));
    System.out.println(word.substring(0, 2) + word.substring(2));
    System.out.println(word.substring(2, 42)); // StringIndexOutOfBoundsException
    System.out.println(word.length());
  }
```
```Python:Python
word = "Python"
print(word[0])
print(word[-1])
print(word[0:2])
print(word[:2] + word[2:])
print(word[4:42])
print(len(word))
```
```
P
n
Py
Python
on
6
```
マイナス値を指定すると後ろからn文字目になるのか～。
あと範囲指定で末尾のindex値の指定は適当にしてもよしなにしてくれるのもびっくり。
でもこれで例外が発生しないことで気づかないバグとかあったりするのかも...？

サイズの測り方について、Javaはクラスが持つメソッドを呼び出し、Pythonはビルトイン関数にインスタンスを入れるといった違いがある。

## リスト
```Java:Java
  public static void main(String[] args) {
    var squares = new Integer[]{1, 4, 9, 16, 25};
    System.out.println(Arrays.toString(squares));
    System.out.println(squares[0]);
    System.out.println(Arrays.toString(
        IntStream.range(2, squares.length)
            .mapToObj(i -> squares[i])
            .toArray()));
    var list = new ArrayList<Integer>();
    Collections.addAll(list, squares);
    Collections.addAll(list, new Integer[]{36, 49, 64, 72, 81, 100});
    System.out.println(list);

    var cubes = new ArrayList<>(Arrays.asList(1, 8, 27, 65, 125));
    cubes.add(3, 64);
    System.out.println(cubes);
    cubes.add(216);
    cubes.add((int) Math.round(Math.pow(7, 3)));
    System.out.println(cubes);
    System.out.println(cubes.size());
  }
```
```Python:Python
squares = [1, 4, 9, 16, 25]
print(squares)
print(squares[0])
print(squares[2:])
print(squares + [36, 49, 64, 72, 81, 100])

cubes = [1, 8, 27, 65, 125]
cubes[3] = 64
print(cubes)
cubes.append(216)
cubes.append(7 ** 3)
print(cubes)
print(len(cubes))
```
```
[1, 4, 9, 16, 25]
1
[9, 16, 25]
[1, 4, 9, 16, 25, 36, 49, 64, 72, 81, 100]
[1, 4, 9, 16, 25, 36, 49, 64, 72, 81, 100]
[1, 8, 27, 64, 65, 125]
[1, 8, 27, 64, 65, 125, 216, 343]
7
```
Pythonは配列＝Listで、Javaの配列っぽい書き方でリストが生成できるというイメージですかね。
[list関数](https://docs.python.org/ja/3/library/functions.html#func-list)もあり。

範囲指定して値を取り出すのは圧倒的にPythonのほうが楽。
リストも演算子を用いていろいろできるということですね。

要素の追加で演算子が使えることについて、本質的には違うけどScalaも似たような見た目で書けるなと思いだした。
```Scala:Scala
val sequence = Seq(1, 2, 3)
sequence ++ Seq(4, 5, 6)
```


あと1つのリストに型関係なく入れられるとのこと。ただし、通常はすべて同じ型を入れるらしい。
ぐちゃぐちゃにいろんな型のものが入ってたら絶対使いにくい。

↓他の関数の違い↓
|  Java  |  Python  |
| ---- | ---- |
|  add(E e)  |  append  |
|  addAll  |  extend  |
|  add(int index, E element)  |  insert  |
|  remove(Object o)  |  remove  |
|  remove(int index)  |  pop  |
|  clear  |  clear  |
|  indexOf  |  index  |
|    |  count  |
|  sort  |  sort  |
|  (Collections.reverse)  |  reverse  |
|  (別変数に代入)  |  copy  |

多次元配列はそこまで差異なし
```Java:Java
var x = new int[][]{{1, 2, 3}, {4, 5, 6}};
```
```Python:Python
x = [[1, 2, 3], [4, 5, 6]]
```

また、`set`, `stack`, `que`はほぼ同様（と認識している）

### 集合(set)
コメントで説明があった通り、算術演算が使える
```Python:Python
a = set("abracadabra")
b = set("alacazam")
print(a)
print(b)
print(a - b)
print(a | b)
print(a & b)
print(a ^ b)
```
```
{'c', 'b', 'd', 'r', 'a'}
{'z', 'c', 'm', 'l', 'a'}
{'b', 'd', 'r'}
{'c', 'b', 'z', 'm', 'l', 'd', 'r', 'a'}
{'c', 'a'}
{'z', 'b', 'd', 'r', 'm', 'l'}
```

### Tuple
```Python:Python
t = 12345, 54321, "Hello!"
print(t[0])
print(t)
u = t, (1, 2, 3, 4, 5)
print(u)
v = ([1, 2, 3], [3, 2, 1])
print(v)
```
```
12345
(12345, 54321, 'Hello!')
((12345, 54321, 'Hello!'), (1, 2, 3, 4, 5))
([1, 2, 3], [3, 2, 1])
```
[] or ()の違いってなに？って思ったけど、ミュータブル or イミュータブルの違いがあるんですね。
固定値という意味ではenumかとも思ったが、[enum](https://docs.python.org/ja/3/library/enum.html#module-enum)は別であった。
業務レベルのコードだとどういうふうに使い分けしてるのかが気になる。

## 連想配列(Map, Dictionary)
```Java:Java
  public static void main(String[] args) {
    var tel = new HashMap<String, Integer>();
    tel.put("jack", 4098);
    tel.put("sape", 4139);
    tel.put("guido", 4127);
    System.out.println(tel);
    System.out.println(tel.get("jack"));
    tel.put("irv", 4127);
    System.out.println(tel);
    System.out.println(tel.keySet());
    System.out.println(tel.containsKey("jack"));
  }
```
```Python:Python
tel = {"jack": 4098, "sape": 4139}
tel["guido"] = 4127
print(tel)
print(tel["jack"])
tel["irv"] = 4127
print(tel)
print(list(tel.keys()))
print(sorted(tel.keys()))
print("guido" in tel)
```
```
{'jack': 4098, 'sape': 4139, 'guido': 4127}
4098
{'jack': 4098, 'guido': 4127, 'irv': 4127}
['jack', 'guido', 'irv']
['guido', 'irv', 'jack']
True
```
名前が違うだけでほぼ変わりなしって感じ。
[初期化の仕方](https://docs.python.org/ja/3/library/stdtypes.html?highlight=dict#mapping-types-dict)もいろいろあるので、Pythonのほうが柔軟なのかな。

# いったんここまで
とりあえず型関連まで。
残りの文法とクラス関連については次の記事にて。