今までに学んだ諸機能の復習

「Python言語によるビジネスアナリティクス」の付録参照

本のサポートページ

http://logopt.com/python_analytics/

オブジェクトの型について

A.1.1 数と論理型

type関数を用いて,以下の出力結果を得なさい.

  1. float

  2. int

  3. complex

  4. bool

set

A.1.2 文字列

フォーマット文字列

文字列の中に変数を表示させたいときがある。そのような場合には、以下のフォーマット文字列を用いる。

x = 100
y = 3.14
print(f"{x}{y}")

問題

  1. 文字列 s='PythonVideoCheckProblem' から,スライス表記を用いて 'onVide' を抜き出しなさい.

  2. 文字列s='PythonVideoCheckProblem' をすべて大文字にしなさい.

  3. 以下の文字列,並びに format を用いて,'Python,Video,Check,Problem' を作成しなさい.なお,単語の間には ',' を挟むこと.

    s1 = 'Problem'
    s2 = 'Python'
    s3 = 'Check'
    s4 = 'Video'
    
  4. 引数として与えた文字列が全て小文字なら True.そうでないなら Falseを返す関数を作りなさい. 例として,文字列 s='PyThOn' を関数の引数として与えて判定しなさい.

  5. 小文字として与えた文字列の先頭が母音('a','i','u','e','o')である場合には,'an 'を,そうでない場合には 'a 'を加えた文字列を返す関数を作れ. 例として,'apple'と'pen'を引数として与えた関数の返値を出力せよ.

A.1.3 リスト

主なメソッド

  • L.count(x) : L内での xの生起回数を返す.
  • L.index(x) : L内で xが最初に発生する添え字を返す.ない場合には例外(エラー名)を返す.
  • L.append(x) : Lの最後に要素 xを追加する. L+=[x] と同じ効果.
  • L.insert(i,x) : Lの $i$番目の添え字に要素 x を挿入する. L[i:i] =[x] と同じ効果.
  • L.remove(x) : Lで最初に発生する x を削除する.
  • L.extend(L2) : Lの末尾にリスト L2を追加する.
  • L.pop(i) : Lの i番目の要素を削除し,返す.iが省略された場合には最後の要素を削除.
  • L.reverse() : Lを逆順にする.
  • L.sort() : Lを小さい順に並べ替える.
  • enumerate(L) : リスト Lの添え字と要素のタプルのジェネレータを返す.

enumerateの使用法

リストの中身とそれが何番めなのかを同時に使いたいときがある。そのような場合には、enumerate関数を用いて反復を行えば良い。

for i, s in enumerate(["A", "B", "c"]):
    print(f"{s}{i} 番目")

>>>
A  0 番目
B  1 番目
c  2 番目

問題

  1. リスト L = [ 'Marvelous', 'Fantastic', 'Amazing!!' ] 内の文字列を,s='Python!! ' を区切り文字として結合し,表示せよ

  2. 文字列s = 'Payatahaoan' のうち,'a' を区切り文字として文字列s を分割したリストで表示せよ.

  3. リスト L = [1,2,3,4,5] が与えられている.

(1). 2番目の要素を削除せよ.

(2). L の2番目に 300 を代入せよ.

(3). L を逆順にせよ.

(4). スライス表記を用いて,2番目に [10,20] を代入せよ.

(5). メソッド append を用いて 100 を追加せよ.

'MarvelousPython!! FantasticPython!! Amazing!!'
['P', 'y', 't', 'h', 'o', 'n']
[1, 2, 3, 4, 5, 100]

問題

  1. 文字列 s='May I have a large container of coffee'を空白を区切り文字として分割し,分割した文字列の長さを順に表示せよ.何になるか?

  2. 文字列 s='How I want a drink alcoholic of course after the heavy lectures involving quantum mechanics and if the lectures were boring or tiring then any odd thinking was on quartic equations again' を空白を区切り文字として分割し,分割した文字列の長さを順に表示せよ.何になるか?

A.1.5 辞書

