初心者データサイエンティストの備忘録

調べたことは全部ここに書いて自分の辞書を作る

【Python】argparseとタスクスケジューラを使った定期実行

Pythonのコードに引数を渡してコマンドラインで実行したいときがあります。その際に、用いるモジュールがargparseです。 このargparseの使い方についての記事はググれば多く見つかります。しかし、使いどころに関する記事は多くないです。そこで、私なりにargparseの使いどころを考えてみました。

※使い方については、下記の記事を参考にしました。

docs.python.org

qiita.com

argparseができること

argparseを使うと、コマンドライン上でPythonコードに引数を渡して実行することができます。例えば、下記のPythonコードを実行することを考えます。

class UserInfo:
    def __init__(self, name):
        self.name = name
    
    def print_name(self):
        print(self.name) 


user_info = UserInfo(name="Suzuki")
user_info.print_name()

これは.pyでも.ipynb(Jupyter)でも実行できるコードです。これを下記のような形でコマンドラインから実行させたいときに使うのが、argparseです。

python 適当なファイル名.py "Suzuki"

上記の例を実装してみます。まず、下記のような.pyファイルを作成します。ファイル名はarg_user_info.pyとしました。

import argparse

# argparseの設定
parser = argparse.ArgumentParser(description="user_infoを実行するためのargparser")
parser.add_argument("name")
args = parser.parse_args()

# ユーザの情報を取り扱うclass
class UserInfo:
    def __init__(self, name):
        self.name = name
    
    def print_name(self):
        print(self.name) 

user_info = UserInfo(name=args.name)
user_info.print_name()

そしてコマンドラインで次を実行するだけです。

python arg_user_info.py "Suzuki"

上記を実行して、コマンドライン上にSuzukiと表示されればOKです。

argparseの使いどころ

argparseは下記のようなときに使います。

  • コマンドライン上で.pyファイルを動かす
  • そのときに引数を.pyファイルに渡す必要がある

なので、argparseの使いどころを考えるため、バッチファイルなどで.pyを動かさなければいけない状況を考えることにしました。

色々なシチュエーションがあると思うのですが、「ここでは.pyファイルを引数を変えて定常実行したい」というシチュエーションを考えてみます。恐らくこれが基本的な使い方なのではないかと思うからです。

今回は、図1が実現できるようにスクリプトの作成やタスクスケジューラの設定をしようと思います。

図1:やりたいこと

そのために、図2の構成でタスクスケジューラや各コードを構築していきます。

図2:タスクマネージャーと各コードの関係性

実装

print_time.pyでは、受け取った引数をファイル出力したいので、下記のようなスクリプトにします。

class WriteAtTime:
    def __init__(self, at_time):
        self._at_time = at_time

    @property
    def at_time(self):
        return self._at_time

    def return_at_time(self):
        return self.at_time

    def write_at_time_on_text(self):
        f = open(self._at_time+".txt", 'w')
        f.write(self.return_at_time())
        f.close()

arg_print_time.py

arg_print_time.pyはmkdir_at_time.batから引数(現在時刻)を受け取り、print_time.pyで実装したwrite_at_time_on_text()を実行します。

import argparse
from print_time import WriteAtTime

parser = argparse.ArgumentParser(description="print_hello_time.pyをbat実行させるためのスクリプト")
parser.add_argument("t")
args = parser.parse_args()

ins_print_hello_time = WriteAtTime(at_time=args.t)
ins_print_hello_time.write_at_time_on_text()

mkdir_at_time.bat

ここでは、現在時刻を取得し、ディレクトリの作成とarg_print_time.pyの実行を行います。

set time2=%time: =0%
set time3=%time2:~0,2%%time2:~3,2%%time2:~6,2%
mkdir %time3%
cd %time3%
python ..\arg_print_time.py %time3%

タスクスケジューラ

1分間隔で15分間mkdir_at_time.batを実行し続けるようにタスクスケジューラを設定しました。 設定の仕方は下記を参照しました。

minto.tech

se-abeaver.com

まとめ

  • argparseはコマンド上で引数を渡して.pyを実行する際に用いる
  • 上記の作業が必要になるのは、タスクスケジューラなどバッチファイルしか実行できないソフトを使って.pyを実行したいときなど

【Python】抽象基底クラスについて勉強したこと

Pythonの抽象基底クラスについて勉強したので、まとめようと思います。

