GitHubの使い方を超簡単に解説してみた〜チーム開発編〜
こちらの記事の続きになります。
イメージして欲しいのですが、
自分がレポジトリからプログラムを落として、修正をしてGitHubにアップしている間、他のチームメンバーも同じように開発を行い修正をしてGitHubにアップしていきます。
これの何が問題かと言いますと、
自分が過去にレポジトリから落としたプログラムは、今GitHubにストックされているプログラムと一緒とは限らはないのです。
自分は落としてきたプログラムを前提に修正点や追加機能を作る訳ですから、その前提となっていたプログラムが途中で変わってしまうと何かしらの影響が出る可能性があります。
また、この問題は他のチームメンバーも同じです。自分の修正点が原因となって他の人のプログラムが動かなくなるかもしれません。
この問題の影響を少なくする方法を知ることがチーム開発では重要なのです。
ソフト面でできること
・できる限りチームメンバーが修正するエリアを被らないようにする
・チーム内でどんな開発をしているかを共有する
・何か影響範囲の大きい修正する場合は事前に共有して許可をもらう
GitHubの機能を使ってできること
開発前に常にコードは最新にしておく
$git pull origin main
このコマンドを実行すると、すでに落としたプログラムから最新のGitHubのレポジトリ内のコードの差分をダウンロードしてくれます。結果、GitHubの最新のコードとローカルファイルが同じものになります。
例えば
git clone時のローカルファイル
a = 34
num = a
GitHUbの最新のコード
a = 34
b = 5
num = a + b
以下のコードが追加、変更されGitHubの最新のコードとローカルファイルが同じものになります。
b = 5
num = a + b
自分の修正をmainに入れない
毎回、チームメンバーみんなが開発する前にコードをGitHubのmainブランチの最新バージョンを落とすため、できる限り問題のあるコードはmainに入らないようにするべきです。
そのために前回扱った、以下のコマンドの前後に工夫をして上記の問題をないようにしましょう。
git add <入れたいファイル> git commit -m "" git push origin main
具体的には、mainブランチではない、自分のブランチを作って、そのブランチの修正点が問題ないかを他のチームメンバーを確認してもらってからマージしてもらいます。
ブランチとは、枝、支部、支流の意味で、mainを大元にして自分の修正バージョンを枝のように作成することができます。
そのコマンドが以下です。
git checkout -b <ブランチ名>
全体的な流れとしては、何か新しい開発を行う前に
コードを最新にする
git pull origin main
新しくブランチを作成
git chheckout -b <ブランチ名>
git add <入れたいファイル>
git commit -m ""
先っほど作成したブランチでGitHubにPush
git push origin <新しく作成したブランチ名>
ここまで終わるとGitHubのWEBページに行きます。

Pushしたレポジトリの「Pull requests」をクリックして、どのブランチからどのブランチ(おそらくmain)に追加を希望するかの情報を入れて、レビュアーに回します。
GitHubを超簡単に説明してみた
ソフトウェア開発で欠かせないGitHubの使い方をざっくり超簡単に解説してみます。
今回カバーするのは、「GutHubでの新しいレポジトリ(PCのフォルダーのようなもの)の新規作成」、「GitHubのコードのダウンロードの仕方」、「GitHubに変更を追加する方っ方」の3点です。
大きく分けて新しくプロジェクトを立ち上げるか、既に始まっている開発でレポジトリ(GitHubにあるコード)があるかで分かれます。
前提としてGitHubアカウントは持っていてログインできており、ターミナルなどでgitが使える状態にあるものと仮定して話を進めますので、もしまだ持っていない場合は登録してから再度以下をお読み頂くことをお勧めします。
以下のコマンドでgitがコマンドから使えるかどうか分かります。
git --version
新規開発
まずはログインんして右上の○の自分のアイコンをクリックします。(自分は何も登録していないのでデフォルトのものです。) Your Repositoryをクリックすると、スクショと同じページが出るはずなので、Newから新しいレポジトリを作成します。
まとめると
自分のアイコン→Your Repositories→New (下のスクショの緑のボタン)

Newを押した後にこのようなページが出ます。