主なメソッド

  • D.keys() : 辞書Dのキーから成るオブジェクトを返す.
  • D.values(): 辞書Dの値から成るオブジェクトを返す.
  • D.items(): 辞書Dのキーと値のタプルから成るオブジェクトを返す.
  • D.get(k,default) : キーkが辞書Dに含まれているときD[k]を返し,それ以外のときdefaultを返す.
  • k in D : 辞書Dがキーkを含むときTrue,含まないときFalseを返す.
  • del D[k] : 辞書Dのキーkを削除する. 

問題

  1. 辞書 D = { 'Mary':126, 'Jane':156, 'Sara': 170 } が与えられている.
    1. キー'Mary'の値,126を180に変更せよ.
    2. メソッドを用いて,キーのリストを表示せよ.
    3. メソッドを用いて,値のリストを表示せよ.

問題

  1. 与えられた正数 $n$ に対して,$n$ 行 $n$ 列のランダムな行列で,各要素が[1,10]の一様整数乱数の行列を,行と列のタプルをキーとし,要素を値とした辞書を用いて作成せよ.
  2. 同じ大きさの行列をもう1つ作成し,行列の積を求めよ.

A.1.6 集合

主なメソッド

  • S.add(x) : 集合Sに要素xを加える.
  • S.pop() : 集合Sから適当な要素を抽出し,その要素を削除する.
  • S.remove(x) : 集合Sから要素xを削除する.
  • S.issubset(T) : 集合Sが集合Tの部分集合であるときTrue,そうでないときFalseを返す. $S<=T$ と同じ効果.
  • S.issuperset(T) : 集合Tが集合Sの部分集合であるときTrue,そうでないときFalseを返す. $S>=T$ と同じ効果.
  • S.union(T) : 集合SとTの和集合を返す. $S|T$ と同じ効果.
  • S.intersection(T) : 集合SとTの共通部分を返す. $S \& T$ と同じ効果.
  • S.difference(T) : 集合SとTの差集合を返す. $S-T$ と同じ効果.
  • S.symmetric_difference(T) : 集合 SとTの対称差集合(S と T のうち,共通部分に含まれない要素から成る集合)を返す. $S$^$T$ と同じ効果.

問題

集合 S = { 1,2,3,4,5 } と集合 T = { 2,4,6 } が与えられている.

  1. SとTの和集合を表示しなさい.

  2. SとTの差集合を表示しなさい.

  3. SとTの共通部分を表示しなさい.

  4. 集合Sの要素 2 を削除し,もう一度SとTの共通部分を表示しなさい.

  5. “banana”の各文字なら成る集合と,”apple”の各文字から成る集合の和集合と共通部分を計算するプログラムを示せ.

A.2 演算子

演算子は他のプログラミング言語と同様に,以下の順で優先順序をもつ.

  1. 括弧 ( )
  2. べき乗(指数演算) $**$
  3. 乗算 $*$ ,除算 $/$, 整数除算 $//$, 剰余 %
  4. 加算 $+$, 減算 $-$

Python3では,割る数と割られる数が両方とも整数の場合でも,除算 $/$ は浮動小数点数を返す. たとえば, $4/5$ は0.8を返す. 整数除算を行いたい場合には,演算子 $//$ を用いる.たとえば, $4//5$ は0を返し, $4//5.0$ は0.0を返す.

文字列やリストに対しても数値と同様の加算や乗算を行うことができる. たとえば,文字列 s='abc'に対して, s+'d' は'abcd'を返し, $s*2$ は'abcabc'を返す. リストでも同様に$[0]*3$ は[0, 0, 0]を返す.

if文やwhile文の中では,比較や論理条件を表す演算子が用いられる. <= は以下,< は未満,>= は以上,> は大きい,==は等しい,!= は等しくないときに真になり, それ以外のとき偽になる演算子である.

isは2つのオブジェクトが等しいか否かを判定する演算子である. たとえば,L=[1,2]に対して,L==[1,2]は真であるが,L is [1,2]は偽となる.

in は集合やリストなどの要素であるとき,not in は要素でないときに真になり,それ以外のとき偽になる演算子である. たとえば, リストL=[5,6,3,2]に対して3 in Lは真を返す.

in 演算子は日本語の文字列 'あけまして' に対しても適用可能であり 'あ' in Lは真を返す. 論理演算子and やor は,それぞれ論理積と論理和をとる演算子である. 真を正の整数(通常は $1$),偽を $0$ としたとき,論理積は乗算,論理和は加算に対応する. たとえば,(1<4) or (5<4)は1<4が真なので,$1+0=1$ となるので,真になる.