抽象基底クラスとは

抽象基底クラスの定義については、抽象クラスを使うメリット - Qiitaが理解しやすかったです。この記事によれば、抽象基底クラスとは、

  • 専ら他のクラスに継承されることによって使用される。
  • インスタンスを持たない。

であると説明されています。クラスから具体的なインスタンスを作り出さないことから「抽象」の名前が、専ら他のクラスに継承されることによって使用されることから「基底」という名前がついているのではないかと私は推測しています。

上記のように説明されてもどんなクラスが抽象基底クラスなのかわかりにくいので、具体例を挙げてみます。

from abc import ABCMeta

class Parent(metaclass=ABCMeta):
    def print_name(self):
        pass
    
    def print_age(self):
        pass

上記のParentクラスが抽象基底クラスです。Parent内で定義されるメソッドprint_name、print_ageは処理が定義されていません。これらのメソッドは、子クラスで定義されることが期待されており、抽象基底クラスでは定義しません。 なお、Parentの引数でmetaclass=ABCMetaとしていますが、この設定をすることでParentは抽象基底クラスであると定義されることになります。

デコレータ@abstractclassmethod

抽象基底クラス内のメソッドに@abstractclassmethodというデコレータをつけることができます。このデコレータを付与されたメソッドは、必ず子クラスで定義しなければなりません。実装しないとインスタンス作成時にエラーが出力されます。 これも例を挙げます。

上記のスクリプトを見るとTreatUserInfoWITHPasswordクラスではちゃんとcombine_user_infoメソッドが定義されており、インスタンス作成時にエラーの出力がありません。しかし、TreatUserInfoWITHOUTPasswordクラスにはcombine_user_infoメソッドが定義されておらず、それによってエラーが出力されています。

抽象基底クラスの使いどころ

ここまで抽象基底クラスを定義してきましたが、どのようなときに使うのでしょうか?それは、子クラスに必ず同じ名前のメソッドを持たせたいときです。

また、例を挙げて説明します。

上記のスクリプトでは、各メソッドは下記のような関係になっています。

処理内容が子クラス共通 処理内容が子クラス共通ではないが、必ず実装したい
print_name combine_user_info

このように、処理内容が子クラス共通ではないが、必ず実装したいメソッドがある際に抽象基底クラスを使います。

おまけ

あとは、自分が勉強したときに疑問に感じたことと、その回答をまとめていきます。

抽象規定クラスではないクラスの継承と抽象規定クラスの継承の違いはなに?

一言でいえば、抽象基底クラスではないクラスの継承だと、メソッドの実装し忘れに気付きにくいです。それが、抽象基底クラスの@abstractclassmethodを使うことで、実装し忘れに気付くことができます。

ABCとABCMetaの違いはなに?

ABCはABCMetaを継承したヘルパークラスです。これを使って抽象基底クラスを作ることもできます。

from abc import ABCMeta, ABC

# ABCMetaを使って抽象基底クラスを作成
class Parent(metaclass=ABCMeta):
    pass

# ABCを使って抽象基底クラスを作成
class Parent(ABC): # ABCを継承して作る
    pass

どちらを使っても挙動は(多分)同じです。

ダックタイピングとの関係性はなに?

ダックタイピングとは、異なるインスタンスに対して、同じメソッドで処理を呼び出せることを言います。
(過去記事) aisinkakura-datascientist.hatenablog.com

抽象基底クラスを使うことで、ダックタイピングも実装しやすくなります(抽象基底クラスを使わなくてもダックタイピングできるが、あった方が実装しやすい)。その理由としては、@abstractclassmethodを使うことで同じ名前のメソッドを子クラスに定義することを強制できるからです。

from abc import ABCMeta, abstractclassmethod

class Animal(metaclass=ABCMeta):
    @abstractclassmethod
    def cry(self):
        pass
    
class Dog(Animal):
    def cry(self):
        print("wow")
        
class Cat(Animal):
    def cry(self):
        print("nya")

# クラスを問わず実行できるメソッド
def animal_cry(obj):
    obj.cry()

# インスタンス作成
dog = Dog()
cat = Cat()

# 実行
animal_cry(dog)
animal_cry(cat)

Animalクラスで定義するcryに@abstractclassmethodがついていることで、DogかCatのどちらかでcryを実装し忘れていても、animal_cryの実行を待たず、インスタンス作成時に気付くことができます。 これは、現実の開発現場では結合テストを待たず、単体テスト実行時に実装し忘れに気付くことにつながります。