必須の項目はRepository名とPublic/Privateの選択です。
Public/Privateはレポジトリを見ることができる人と、レポジトリに
Publicにすると誰でも見えることができます。(オープンソースのソフトウェアとか)
Privateなら自分と自分が追加した人しか見ることができません。
その他の設定について
README File: プログラムの概要や説明などを記述するファイルで、それを追加するかどうかを選択できます。
.gitignore: githubに変更的を追加するときに無視するファイルやディレクトリーと決めることができます。
license: これはこのプロジェクトのライセンス、どのように使っていいか(いけないか)を決めるものです。Publicの時は重要になります。
さて、レポジトリーが一旦できると次からの動作は「途中から開発」と同じになります。
既存のレポジトリからダウンロード
Repositoriesから開発を行うレポジトリをクリックします。

「Code」という緑のボタンをクリックすると、上のスクショのようになります。
今回はHTTPSでプログラムをダウンロードします。
赤で囲ったURLをコピーします。横のアイコンをクリックするとコピーされます。
Macの場合はターミナル、Windowsの場合はコマンドプロンプトを立ち上げて、ダウンロードしたいディレクトリーまで移動します。
$ git clone <先ほどcopyしたパス>
を実行します。
もしかしたら、この時にアカウントのログインを求められるか、公開鍵の登録を求められるかもしれません。
公開鍵は最初は戸惑うかもしれませんが、コマンドを少し打つだけで取得できるの調べて作成してください。
git cloneが正常に動けば、レポジトリのダウンロードっは完了です。
修正点をGitHubに送る
自分が修正したコードをGitHubに送る方法をお伝えします。
こちらは、宅配便などで荷物を送る時と似ています。
荷物を送るときのフローをイメージしてみてください。
典型的な例として以下の手順になります。
「何を入れるかを考える」→「段ボールに送りたいものを入れる」→「ガムテープで包んで、宛先を書く」→ 「配送センターなどに持っていく」
Gitも同じような手順を踏みます。
何を入れるかを考える
何をGitHubに送るかを考えるために、現在自分がどんなファイルのコードを変更したのかを確認しましょう
$git status
これで自分が編集したファイル、新しく作成したファイルが分かります
詳しく変更点を見たい場合はファイル名をコピーして、下記のコマンドを入力します。
$git diff <パスを含んだファイル名>
例:git diff src/main.py
段ボールに送りたいものを入れる
ここから実際に入れていきます。GitHubの場合いいことは段ボールはいりません。
入れたいファイル名を使って下記コマンドで入れていきます。
$git add <パスを含んだファイル名>
全部の変更点をを入れたい場合はこちらも可能です。
git add .
ガムテープで包んで、宛先を書く
GitHubに送りたいものを追加した後は、ガムテープでとめます。
$git commit -m "コメント"
宛名というかコミット先はgit pullした先を自動で選択してくれるので、何が入っているかだけ書きましょう。
例:git commit -m "fix: 〇〇のバグを修正"
配送センターなどに持っていき
次のコマンドで修正点をGitHubに送ります。
$git push origin main
MNISTのデーターセットを使ってニューラルネットワークを実装しよう
この記事は以下の記事の続きになり、実際にPythonのKerasというライブラリーを用いてニューラルネットワーク(深層学習より層が少ない)を実装していきたいと思います。
Kerasとは
Kerasは、ディープラーニングモデルを作成するための高レベルのプログラミングインターフェースを提供するPythonライブラリです。複雑なディープラーニングモデルを比較的簡単に構築できます。
層、目的関数、最適化手法などを追加するのが簡単で、どう簡単なのかは実際にコードを見ながら理解して頂ければと思います。
MNISTとは
MNIST(Mixed National Institute of Standards and Technology database)は、手書き数字の大規模なデータセットで、データセットの簡単さとクリーンさにより、初心者が基本的なディープラーニングを学び、経験を積むのに役立ちます。
60,000の訓練画像と10,000のテスト画像から成り、手書きの数字(0から9)がグレースケール画像として表現されています。各画像は28x28ピクセルで、各ピクセルは0から255までの値を取り、画像内の特定の位置の強度を表します。
データセットの構造
データセットは上述の通り60,000の訓練画像と10,000のテスト画像が入っています。
ですが6万個.pngや.jpegの画像が入っているわけではなく、各ピクセルの白黒の強さが0から255の数字で表されていた6万個の28×28の配列が入っています。
まとめると、データセットは以下の構図になっています。
data_set = ( (A,B) , (C,D) )
A ... 訓練用データセット、6万個、白黒の強さが0から255の数字が入った28×28の配列
B ... 訓練用データセットのラベル、6万個、手書きの数字(0から9)の訓練用データセットの正解
C ... 検証用データセット、1万個、白黒の強さが0から255の数字が入った28×28の配列
B ... 検証用データセットのラベル、1万個、手書きの数字(0から9)検証用データセットの正解
実際にモデルを作成
ライブラリーのインストール
import keras
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense, Dropout
from keras.optimizers import RMSprop
必要なライブラリーをインポートしていきます。大前提のKeras、MNISTのデーターセット(Kerasからダウンロードできます)、ニューラルネットワークを作る上で必要な機能をimportしてきます。
データセットの用意
#1 データセットを代入
(x_train, y_train), (x_test, y_test) = mnist.load_data()
#2 データを調整
x_train = x_train.reshape(60000, 784)
x_test = x_test.reshape(10000, 784)
x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255
#1 データセットを代入
上のデータセットの構造のまま以下のように代入されます。
A → x_train
B → y_train
C → x_test
D → y_train
#2 データを正規化
.reshapeは配列の形を変えるのに使われます。28×28の正方形のピクセル([1,2,3 ...28]が28個ある配列)を一時配列(リストの中にリストがない状態、[1,2,3,4]みたいな感じ)に直します。
理由は後で分かるのですが、今回のモデルは入力層を728個(28×28)用意したので、28個目の次が別の配列でなく、29個目につながって728まで続くように配列を変形します。
データを"正規化"というものをしていきます。
今回は0~255の数字を0~1の間に収めます。
ニューラルネットワークでは、入力データが0近辺で中心化されている(平均が0)と、または小さな範囲に収まっている(例えば-1から1、または0から1)と学習がうまく進むことが一般的に知られています。
自分の感覚的なイメージは、最後0~9のラベルに確率で出るので入力が158, 230などの大きな数字になると収束されるのが大変でモデルの精度が上がらないものと捉えています。
モデルの構造を実装
model = Sequential()
model.add(Dense(512, activation='relu', input_shape=(784,)))
model.add(Dropout(0.2))
model.add(Dense(512, activation='relu'))
model.add(Dropout(0.2))
model.add(Dense(10, activation='softmax'))
最初にどんなmodelにするかを決定します。
今回はadd()で追加した層を順番に実行していくSequentialを採用します。
model.add()で層(レイヤー)を追加していきます。
層は入力層、中間層を入れていきます。
層の情報はadd()の()の中の情報です。
意味はこんな感じです。
Dense ... その層に属する全てのニューロンが前の層の全てのニューロンと接続されている層
activation ... 活性化関数
input_shape ... 入力層
活性化関数についてはまた後日ブログを書ければと思います。
モデルを実行
model.compile(loss='categorical_crossentropy',
optimizer=RMSprop(),
metrics=['accuracy'])
model.fit(x_train, y_train,
batch_size=128,
epochs=10,
verbose=1,
validation_data=(x_test, y_test))
.compileは先ほどのコードをPCが実行できるようにする感じです。
.fitで実際に学習が始まります。
スコアの確認
score = model.evaluate(x_test, y_test, verbose=0)
print('Test loss:', score[0])
print('Test accuracy:', score[1])
このコードでモデルの結果を確認できます。
自分の実行したときはこんな数字でした。
Test loss: 0.09119302034378052
Test accuracy: 0.9825999736785889
スタック(Stack)とキュー(Queue)について
スタック(Stack)とキュー(Queue)は自分の知るがぎり簡単な部類のデータ構造ですが、どっちがどっちか間違いやすく意外と厄介です。この記事でっはその違いを簡単に紹介できればと思います。
スタック(Stack)とキュー(Queue)の違い
違いを一言で言うと、スタック(Stack)は筒で、キュー(Queue)は列です。
スタック(Stack)は筒で中に一度入れると取り出すのは筒の上にあるもの、すなわち最後に入れたものになります。
キュー(Queue)は列で最初に並んだ人が最初に呼ばれ(取り出され)ます。
スタック (Stack):
スタックは、「最後に入ったものが最初に出る」(Last In, First Out; LIFO)という原則に従ったデータ構造です。
スタックに要素を追加する操作を「プッシュ」(push)、要素を取り出す操作を「ポップ」(pop)と呼びます。
これは、物理的な積み重ね(例えば、皿の山)と考えるとわかりやすいです。最後に積み上げた皿が、最初に取り出されます。
class Stack():
def __init__(self):
self.stackList = []
def push(self, element):
self.stackList.append(element)
def remove(self):
self.stackList.pop()
def show(self):
print(self.stackList)
stack = Stack()
stack.push(1) # スタックに1を追加
stack.push(5) # スタックに5を追加
stack.push(7) # スタックに7を追加
stack.show() # スタックの状態を表示 ([1, 5, 7])
stack.remove() # スタックから最後に追加された要素(7)を削除
stack.show() # スタックの状態を表示 ([1, 5])
Stackクラスが定義され、その中にpush、remove、showというメソッドが定義されています。
push: スタックに要素を追加します。remove: スタックから最後に追加された要素を削除します。ただし、このメソッドは削除された要素を返さないので、popと名付ける方が一般的かもしれません。show: スタックの現在の状態を表示します。
このremoveが最後に追加した要素を取り出すことから、「最後に入ったものが最初に出る」が実装されています。
キュー (Queue):
キューは、「最初に入ったものが最初に出る」(First In, First Out; FIFO)という原則に従ったデータ構造です。
キューに要素を追加する操作を「エンキュー」(enqueue)、要素を取り出す操作を「デキュー」(dequeue)と呼びます。
これは、物理的な行列(例えば、チケット売り場の列)と考えるとわかりやすいです。最初に列に並んだ人が、最初にサービスを受けるでしょう。
class Queue():
def __init__(self):
self.stackList = []
def enqueue(self, element):
self.stackList.append(element)
def dequeue(self):
self.stackList.pop(0)
def show(self):
print(self.stackList)
queue = Queue()
queue.enqueue(1) # キューに1を追加
queue.enqueue(5) # キューに5を追加
queue.enqueue(7) # キューに7を追加
queue.show() # キューの状態を表示 ([1, 5, 7])
queue.dequeue() # キューから最初に追加された要素(1)を削除
queue.show() # キューの状態を表示 ([5, 7])
Queueクラスが定義され、その中にenqueue、dequeue、およびshowというメソッドが定義されています。
enqueue: キューの末尾に要素を追加します。dequeue: キューの先頭から要素を削除します。ただし、このメソッドは削除された要素を返さないので、一般的なキューの実装では削除された要素を返します。show: キューの現在の状態を表示します。
dequeuueでリストの一番最初に追加した要素を取り出すことで、「最初に入ったものが最初に出る」が実装されています。
機械学習、初学者必見!深層学習のアルゴリズムのイメージを書いてみた
機械学習、初学者の方へ
最初から複雑なモデルを作れるだけのプログラミングと数式の理解はハードルが高く難易度ががります。ですが簡単に何かおーっとなるようなAIモデルを作りたい。
そんな人にGoogleのTeachable Machineはおすすめです。
Teachable MachineとはChatGPTに聞くと以下のような回答を頂きました。
Teachable Machineは、Googleが提供するオンラインツールです。このツールは、機械学習を使用してユーザーがカスタムモデルを作成し、それを教えることができるように設計されています。ユーザーは、ビデオ、音声、または画像を使用して、機械学習モデルをトレーニングすることができます。
Teachable Machineは、機械学習の基本的な概念を理解していないユーザーにもアクセスしやすくするために開発されました。コーディングやデータサイエンスの知識がなくても、ビジュアルなインターフェースを通じて簡単にモデルを作成し、トレーニングすることができます。
要は知識のない人でもWEBでビジュアルで簡単に画像や音声の機械学習モデルを作れるというものです。
詳しい作り方はこの記事などを参考にされてはいかがでしょうか?
https://www.itmedia.co.jp/news/articles/2209/16/news038.html
この記事ではそこで使われる知識を紹介できればと思います。
機械学習とは
そもそもですが、機械学習とはめっちゃ簡単に言うと1000組のデータと予測したい物の答え(家賃を予測するAIの場合、データ:物件の広さ、答え:家賃 とか)を与えて、決められた数式の形を前提に最適な数式を探し出す物です。
例えば
y= ax+bを数式の形として与えた場合、データをxに入れてyの値を出した時、そのすべてのyとすべてのデータが最も近くなるaとbのを何100回、何1000回も計算して探すことです。
この数式の形の一つがニューラルネットワークで、ニューラルネットワークの中である条件を満たすものを深層学習(ディープラーニング)と言います。
アルゴリズムについて
おそらくTeachable Machineには深層学習(ディープラーニング)が使われていると思われます。
その深層学習について厳密性は省き、めちゃくちゃ簡単に説明できればと思います。
深層学習のイメージは以下になります。
入力層にデータが入り、→の方向に数が渡されていき出力層の分類する数分あるノード(丸の箱)にそれぞれの確率が入ります。
ポイント1
→はただ前のノードから次のノードに数字を渡すだけでなく、重り(通常wと書かれる)をかけた値を渡します。このw(矢印分存在)がy=ax+bのaとb、すなわり学習して適切な値を探すものになります。
ポイント2
グレーの⚪️の中には活性化関数と呼ばれるものが入っており、すべての矢印から送られてきた数の和をそのまま次のノードに送るわけではなく、すべての矢印から送られてきた数の和に活性化関数に通した数を次のノードに渡します。
活性化関数にはReLU関数、Sigmoid関数などがあります。
なぜ活性化関数をかける理由は今後の記事で書きたいと思いますが、一言で言うと、数式(数理モデル)が重りの掛け算とノードでの足し算でできた単調なものにしないことで柔軟なモデルを作るためです。