他にも, 展開演算子($*$と$**$)がある.

演算子 $*$ をリスト,集合,辞書などの前に付けることによって,その要素(辞書の場合にはキー)をタプルに展開する.

例として,集合,辞書,ジェネレータ(リスト)をそのまま出力する場合と,タプルに展開してから出力する場合を以下に示す.

a = {1, 2, 3, 4}
b = {"hello": "world"}
c = range(5, 10)
print(a, b, c)
{1, 2, 3, 4} {'hello': 'world'} range(5, 10)
print(*a, *b, *c)
1 2 3 4 hello 5 6 7 8 9

演算子 $*$ は,以下のように2つのリスト内から,最小の要素を探すときに便利である.

L1 = [6, 3, 4, 300, -10]
L2 = [5, 8, 4, 3, 100]
print(min(*L1, *L2))
-10

演算子 $*$ がタプルに展開するのに対して,演算子 $**$ は辞書に展開する.

例として,3つの辞書を展開してから再び1つの辞書としてまとめてみる.

d1 = {"Sara": 165, "Mickey": 120}
d2 = {"Minny": 110}
d3 = {"Kitty": "Three Apples", "Mickey": 200}
{**d1, **d2, **d3}
{'Sara': 165, 'Mickey': 200, 'Minny': 110, 'Kitty': 'Three Apples'}

キー'Mickey'の値が200になっていることから分かるように,キーが同じ場合には,後に書いた辞書(この場合にはd3)の値に上書きされる.

展開演算子は,関数の複数の引数の指定の際に用いられる.

問題

5 / 3 の出力結果は,1.6666666……となってしまう.これを,整数部分のみ出力を得たい場合はどのような演算子を用いるべきか?

A.4 関数

無名関数 lambda と高階関数 map

lambdaを使うと、その場だけで使用する名前をつけない関数を定義できる。

mapは、第1引数の関数を第2引数のものに対して適用した結果を返す。 例えば、リスト[1,2,3,4,5]を2乗したリストは、lambda関数とmapを用いて、以下のように計算できる。

list( map(lambda x: x**2, [1,2,3,4,5]) ) 

>>>
[1, 4, 9, 16, 25]

位置引数とキーワード引数

関数の引数は順番で指定する位置引数と、名前を指定するキーワード引数がある。

位置引数の後にキーワード引数を書く.

def f(name, weight):
    print("Name is", name, "whose Weight is", weight, "kg")

f("Kitty", 2)  # 位置で呼び出し
f(name="Kitty", weight=2)  # キーワードで呼び出し
f("Kitty", weight=2)  # 位置とキーワードを混ぜて呼び出し(位置引数は必ずキーワード引数の前;逆にするとエラーする)

>>> いずれも以下の出力を得る
Name is Kitty whose Weight is 2 kg

既定値

引数を定義する際に、既定値(デフォルト値)を指定することもできる。既定値は省略した場合に、その値が代入される。

def f(name, weight = 100):
    print("Name is", name, "whose Weight is", weight, "kg")

f("Kitty")  #第2引数を省略して呼び出し

>>>
Name is Kitty whose Weight is 100 kg

任意の数の引数

数が事前には分からない複数の引数も定義できる。位置引数の場合には*args (argumentsの略)で、キーワード引数の場合には**kwards (keywordsの略)で指定する。

例えば、引数の和を返す関数を位置引数を用いて書くと、以下のようになる。

def f(*args):
    s = 0
    for i in args:
        s += i
    return s

f(1, 2, 3, 4, 5)
> >>
15

名前と任意の数の属性を出力する関数は、キーワード引数を用いて、以下のように書くことができる。

def f(name, **kwards):print(f"Name is {name}")    for i in kwards:
        print(i, " is ", str(kwards[i]))


f("Kitty", weight=2, height=80)

>>>
Name is Kitty
weight  is  2
height  is  80

問題

  1. 引数を2つ与え、それらの和を出力する関数 printSum( x, y ) を作成し,その関数に既定値を与え,printSum() と引数なしで実行した場合,出力結果 10を得られるように作成せよ.

  2. 無名関数 lambda を用いて,与えた数の2乗が返るような関数を作成し,表示せよ.

  3. 文字列を合体し,3回繰り返したものを返す関数を作成せよ.