【読書記録】ひとはなぜ「認められたい」のかー承認不安を生きる知恵

本書を読んだ理由

私は承認欲求が人一倍強いです。また、それゆえ、承認欲求が満たされない苦しさを常に抱えています。 この苦しさと向き合う中で、私は次の二つの問いを持つようになりました。

  • 私はなぜ承認欲求が強いのだろう?
  • どうすれば承認欲求が満たされない苦しさから脱却できるだろうか?

この問いに対する答えを探していた時に、本書と出会いました。

結論から言えば、本書を読むことで自分の承認欲求が強い理由については、ある程度見当をつけられそうだと思いました。しかし、承認欲求が満たされない苦しさからの脱却については、本書からヒントは得られたものの、一人で解決することは難しそうだとの印象を持ちました。これは本書の不備というよりは、承認欲求が満たされない苦しさから脱却することが本質的に難しいからだと思います。

私はなぜ承認欲求が強いのだろう?

承認の種類

「私はなぜ承認欲求が強いのだろう?」という問いを考える上で、非常に参考になった考え方があります。それは、承認にはいくつかの種類があるという考え方です。本書では、承認を「何が認められるのか?」という観点から二種類、「誰に認められるのか?」という観点から三種類に分類しています。

図1:承認の種類

過去の振り返り

私はどの承認欲求がいつ満たされていたのかということを考えるため、過去を振り返ってみることにしました。 過去を振り返ることで、今の承認欲求のルーツが分かると考えたためです。
図2は、先ほど説明したそれぞれの承認欲求が、過去どのような状態だったのかを表したものです。なお、一般的承認は受ける機会がなかったので、図からは割愛しています。

図2:過去の承認欲求の満たされ方

図2を見てみると、中学~高校までは「行為×集団的」の承認が満たされていました。しかし、大学に入ると他の承認欲求と同様に承認欲求が全く満たされない日々が続いていることがわかります。

私の承認欲求が強い理由

私の承認欲求が強い理由を一言でいえば、中学~高校まで満たされていた「行為×集団的」の承認を忘れることができないからです。過去に唯一満たされていた「行為×集団的」の承認に、今もしがみついているのです。
また、それゆえ「存在×親和的」の承認が現在においては満たされているにも関わらず、自分が満たして欲しい承認(=「行為×集団」の承認)は満たされないために承認不安を抱えている状態になっています。

なお、本書には行為の承認について下記の考察がされていました。(p140から引用)

親和的承認は存在そのものが受容される「存在の承認」でもあり、この経験が乏しい人ほど、「行為の承認」に執着し、ありのままの自分では受け入れられない、と感じるようになります。

この文章は読んだ瞬間に私のことを指している!という強い納得感がありました。

どうすれば承認欲求が満たされない苦しさから脱却できるだろうか?

承認不安を解消する方法

承認不安を解消する方法を本書は下記のように説明しています(p138から引用)。

承認不安を克服し、自由に生きるために、自己分析の方法を示してきましたが、それは自分の感情から承認不安、欲望、義務感に気づき(自己了解)、さらに自己ルールの分析をとおして不安の原因を突きとめ、自己ルールの歪み、行動を見直していく、という方法でした。

この文章を理解するため、自己ルールと自己了解という言葉について下記で補足します。

自己ルールと自己了解

まず、自己ルールについて説明します。自己ルールとは自分の中に持っている行動の基準です。例えば、「中学生が勉強をしなければいけないのに、友達に遊びに誘われた」というシチュエーションを考えてみます。このとき、「遊びにも行きたいし、友達にも悪いが勉強しなければまずい。勉強しよう!」と自分の行動を決めるための基準が自己ルールです。

この自己ルールですが、自分にとって常に良い結果をもたらすとは限りません。欲望と義務のバランスが取れている場合は、自己ルールにしたがうことで、達成感を得られるといったポジティブな結果につながることもあります。しかし、欲望が強すぎれば義務を果たすことができず、逆に義務が強すぎれば欲望を満たせない状態になってしまいます*1。(図3)

図3:欲望と義務感のバランス

