技術メモ

役に立てる技術的な何か、時々自分用の覚書。幅広く色々なことに興味があります。

pythonのargsとkargsの使い方色々

※実行環境 python3.6

########### 基本的なargs
def argsfunc(*args):
    return args[0] + args[1]
print(argsfunc(1,2))
# print(argsfunc(dog=1, cat=2)) 引数名を与えるとargsとして認識してくれない

########### 基本的なkwargs
def kwargsfunc(**kwargs):
    return kwargs["a"] + kwargs["b"]
print(kwargsfunc(a=1,b=2))

def multifunc(*args, **kwargs):
    return args[0] + args[1] + kwargs["a"]
print(multifunc(1,2,a=3,b=4))

########### デフォルト引数と併用するケース
def multifunc2(first, second=0, *args, **kwargs):
    return first + second + args[0] + kwargs["a"]
print(multifunc2(1,2,3,a=4)) #>10
# print(multifunc2(1, second=2, 3, a=3)) #ダメ。変数指定して渡すのは全て後に書かないといけない

def multifunc2_2(first, *args, second=0, **kwargs):
    print("second: {}".format(second), end="| ")
    return first + second + args[0] + kwargs["a"]
print(multifunc2_2(1, 3, second=2, a=3)) 
print(multifunc2_2(1, 3, 2, a=3)) #>7 #3番目の引数はsecond=2のつもりなのにargs[1]として認識されてしまう


def multifunc3(first, second=0, **kwargs):
    return first + second + kwargs["a"]
print(multifunc3(1,2,a=3))
print(multifunc3(1,second=2,a=3))


############ キーワードが重複するケース # 定義だけではエラーにならない。呼び出そうとするとTypeError
def duplicate_kwargs(first, second=0, **kwargs):
    return first + second + kwargs["first"]
# print(duplicate_kwargs(1,2,first=3)) 
# >TypeError: duplicate_kwargs() got multiple values for argument 'first'

############ 可変長引数の重複はSyntaxError
# def kwargs_duplicate(**kw1, **kw2):
#    return kw1["a"] + kw1["b"] + kw2["a2"]

############ 可変長引数が引数の前に来るのはSyntaxError
# def kwargs_head(**kw1, second=0):
#    return first + second + kw1["a"]

############ argsを先に使うと、後ろの変数は全て変数指定して渡さないといけなくなる
def args_head(*args, first, second=0):
    return first + args[0] + second
# print(args_head(3,1,2)) #変数名を指定しない場合全部argsとして認識されるのでfirstが無いと怒られる
print(args_head(3,first=1,second=2)) #OK

エクセルで編集したデータをそれぞれのシート名でCSVに変換する【python】

動作確認環境

python3.6.1
pandasが必要。必要に応じて以下コマンドでインストールする。

pip install pandas

コード

import pandas as pd
import sys

def excel_to_csv(filename,
                target_sheet_index = None,
                target_folder = "./"):
    '''
    エクセルで編集したデータをそれぞれのシート名でCSVに変換する
    
    Parameters
    ----------
    filename: string
        変換元のエクセルファイル
    target_sheet_index: list of int
        何番目のシートを変換するかをリストで表記。
        0番目から始まる。指定しない場合は全シートが選ばれる。
    target_folder: string, default './'
        フォルダ名を指定して出力。
    '''

    excel_file = pd.ExcelFile(filename)
    sheetnames = excel_file.sheet_names
    excel_file.close()
    if target_sheet_index == None:
        target_sheet_index = range(len(sheetnames))
    for i in target_sheet_index:
        try:
            data = pd.read_excel(filename, sheet_name = sheetnames[i])
            output_file = target_folder + sheetnames[i] + '.csv'
            data.to_csv(output_file, index = False, date_format='%Y/%m/%d')
            print('convert success: ' + sheetnames[i])
        except Exception as error:
            print(error)
            continue
        
if __name__=="__main__":
    filename = sys.argv[1]
    try:
        target_sheet_num = int(sys.argv[2])
        target_sheet_index = list(range(target_sheet_num))
    except IndexError:
        target_sheet_index = None
    excel_to_csv(filename=filename,
                target_sheet_index=target_sheet_index, 
                target_folder="./data/")

プログラムで月ごとの営業日数を求める

月ごとの営業日数を求めたい事があったので、pythonで簡単にできるんじゃないかと思ってやってみた。

祝日計算

祝日計算には内閣府csvファイルを取ってくる方法を見つけた*1が、これだと振替休日などに対応できない。
そこで、こちらで紹介されているjpholidayを使った。
github.com

コード

実行前に

pip install jpholiday

としてjpholidayを取ってくる必要がある

import datetime, jpholiday

def is_holiday_or_weekend(date):
    return date.weekday() == 6 or date.weekday() == 5 or jpholiday.is_holiday(date)

def businessday_count(year, month):
    date = datetime.date(year, month, 1)
    sum = 0
    while month == date.month:
        if not is_holiday_or_weekend(date):
            sum += 1
        date = date + datetime.timedelta(1)
    return sum

if __name__=="__main__":
    year = 2019
    for i in range(1,13):
        print(i,end="\t")
        print(businessday_count(year, i))

結果

1       21
2       19
3       20
4       20
5       19
6       20
7       22
8       21
9       19
10      21
11      20
12      22

おまけ

月の末日を取ってくる

date - Get Last Day of the Month in Python - Stack Overflow

monthrange(year, month)
Returns weekday of first day of the month and number of days in month, for the specified year and month.
>>> import calendar
>>> calendar.monthrange(2002,1)
(1, 31)
>>> calendar.monthrange(2008,2)
(4, 29)
>>> calendar.monthrange(2100,2)
(0, 28)