A.5 内包表記

  • リスト内包表記
  • ジェネレータ内包表記
  • 集合内包表記
  • 辞書内包表記

問題

  1. $0$ から $10$ までの整数のリストを内包表記で表示せよ.

  2. $0$ から $5$ までの整数 $x$ に対して, $(x, x^2, 2^x)$ からなるタプルのリストを内包表記で作成せよ.

  3. ジェネレータ内包表記とsum関数を用いて,$0$ から $10$ までの整数でかつ,奇数のものの合計を表せ.

  4. $0$ から $5$ までの整数に対して,整数がキー,値がキーの2乗になるような辞書を,内包表記を用いて表せ.

A.8 モジュール

import モジュール名
import モジュール名 as 別名
from モジュール名 import 関数やクラス

randomモジュールの主要な関数

  • seed(x) : xを用いて乱数の初期化を行う. xを省略した場合には現在のシステム時間で初期化される.
  • random() : $[0.0, 1.0)$ の一様ランダムな浮動小数点型の数を返す.
  • randint(i,j) : 整数 $i,j$ ($i$ $\leq$ $j$) に対して $i \leq k \leq j$ の一様ランダムな整数 $k$ を返す.
  • shuffle(L) : リストLの順序をランダムに混ぜる.
  • choice(L) : リストLからランダムに1つの要素を選択する.

問題

  1. mathモジュールをインポートし,

    1. $2$ の平方根を表示せよ.

    2. $6$ の階乗を表示せよ.(階乗を表示するには,factorial() を用いる.)

  2. random モジュールから,randint関数, shuffle関数 のみをインポートし、

    1. $-5$ 以上,$3$ 以下の一様ランダムな整数を発生させよ.

    2. リスト $L = [1,2,3,4]$ の順序をランダムに混ぜよ.

  3. itertoolsモジュールをインポートし,

    1. range(5)内の要素の長さ $2$ の(繰り返しを許さない)順列を生成し,リスト型で表示せよ.
    2. range(5)内の要素の長さ $2$ の(繰り返しを許さない)組み合わせを順に生成し,リスト型で表示せよ.

問題(randomモジュールの応用)

  1. 各期の需要が平均100,標準偏差10の正規分布のとき,100期分のシミュレーションを行い,需要が110を超える期数を調べるプログラムを作成せよ.

(ヒント:正規分布にしたがう擬似乱数はrandomモジュールのgauss関数(もしくはnormalvariate関数)で生成できる.引数は平均と標準偏差である. )

  1. あるスーパーで販売しているある商品の在庫を管理したい.

いま,$t-1$日の在庫量の営業後に在庫を調べて,発注量 $x[t]$ を決める.発注した商品は翌日の朝に届き, それによって $t$ 日の営業後の在庫 $I[t]$ は,以下のように決まるものとする.

$$ I[t] = I[t-1]+x[t] –D[t] $$

ここで $D[t]$ は$t$日の需要量であり,需要が平均100,標準偏差10の切断正規分布(負の場合には0とした正規分布)とする. また,最初の日($t=0$)の営業後の在庫は0であると仮定する.

以下の2つの在庫管理方策のプログラムを作成せよ.

  • (s,S)方策:在庫量 $I[t-1]$ が $s$ 未満であるなら,翌朝の在庫が $S$ になるように発注する.

  • (Q,R)方策:在庫量 $I[t-1]$ が $R$ 未満であるなら,$Q$ だけ発注する.

100日のシミュレーションの後で,発注費用,在庫費用,品切れ費用の合計を計算するプログラムを作成せよ.ただし,毎日の営業後の在庫量が0以上の場合には1個あたり10円の在庫費用がかかり,在庫量が負の場合には,1個あたり100円の品切れ費用がかかるものとする.(負の在庫は顧客が待っている状態を表し,翌日の朝に商品を引き取ると仮定する.これをバックオーダーと呼ぶ.)また,発注を行う度に(発注量が正のときに)発注費用1000円がかかるものとする.また,作成したプログラムを用いて,各方策のパラメータはどのように設定すれば総費用が最小になるか考察せよ.