不適切な自己ルールを排除し、自分の人生において適切な自己ルールを身に着けることが幸福に生きるためには必要です。 では、不適切な自己ルールを排除し、適切な自己ルールを身に着けるためには何をしたら良いのでしょうか?その答えにつながる概念が自己了解です。

自己了解とは、読んで字のごとく自己の内面について理解することです。先ほどの例でいえば、「今私は『勉強をしなければ親に怒られるな』や『勉強しなければ高校に落ちるな』という不安と『遊びに行きたいな』や『断ったら友達に悪いな』という欲望がある」と理解することが自己了解できた状態となります。

本書では、自己了解をすることは、歪んだ自己ルールに気付くきっかけになると述べられています。その理由を先ほどの例を通じて考えてみたいと思います。

上記の例では、「友達と遊びに行きたいが不安だ」というのが最初に生まれる感情でしょう。これを自己了解するために深堀すると、不安の正体は「親が怖い」や「高校に落ちる」という不安だと気付くことができます。

では、なぜ「親が怖い」と思うようになったのかということを考えてみます。例えば、過去にテストの成績が悪かったことで暴力を振るわれたとか、罵詈雑言を浴びせられたとかあればそれが原因だとわかります。 同様に、「高校に落ちる」という不安も、過去に塾で煽られたとか、名門高校に行かなければ生きる価値がないと周囲から教え込まれたとか思い出せればそれが原因だとわかります。

このように自己了解をすることができれば、根拠のない事柄(別にテストの点数が悪かったからと言って親は暴力を振るう権利はないし、名門高校に行けなくても死ぬ必要はない)に振り回されて自己ルールを形成してしまったのだなと自覚することができます。

ここまででの議論を図4にまとめました。

図4:自己了解をきっかけに自己ルールの修正に至る過程

我が身を振り返ってみて

私は大学生の頃、ひどい鬱状態になり毎週カウンセリングを受けていました。そのことを今振り返ってみると、カウンセリングを通じて自己了解はかなり進んだのではないかと思います。

しかし、その一方で歪んだ自己ルールは今でも強く自分を縛り付けています。なので、自己了解が進むことは、自己ルールを自覚する必要条件ではあるものの、歪んだ自己ルールを適切な自己ルールに書き換えるための十分条件ではないと感じています。 このことについて、本書では下記のように述べています。(p138から引用)

仮に自己了解によって承認不安を自覚できたとしても、歪んだ自己ルールを変えることは、かなりの勇気がいります。なぜなら、その自己ルールは承認に関わる危険を避けるためにあるからです。自己ルールを否定し、行動を変えるということは、いわば承認されない危険に身をさらすようなものですから、すぐには受け入れることができません。そんなことをしようとすれば、強い承認不安が喚起されて、無意識にブレーキがかかるでしょう。

どうやったら自己ルールを書き換えて健全な状態で生きることができるのか、それについて本書では銀の弾丸のような方法は示されていません。 なので、時間をかけて自分なりの自己ルールの書き換え方を模索するしかないと思っています。

まとめ

  • 承認にはいくつかの種類がある
    • 各承認が満たされていたかを振り返ることで、自分の承認欲求がどのように育ってきたかを理解することにつがなる
  • 自己ルールとは、自分の中にある行動の基準
    • 適切な自己ルールを持つことが幸福に生きるためには必要
    • 自己了解できることは、適切な自己ルールを持つきっかけとなる

*1:余談ですが、ニコマコス倫理学の文脈ではこのような状態はどちらも幸福ではないとしています

【Python】型ヒントの理解で苦しんだこと

Pythonの型ヒントについて勉強しているときに、理解に時間がかかったことをまとめようと思います。

型ヒントとは

Pythonの型ヒントとは、定義した変数や関数の引数や返り値の型を注釈することです。 例えば、valという変数にはintしか入れたくないという場合には、

val : int
val = 1

という書き方をします。このとき、注意しなければいけないことは、「valはint型である」という情報はあくまで注釈にすぎないということです。 したがって、次のような書き方をしてもエラーの出力はありません。

val : int
val = "1"

上記の例では、valにint型であると注釈をつけたのに、valに文字列型を入れてしまっています。しかし、Python動的言語であり、かつ「valはintである」という情報はあくまで注釈にすぎないため、エラーを出力することはありません。

Mypy

型ヒントの型と異なる型を変数に代入してもエラーは出力されないと上で書きました。それでは、型ヒントは何に役に立つのでしょうか? キーワードはMypyです。 宣言した型と異なる型の値が変数に代入されたときに、Mypyはエラーを出力してくれます。