イメージのための簡単な例
例として飲み物の特徴から飲み物の種類を判定する深層学習があったとします。(画像の分類は深層学習のイメージを掴んでもらった後に書いてます。)
種類(出力)は[オレンジジュース, コーヒー, 水]として、特徴(入力)は[にがさ、水っぽさ、甘さ]とします。

深層学習では左の入力と呼ばれるところから[にがさ、水っぽさ、甘さ]のそれぞれの数字を受け取り矢印の先になるノードに数字が送られます。ただ矢印は送る時に重りと呼ばれる数をかけてノードに送ります。
この場合、にがさ:73、水っぽさ:16、甘さ:11の数字が入ったことになります。(答えの分類はコーヒーが正解です。)

なのでAのノード(箱)には
それぞれの入力層の数字にそれぞれの重り(矢印の横に書いた数字)がかけられてAに入ります
なのでA = 73×0.1+16×0.5+11×0.3 = 18.6がが入ります。
こんな感じで下のノードにも数字が入ります。
ノード内には活性化関数と呼ばれる関数が入っておりノードの値を関数に入れてノードの値を新しくします。
そして、ノード(Aとか)が活性化関数で出力した新しい値を次の右のノード達に重りをかけて渡します。
これを出力層にたどり着くまで繰り返します。
出力層に以下のような結果が出たとします。
[水:0.79,コーヒー:0.11,オレンジジュース:0.10]
分類結果は水になっています。これは正解のコーヒーとは異なります。
機械学習はこの違いをもとに重りを修正して新しくモデルを作ります。
これを繰り返しできた正答率の高いモデルを採用します。
画像処理の場合
画像処理の場合入力層に画像を入れるだけです。
実は画像はめちゃくちゃ小さな単色の正方形の集合でできており、入力層はそれぞれの一つの小さな正方形を入れます。ただ注意点はコンピューターは数字しか処理できないので(red, green, blue)を数字で表した数で正方形を表現して入れます。(今後もそちらもブログで書ければと思います。)
ここが深層学習の難しいところであり、面白いところなのですが、入力層に何を入れてもよく出力層に何を出してもよくて、ただ入力層から受けたデータを正しい答えを出す確率が高い数式を出すのが深層学習になります。
プロのエンジニアは何が違う?保守性です。
アメリカの大学を卒業して1年弱経ち、新卒でIT企業に入社しエンジニアとしてシステムの開発に約10ヶ月ほど従事しました。
そこで気づいたプロのエンジニアの書くコードと自分の大学時代に書いていたコードの書き方で明確な違いが何点か見つかったのでここで共有できればと思います。前提として複数人で実際にサービスとして提供されるシステムを作る際の実務での気づきになります。
実務未経験のエンジニアの方にはとても役にたつのではないかと思います。
保守性を高める
保守性とはバグや誤りの見つけやすさと仕様変更、機能追加の行いやすさです。
1、変数、定数、関数クラスの名前の付け方
これは実務経験がなくても大学などで教授に指摘されたり、自分でも気づいていたりするかもしれませんが、変数などの名前の付け方を適当にすると面倒なことが起こります。
個人の開発でも半年前のコードを読んだ時に解読できないという経験をしたことは多いのでは中と思います。
書いた本人でさえ時間が経てばわからなくなるものを、書いたことすらない他のチームメイトが解読することはとても骨の折れる行為で時間がとてもかかります。この時間は自分が少し名前を意識するのにかかる時間と比べ物になりません。(またチームメイトは自分ともう一人とも限りません。)
そのため見ただけで変数や関数などの意味がわかりやすい名前の付け方は意識することを要求されます。
例)
× num
○ totalUserNumber
バグがあった際も、仕様変更、機能追加の際も基本的に既存のコードを見るので、保守性の全てに通ずるところがあります。
名前の付け方のルールは具体的な単語を入れるだけでなく、単語の繋げ合わせ方でも以下のようなルールがあります。キャメルケース(camelCase)やパスカルケース(PascalCase)、スネークケース(snake_case)、ケバブケース(kebab-case)
この()内の英語の名前が表記の仕方になっています。
例えば、キャメルケース(camelCase)の場合は複数の単語のうち真ん中の先頭を大文字にして、スネークケース(snake_case)の場合は複数の単語を_で繋ぎます。
キャメルケース(camelCase)だとuserItemや、スネークケース(snake_case)の場合はcurrent_userのように。
ちなみに、自分のおすすめの方法は以下のように種類でケースを分けることです。
変数、定数、関数 ... キャメルケース(camelCase) 例)findAllUsers()
クラス ... パスカルケース(PascalCase) 例)LinkedList
DB関連の名前 ... スネークケース(snake_case) 例)user_password
HTMLのidなど ... ケバブケース(kebab-case) 例)title-container
普段HTMLは触らないのでこんな名前があるかはわからないのですが苦笑
2、Unitテストを入れる
Unitテストとは関数やクラスの一つ一つが正常にテストを動くかをチェックするものです。
機能でも複数の関数が連続として動くことで作用するものは多くあると思います。その際にそれぞれの関数自体は正常で動いていることが分かれば、接続さえ見れば良いことになるのでバグを解決しやすくなります。
また、ただそれぞれのユニット(関数、クラス)の正常さの保証だけでなく、仕様変更の際などでバグを残してしまっていた際にユニットテストが回っていれば気づ気安くなります。
3、設計
設計という言葉は粒度がありますが、今回はクラス設計や関数の切り分け方などです。
クラスなどでは単一責務という考え方があり、一つのクラスには一つの責任を持たせて、同時に異なり目的のことをさせないというものです。
これがなぜ保守性を高めるかですが、単一責務でない場合自分が想定していなかったエラーが起こりうる可能性が増えるからです。
これは自分もまだ勉強中で人に説明できるレベルではないので、また後日書き足させてください。
JavaScriptの基本文法をpythonと比較してマスターしよう!③
関数
定義の仕方
pythonの場合
def add(a,b):
return a+b
JavaScriptの場合
const add = function(a,b){
return a+b;
};
呼び出し方は両方とも同じです。
add(1,2)
add(1,2)
アロー関数
*新しいJavaScriptではアロー関数といって以下の書き方もできます
const add = (a,b)=>{
処理;
};
アローとは英語で矢印という意味があります。
クラス
クラスはReactやVue.jsを学ぶのに必須の知識になります。
pythonのクラスの例
class Person {
def __init__(self, name, age)
self.name = name
self.age = age
def info(self)
print('名前は'+self.name+'です')
print(self..age+'歳です')
animal = Person("Astrostory", 30);
animal.info()
JavaScriptのクラスの例
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
info() {
console.log(`名前は${this.name}です`);
console.log(`${this.age}歳です`);
}
}
const animal = new Person("Astrostory", 30);
animal.info();
pythonとJavaScriptのクラスの違い
- pythonのinit()がJavaScriptではconstructorみたいだね。
- pythonのselfがjavaScriptだとthisに変わる
- クラスや中のメソッドには ; をつけない