例として次のGistを見てください。なおコマンド中のマジックコマンドはPythonの型定義の方法とは?型ヒントについてもわかりやすく解説に記載があったものを利用しています。

上記のGistの中で、In[2]を見ると型ヒントの型と異なる型を変数に代入しています。しかし、Pythonを実行する上ではエラーを出力することもなく、普通に実行できています。

次に、In[3]を見てください。In[3]ではMypyによるチェックが行われています。 Mypyのチェックを行うと、型ヒントの型と変数に代入した型が異なる場合に、エラーを出力しています。

以上のように、型ヒントはPythonを実行する上では影響を与えませんが、Mypyによって静的型付けのチェックをすることが可能になります。

理解に時間がかかったこと

typing.cast

typing.castメソッドを使い、型付けを行う方法があります。これについて、私は最初typing.castは型を変更するメソッドだと勘違いしていました。なので、下記のようなスクリプトを書いて、「なぜval2はstr型にならずint型のままなのだろう~」と考えていました。

しかし、実際はtyping.castメソッドは型チェッカー(今回はMypy)に型を伝えるだけの存在です。例えば次のスクリプトはMypyによるエラー出力があります。

%%typecheck --ignore-missing-imports

from typing import cast
from __future__ import annotations

x:int|str = 1

def kronecker_delta(y:int) -> int:
    if y >= 0 | y <= 1:
        return y
    return 0

print(kronecker_delta(x))

これはxがint|str型(intとstrの合併型)であるのに対し、kronecker_deltaメソッドの引数がint型であるためにMypyはエラー出力をします。このような場合に、typing.castは役に立ちます。次のスクリプトだとMypyによるエラー出力はありません。

%%typecheck --ignore-missing-imports

from typing import cast
from __future__ import annotations

x:int|str = 1

def kronecker_delta(y:int) -> int:
    if y >= 0 | y <= 1:
        return y
    return 0

x = cast(int, x)

print(kronecker_delta(x))

この場合は、xを最初にint|str型で指定しましたが、castによってint型であるとMypyに伝えています。そのため、kronecker_deltaの引数の型との矛盾が発生せず、Mypyはエラー出力をしません。

このことをイメージしたものが図1です。typing.castは型を変換するのではなく、型チェッカ―に型を教えるメソッドと私は理解しました。

図1:Mypyがtyping.castによって認識している型を変える

typing.overload

メソッドの引数と返り値に型ヒントを与える方法として下記の書き方があります。

def union(x:int|str, y:int|str) -> int|str:
    return x+y

var2: int = union(x=1, y=1)
var11: str = union(x="1", y="1")

しかし、この書き方だとMypyは次のエラーを出力します。

error: Incompatible types in assignment (expression has type "Union[int, str]", variable has type "int")
error: Incompatible types in assignment (expression has type "Union[int, str]", variable has type "str")

つまり、var2の出力がint型、var11はstr型なのに、unionの返り値はint|str型だとMypyは主張します。 このようなときに役に立つのがtyping.overloadです。

上記のメソッドunionはx, yがint型のときは出力は必ずint型になります。x, yがstr型のときは必ずstr型です。これを意識して書いたスクリプトが下記です。

from typing import overload

@overload
def union(x:int, y:int) -> int:
    ...

@overload
def union(x:str, y:str) -> str:
    ...

def union(x, y):
    return x+y

Mypyのための型ヒントをつけたメソッドを定義し(@overloadをつけたメソッド)、その後ろに処理を定義したメソッドを書くというのが@overloadの使い方です。

まとめ

  • typing.castは型を変換するメソッドではなく、型チェッカーに型を伝えるためのメソッド
  • typing.overloadは引数と返り値の型が1対1対応するメソッドを定義し、引数と返り値に合併型を使わないメソッドを構成するためのデコレータ

参考文献

【読書記録】NHK 100分 de 名著 アリストテレス『ニコマコス倫理学』

「『幸福』」を掴むためにどうすれば良いか?」という問いに対して、過去の偉人はどのように考えたのかを知りたくて手に取りました。

本を読んだ背景

私は会社で出世できていないことを非常に苦痛に感じており、この苦痛をどう取り扱うべきなのかに悩んでいます。そんな折、TV番組「100分で名著」を通じて「ニコマコス倫理学」と出会い、興味を持ちました。

要約と感想

三つの生活類型

アリストテレスは人間の生活は三つに分類できると主張します。 快楽的生活、社会的生活、観想的生活です。

快楽的生活とは、読んで字の如く快楽を幸福とする生活です。社会的生活とは、社会において自分がなんらかの役割を担っていくことを幸福とする生活です。そして、観想的生活とは、知ることを幸福とする生活で、アリストテレスはこれを究極に幸福な生活としています。

この分類を出世欲が強い自分に当てはめてみました。

私が出世したい理由は、2つあります。一つは、金銭的に豊かになり良い思いをしたいということです。もう一つは、出世することで社会から認められたいという気持ちです。

前者については金銭を通じて快楽を求めているということで、快楽的生活に当てはまると考えています。後者についても一見、社会的生活のように見えますが、内実自分自身が認められて良い思いをしたいという快楽に基づいています。

したがって、出世を求めて生きることは、私の場合、快楽的生活に当てはまると考えています。

快楽的生活の欠点

快楽的生活は、人間を安定的・持続的な幸福に導かないとアリストテレスは主張します。その理由を本書では次のように述べています。

快楽そのものは悪いものではないのですが、快楽を軸に人生を組み立てようとすると、刹那的な快楽に振り回されることになってしまい、安定した人生の道筋が見失われてしまうからです。

以上のことから、出世欲が強く、かつそれを叶える能力があったとしても、出世を求める生活が快楽的生活である以上、安定的・持続的な幸福を得ることはできないと考えています。

私はどうあるべきか

私の人生を振り返って、どのような時に幸福を感じたかと言うと、何かを知ったり分かったりした時です。

例えば、私は受験生のとき、大学合格やその先にある大学生活にあまり興味を持てませんでした。一方で、数学と物理と漢文を勉強している間だけは幸福を感じることができました。 その性格は今でも変わっておらず、出世したいと願いつつも、ときどき出世がめちゃくちゃどうでもよくなる瞬間があります。

以上のことを踏まえると、私は人生をかけて、知ることに幸福を感じる観想的生活を送ることが向いているのではないかと思います。

最後に

今まで勉強は何かの手段であるべきと教育されてきました。そのことに私は密かに苦痛を感じてきました。 今回、ニコマコス倫理学と出会えたことで、私が感じていた苦痛を言語化でき、かつ知ることを中心に据えた生活を送ることが非難されるべきではないことを確認できました。 今後は出世欲を弱め、知識欲を強める生き方をしていきたいと思います。

おまけ

出世欲について考える過程で、承認欲求についても考え込んでしまいました。 その際気が付いたのですが、承認欲求を満たせるか満たせないかは、運によるということです。つまり、自分の努力だけで承認欲求を満たすことは結構難しいのではないかということに気が付きました。

その理由としては、承認する主体が自分ではないからです。どんなに努力しても、その努力を認めてくれる人が偶然周りにいなければ承認欲求を満たすことは難しいです。

そういった意味で承認欲求とは人任せの欲求であり、これに依存しすぎるとかなり苦しい生活が待っているのではないかと思われます。

一方で、承認欲求は基本的な欲求の一つのようにも感じられます。どんな人間でも人から認められるという経験がなければ、精神が病むのではないかと思われます。以上のことから、承認欲求とは取り扱い注意な欲求であるのではないかと思うに至りました。

【Git】すごいぞrebase -i

Git上でコミットを修正したいとき、rebase -iさえ覚えていればいろいろできることを知り感激。 この感激を忘れないために記事にすることにしました。

git rebase -iでできること

git rebase -iでできることのうち、よく使うコマンドについてだけ書きます。

  • 過去のコミットメッセージの変更
  • 過去のコミットを合体させる
  • 過去のコミットを消す

具体的な手順

過去のコミットメッセージの変更

やりたいこと↓

コミットメッセージの変更

HEADを含めて2個前のコミットを修正したいので、下記のコマンドを打ちます。

git rebase -i HEAD~2

すると、下記のようなエディターが開くので、対象のコミットのpickをrewordに書き換え保存します。

図2:rebase -iで開いたエディタの編集

上記でエディターを保存して消すと、さらにエディターが開くのでtypoされたコミットメッセージを正しいコミットメッセージに修正します。

図3:コミットメッセージの修正

過去のコミットを合体させる

やりたいこと↓

図4:コミットの合体

今回も同じように、下記のコマンドを打ってエディターを開きます。

git rebase -i HEAD~2

このとき、エディターに記載された対象のコミットのpickをsquashに書き換えます。

図5:rebase- -iで開いたエディタの編集

さらに新しく開いたエディターを図6のように編集することで、コミットを合体し、かつコミットメッセージを修正することができます。

図6:コミットメッセージを修正して、コミットを合体させる

なお、図5でpickをsquashではなく、fixupと書き換えるとコミットメッセージを変えずにコミットを合体させることができます。(図7のようになります)

図7:コミットメッセージを変えずにコミットを合体する

過去のコミットを消す

やりたいこと↓

図8:コミットの削除

同じようにgit rebase -i をして、pickをdropに置き換えるだけです。

まとめ

git rebse -iを打つと出てくるエディターに対して、対象のコミットをpickから書き換えることで、様々なコミットの改変をできることを学びました。 pickから書き換える文字列とそれによって改変できる内容は下記の通りです。

  • 過去のコミットメッセージの変更:reword
  • 過去のコミットを合体させる
    • コミットメッセージを変更する場合:squash
    • コミットメッセージを変更しない場合:fixup
  • 過去のコミットを消す:drop

秋の江の島沖ライトジギング

かなーり久しぶりにライトジギング行ってきました。

船宿は島きち丸です。

shimakichimaru.com

船長さんや中乗りさんが非常に親切でした。初心者にはめちゃくちゃおすすめの船宿です。

タックル

  • ロッド:SHIMANO COLTSNIPER BB
  • リール:SHIMANO TWINPOWER C3000HG
  • ライン:PE1号+リーダー3号←船長さんにリーダーは5号くらいが良いと言われました
  • ルアー:40~80gのジグいろいろ

釣果

アオハタ:1匹

アオハタ

サバ:1匹

サバ

マルソウダ:1匹

マルソウダ

エソ:1匹

エソ(首落としてから写真撮り忘れていたことに気が付きました...)

他にもメジ(クロマグロの幼魚)が釣れましたが、持って帰ると法律的にアウトなのでリリースしました。

反省点

狙う水深が60mオーバーだと40gのジグだとさすがにきつい!
着底まで時間かかりすぎて、隣の人とお祭りしますね。今回は60mオーバーの場所がメインだったので、60-80gのジグがメインでした。 次回は60-80gのジグを充実させていこうと思いました。

特に今回は細長いジグに反応が良かったので、短くて太いタイプのジグだけでなく、細長いタイプを次回は入手して行こうと思います。 ちなみに、タックルベリーで150円で買ったジグでも普通に釣れました。重ささえあればジグは何でも良いという私の信念が強化されました。

湾ベイトめっちゃ良い
以前乗ったシーバスジギング船で湾ベイトを使って爆釣した経験があり、今回も役に立つのではないかと思って持っていきました。 私が持っていた湾ベイトが29gだったため、さすがに無理かと諦めていたところ、ルアーボックス内にジョイントノッカーの28gの重りを発見。 ダメ元で合体させて足元で泳がせてみたところ、意外とちゃんと泳ぐ。意外とありなんじゃないかと思って沈めてみると一発でヒット。 エソが釣れました。

その後も2回ヒットあったものの、残念ながらバラシ。シングルフックがジグ用のしかなかったため、ボディからフックが離れてしまっており、魚の口にちゃんとかからなかったのではないかと推察します。 次回はちゃんとしたシングルフックを装着して、かつ40gの湾ベイトを使って青物釣りたいところ。

湾ベイトはしゃくる必要ないので、女性や子どもにもお勧めです。もし私の子どもが将来一緒にライトジギングに来てくれるのであれば、湾ベイトは必ず持っていきます。

なんとか頑張った湾ベイト

レンタルロッドは厳しかった
レンタルロッドが恐らく鱒レンジャーかそれに類するものでした。鱒レンジャーで60gのジグはさすがにしゃくるのきつかったです。一緒に行った友人がレンタルロッドで苦戦しているのを見かねて、私のロッドと交代しました。 交代して1投目で釣れていたので、やっぱりロッドがよろしくなかったのでしょう。次回初心者と行くときは絶対に自分のロッド貸す。

tsurihack.com