Casio Python - 関数の作成と活用

Python Casio Python
 Casioグラフ関数電卓の Python を使ってみる
     - 関数の作成と活用:grp_color()関数の作成 
目次


初版:2020/07/06
追記修正:2020/07/10
前の記事 - 4. Casio Python への移植 |  次の記事 - 6. グラフィックス出力関数の追加


5. 関数の作成と活用:grp_color()関数の作成

前回作成した circle() 関数は以下のようになっています。

circle() の書式
 circle(x, y, r)
 x: 整数型 (int型)、円中心の x 座標
 y: 整数型 (int型)、円中心の y 座標
 r: 整数型 (int型)、円の半径


 circle() の関数定義:
from casioplot import *
from math import *

#draw circle
def circle(xyr):
 r*2406/383
 2*pi/p
 for i in range(p):
  px x+r*cos(i*a)
  if px<0 or px>383:
   continue
  py y+r
sin*(i*a)
  if py<0 or py>191:
   continue 
  set_pixel(int(px)int(py))
  show_screen()

この関数を少し拡張しようと思います。

点を描画する set_pixel() は、第一引数と第二引数でそれぞれX座標とy座標を指定しますが、第三引数で点の色を指定できるので、circle() 関数でも色を指定できるように拡張できます。

set_pixel() は、第一引数と第二引数を設定しなければエラーになりますが、第三引数は省略可能で、省略時はデフォルトで色が黒に指定されます。第三引数を指定した時だけ色を指定できる仕様です。そこで circle() 関数でも同様に、第三引数を省略可能で、かつ色指定できるように拡張してみます。


5.1 関数の引数について

関数 func() を定義するいは、def ステートメントを使います。

 def func():

行末にコロン : が必要です。コロンの下の行からインデントを入れて関数の中身を記述します。インデントレベルが同じ範囲が、関数定義の範囲になります。

さて、引数1、引数2を追加するには、以下のように書きます。

 def func(param1, param2):
  sum = param1 + param2
  print(sum)

第一引数と第二引数を加算した結果 sum を表示する関数ができました。

この関数を使う時は、例えば以下のようにします。

 func(1,2)

これが実行sあれると、1 + 2 の結果を表示します。
1つめの引数が param1 に、2つめの引数が param2 に自動的に割り振られます。このように引数の位置で割り振りされる引数を "位置引数 (Positional Arguments)" と言います。

次に、省略可能な第三引数を追加します。

 def func(param1, param2, param3=0):
  sum = param1 + param2 + param3
  print(sum)


param3 には、デフォルトで 0  としています。省略するとデフォルトの値が param3 に割り振られます。

 func(1, 2)

とすれは、1 + 2 + 0  の結果 3 が表示されます。

 func(1, 2, 3)

とすれは、6 が表示されます。

このような param3"デフォルト引数 (Default Arguments)" と言います。
デフォルト引数は、位置引数の後に設定する必要があります。

全ての引数をデフォルト引数にしてみます。全てにデフォルト値が設定されます。

 def func(param1=1, param2=2, param3=3):
  sum = param1 + param2 + param3
  print(sum)


すると、全ての引数を省略できます。

 fund()

とすると、全てデフォルトの値を使うので、結果 6 が表示されます。

では、

 func(param2=5)

とすると、1 + 5 + 3 の結果 9 が表示されます。

このように、位置を無視して記述できる引数を "キーワード引数 (Keyword Arguments)" と言います。

次のような関数定義をしてみます。

 def func(param1, param2, param3=3, param4=4):
  sum = param1 + param2 + param3 + param4

  print(sum)

第一引数と第二引数は位置引数、第三引数と第四引数はデフォルト値のある引数です。

 func(1, 2)

は、1 + 2 + 3 + 4 の結果 10 が表示されます。

 func(1, 2, 5)

は、第4引数が省略されデフォルト値を使うので、1 + 2 + 5 + 4 の結果 12 が表示されます。

では、第三引数を標略して、第四引数に値を設定しい時は、第四引数をキーワード引数にする必要があります。

 func(1, 2, param4=10)

とすると、1 + 2+ 3 + 10 の結果 16 が表示されます。

 func(param4=10, 1, 2)

とすると、エラーになります。キーワード引数は、位置引数の後に設定する必要があるからです。


5.2  関数内の変数の有効範囲 - 変数のスコープ

以下のスクリプトを実行してみます。

 sum = 100
 def func(param1, param2):
  sum = param1 + param2
  print(sum)

 func(1, 2)

関数定義の前(=外)に変数 sum があり、100 が代入されています。
関数定義内にも同じ名前の変数 sum があります。

このスクリプトの最後で実行される func() の結果は、3 となり、103 ではないことに留意してください。

関数定義の中の sum は、その有効範囲が関数内に限定され、関数の外の sum とは別物になります。func() が実行される時は、関数の外の sum の値の影響を受けないのです。メモリ上には、関数内の sum と間数階の sum の2つが存在します。より詳しく言えば、関数が実行されている間だけ、関数内の sum がメモリ上に作られ、関数の実行が終われば、関数内の sum は消滅します。

変数の有効範囲を スコープ (scope)  と言います。関数内の変数のスコープは関数内に限定されるわけです。


5.3 circle()関数の拡張

以下のように、デフォルト値を設定して、第三引数と第四引数を追加します。
第三引数には、set_pixel() に渡すRGBカラー設定をデフォルト色黒 (=(0, 0, 0)) で追加します。
第四引数には、VRAMから画面への転送を行うかどうかを 1 か 0 あるいは True か False で設定し、デフォルトは 1 (転送する) とします。

 拡張 circle() の関数定義:
from casioplot import *
from math import *

#draw circle
def circle(xyr, color=(0, 0, 0), show=1): #ここを変更
 r*2406/383
 2*pi/p
 for i in range(p):
  px x+r*cos(i*a)
  if px<0 or px>383:
   continue
  py y+r
sin*(i*a)
  if py<0 or py>191:
   continue 
  set_pixel(int(px)int(py), color)
  if show: #これを追加
   show_screen()


5.4 色指定関数を追加

set_pixel() の色指定は、(r, g, b) というタプル型のデータで RGB値を使います。


5.4.1 RGBによる色指定
一般に RGB による色指定は、R = 0 ~ 255の整数、G = 0 ~ 255の整数、B = 0 ~ 255の整数 とそれぞれ 8bit、併せて 24 bit で色を決める方法で、この方法で指定する色を 24bit カラーと言います。

一方、fx-CG50 搭載の液晶は 24 bitカラーには対応しておらず、16 bit カラーで色が表現されます。
具体的には、R と B は 0 ~ 248 までの4の倍数 (それぞれ 4bit)、G が 0 ~255 までの整数 (8bit)、併せて 16 bit カラーになっています。fx-CG50 の液晶は、24bitカラーで指定してもエラーになりませんが、16bitカラーに変換され、24bitからの細かい色調の違いを表現できません。たとえは、白は、(255, 255, 255) と指定しても実際は (248, 255, 248) と同じになります。

但し、PCでは24bit カラーが一般的なので、分かり易さから 24 bitカラーを使って色指定しても良いと思います。繰り返しますが、実際は 16bit カラーに変換されて表示されることは、頭にいれておくと良いと思います。


5.4.2 タプル型
デフォルト引数の color=(0, 0, 0) は、変数 color をタプル (tuple) 型として初期化しています。タプル型はリスト型と似ている配列変数の一種です。リスト型は カギ括弧を使って [0, 0, 0] と定義しますが、タプル型はマル括弧を使います。リスト型は各要素を変更することが前提です。一方、タプル型は各要素を変更しないことが前提で、要素の変更を行おうとするとエラーになる、そのようなデータ型です。


5.4.3 色指定方法の拡張
fx-CG50 の Casio Basic では、RGB による色指定はできず、以下の7色設定に限られています。
 ・black
 ・blue
 ・red
 ・magenta
 ・green
 ・cyan
 ・yellow
(チョット見えずらいです)

そこで、上記の文字列での色指定も可能にしたいと思います。さらに、上の7色に加えて白の色指定 (whilte) も追加する必要があります。なぜなら、前回作ったスクリプトで、テキストを頻繁に書き換えて表示するためには、一旦背景と同じ white で上書きして一旦消去した後、新たな文字列を表示する必要があったことを思い出してください。

その上で、whilte を加えて8色について、0 ~ 7 までの整数でのカラーコードで色指定を可能にすると、さらに便利で使いやすくなると思うので、整数での色指定方法も可能にしようと思います。

 ・カラーコード=0:'white'
 ・カラーコード=1:'black'
 ・カラーコード=2:'blue'
 ・カラーコード=3:'red'
 ・カラーコード=4:'magenta'
 ・カラーコード=5:'green'
 ・カラーコード=6:'cyan'
 ・カラーコード=7:'yellow'


タプル型のRGB、文字列型、そして整数型のカラーコードの3通りを引数に指定すると、タプル型のRGB値を返す関数を作っておくと、circle() 以外にも、今後グラフィックス画面での描画関数を作る時、この3通りの色指定ができるようすると便利だと思います。


5.4.4 グラフィック画面での色指定関数 grp_color() 関数の作成 
これから作る関数の枠組みは以下のようになります。

 def grp_color(color=1):
  必要な処理
  return rgb


ここで、return ステートメントで返す rgb 変数はタプル型の rgb値とします。

この関数の引数は1つだけですが、3通りのデータ型が指定されるのが仕様なので、先ず最初に引数として渡される 変数 color のデータ型を判定する必要があります。判定した型に応じて、タプル型の rgb に変換し、それを返すようにすれば良いわけです。 

データ型の判定
データ型の判定を行う type() 関数が使えます。

Note: type()
オブジェクトを渡すとオブジェクトの型を返します。

そこで、grp_color() に渡される引数 color の型を調べて、タプル型、文字列型、整数型に応じて、それらをタプル型 (変数 c_rgb) に変換します。

def grp_color(color=1):
 if type(color) is int:
  c_egb = (必要な式1)
 elif type(color) is str:
  c_rgb = (必要な式2)
 elif type(color) is tuple:
  c_rgb = color

 else:
  c_rgb = (color[0], color[1], color[2])

 return
c_rgb



最初の if 文での処理
これは、整数のカラーコードを指定した時の処理です。カラーコードが代入されている color 変数について、0 から 7 までの8通りの場合分けを if 文で処理すれば良いですね。但し今回は、この処理をシンプルに記述するために、リストを使ってみます。詳しく言えば、タプル型の rgb 設定を要素に持つリストを作って、それを使います。このリストの要素は、インデックス 0 が 白、インデックス 1 が黒、・・・と、上で決めた色になるように、左かr網気へ rgb 指定を並べます。

rgb = [(255,255,255), (0,0,0), (0,0,255), (255,0,0), (255,0,255), (0,255,0), (0,255,255), (255,255,0)]

Note: リストの定義
要素を , で区切り、[ ] で囲むと、リストになります。要素を呼び出すには、0 から始まるインデックス(整数) で指定します。

Note: タプルの定義
要素を , で句切り、( ) で囲むと、タプルになります。要素を呼び出すには、0 から始まるインデックス(整数) で市営します。

繰り返しますが、ここで定義したリスト rgb は、3つの整数が要素になっているタプル型データで構成されています。このタプル型データは、rgb の色指定になっています。1つめの要素 rgb[0](255,255,255) つまり、白 (white) にしています。以下同様にして、インデックスに整数のカラーコードを指定すると、その色の rgb値(タプル型) になるように、要素を並べています。
 ・rgb[0] = (255,255,255) #white
 ・rgb[1] = (0,0,0) #black
 ・rgb[2] = (0,0,255) #blue
 ・rgb[3] = (255,0,0) #red
 ・rgb[4] = (255,0,255) #magenta
 ・rgb[5] = (0,255,0) #green
 ・rgb[6] = (0,255,255) #cyan
 ・rgb[7] = (255,255,0) #yellow


これを使った、最初の if 文での処理を具体化します。

def grp_color(color=1):
 rgb=[(255,255,255),(0,0,0),(0,0,255),(255,0,0),(255,0,255),(0,255,0),(0,255,255),(255,255,0)]

 if type(color) is int:
  c_egb = rgb[coor] #ここまで完成
 elif type(color) is str:
  c_rgb = (必要な式2)
 elif type(color) is tuple:
  c_rgb = color

 else:
  c_rgb = (color[0], color[1], color[2])
 
 return
c_rgb

このように、たった1行で記述できました。if文color の値に応じて8通りの場合分けを記述するよりも遙かにシンプルになりました。Python のシーケンス(いわゆる配列です)、ここではリストですが、定義もシンプルで使うのも簡単で、なかなか便利なものですね。


1つめの elif での処理
ここでは、引数が文字列型 (str型) の時の処理で、変数 color は文字列です。ここでは文字列から対応するタプル型の rgb 値を得る処理を書きます。

if 文で処理しても良いのですが、ここでもリストを使えば、格段に簡潔に記述できます。具体的には、以下のような文字列リストを作って利用します。

c_name = ['white', 'black', 'blue', 'red', 'magenta', 'green', 'cyan', 'yellow']

文字列リスト c_name の各要素が、色を指定する文字列になっています。文字列変数の color が、何番目の要素にあるのかが分かれば、それをインデックス番号として上と全く同様に rgb[インデックス番号] とすると、インデックスに対応するタプル型の rgb値が得られます。

文字列リスト c_name の要素のうち、どれかの要素を指定した時にその要素のインデックス番号が分かれば、そのインデックス番号を使って rgb[インデックス番号] として、目的の rgb値が得られますね!

ここでは、そのような目的で使える .index() 関数(あるいはメソッドとも言います) を使います。この関数はリスト型オブジェクトの帰属関数なので、リストオブジェクトとコンマ . で繋いで記述します。つまり、c_name.index(color) と記述します。.index() 関数は、引数に要素を指定すると、その要素のインデックス(整数) を返しますので、引数に文字列変数である color を指定しています。

繰り返しになりますが、color変数(文字列変数) に目的の色を示す文字列が入っているので、

c_name.index(color)

は、color で指定された色の文字列のインデックスを返します。

従って、rgbリストにこのインデックスを指定すると、その要素が目的のタプル型 rgb です。
c_rgb = rgb[インデックス]
は、上で使った方法ですね!

つまり、

c_rgb = rgb[c_name.index(color)]

と書けば、1行で目的の変換ができました!
リストを活用することで、if 文なしで、とても簡潔に記述できました!

ここまでのコードを具体化します。

 def grp_color(color=1):
 rgb=[(255,255,255),(0,0,0),(0,0,255),(255,0,0),(255,0,255),(0,255,0),(0,255,255),(255,255,0)]
 c_name=['white', 'black', 'blue', 'red', 'magenta', 'green', 'cyan', 'yellow']

 if type(color) is int:
  c_rgb = rgb[color]
 elif type(color) is str:
  c_rgb = rgb[c_name.index(color)]
 elif type(color) is tuple: #2つめの elif 節
  c_rgb =
color

 else: #else節
  c_rgb = (0, 0, 0)

 return
c_rgb


スクリプトを一気に作り、2つめの elif 節else 節の説明が後になりました。以下を確認してください。

2つめの elif での処理
これは、タプル型のrgb値の変数 color が渡されたときの処理なので、color をそのまま c_rgb に代入すれば良いですね!

最後の else での処理
color 変数が、int型、str型、tuple型のいずれでもないとき、else 節でデフォルトの黒、(0,0,0)c_rgb に指定します。これはエラーでスクリプトの実行が強制中断されないための安全策です。例えば、整数でなく浮動小数点が color に渡される時は、例えば今作っている grp_color() の戻り値がそのまま set_pixel() に渡されるとエラーになります。そこで、else 節では、想定外の値、例えば浮動小数点が color に入っている時は、デフォルトの黒にして、エラーの発生を抑制する作戦です。このエラー抑制のための処理は、無くても大きな問題ではないと思いますが、スクリプトの動作が強制終了されるよりも、止まらないことを優先させたいと思う管理人の好みを反映させました。

これで、基本機能の実装が終わりました。続いて想定される範囲でよく発生しそうなエラーを抑制するための処理を追加してゆきます。

color に整数のカラーコードを指定した時、0 ~ 7 までの整数を前提にしていますが、これ以外の整数が指定されるとエラーになります。そこで、color が 0から7までの整数の場合に上の本来の処理を行い、そうでない場合は、黒を指定するようにします。これは、上記のエラー抑制処理と同じ理由 (管理人の好み) に基づいています。

 c_rgb = rgb[color] 

を以下のように書き換えます。

 if 0<=color<=7:
  c_rgb = rgb[color]
 else:
  c_rgb = (0,0,0)



Note: Python の比較演算子
color>=0 and color<=7 としても良いですが、0<=color<=7 とできるのは、Python の便利なところです。

color に文字列の色指定をする時は、あらかじめ決めている文字列以外が渡されるとエラーになります。そこで、予め決められた文字列の時は上の本来の処理を行い、そうでない場合は、黒を指定するようにします。

 c_rgb = rgb[c_name.index(color)]

を以下のように書き換えます。

 if color in c_name:
  c_rgb = rgb[c_name.index(color)]
 else:
  c_rgb = (0,0,0)



Note:帰属検査の in
ここでは、帰属(所属)検査のステートメント in を使っています。c_name は文字列リストなので、このリストに文字列 color が含まれているかどうかが in で検査できます。このあたりは、python の分かり易さ、使いやすさの良い例だと思います。


以上で、grp_color() 関数を完成とします。コメントも追加して、完成したスクリプトを示します。


 def grp_color(color=1):
 """Convert colorparameter to rgb in tuple

 version 1.0

 parameters:
 --------------
 color: code, name,    rgb
     0   'white'  (255,255,255)
     1   'black'   (0,0,0)
     2   'blue'     (0,0,255)
     3   'red'    (255,0,0)
     4   'magenta' (255,0,255)
     5   'green'  (0,255,0)
     6   'cyan'    (0,255,255)
     7   'yellow'   (255,255,0)
  default:1 'black'   (0,0,0)

 Returns:
 ---------
  tuple:(rgb)
 """
 #set rgb from parameter (color)
 rgb=[(255,255,255),(0,0,0),(0,0,255),(255,0,0),(255,0,255),(0,255,0),(0,255,255),(255,255,0)]
 c_name=['white', 'black', 'blue', 'red', 'magenta', 'green', 'cyan', 'yellow']

 if type(color) is int:
  if 0<=color<=7:
   c_rgb = rgb[color]
  else:
   c_rgb = (0,0,0)
 elif type(color) is str:
  if color in c_name:
   c_rgb = rgb[c_name.index(color)]
  else:
   c_rgb = (0,0,0) 
 elif type(color) is tuple:
  c_rgb =
color

 else:
  c_rgb = (0, 0, 0)

 return
c_rgb


5.5 circle() 関数拡張の書き換え

これまで作成した grp_color() 関数を使って、circle() 関数の拡張を書き換えます。

 書き換えた拡張 circle() の関数定義:
def circle(xyr, color=1, show=1): #ここを変更
 rgb = grp_color(color) #これを追加
 r*2406/383
 2*pi/p
 for i in range(p):
  px x+r*cos(i*a)
  if px<0 or px>383:
   continue
  py y+r
sin*(i*a)
  if py<0 or py>191:
   continue 
  set_pixel(int(px)int(py), rgb) #ここを変更
  if show: #これを追加
   show_screen()

circle(x, y, r) とすると、色はデフォルトの黒、VRAMから画面転送(デフォルト設定)を行います。
色指定をしたい場合は、第三引数に3通りの方法、1) カラーコード、2) 色の文字列、3) タプル型のrgb指定、で色を指定可能。
VRAMから画面転送を抑制したいときは、第四引数に 0 あるいは show=0 (第三引数を指定しない場合) とします。


5.6 モンテカルロ法(2) - monteca2.py

最後に、grp_color() と 拡張 circle() を使って、モンテカルロ法(1) のスクリプトをカラー化してみます。

円を赤で、点を青で描画するように変更しました。以下は変更した部分です;
circle(dx, dy, r, 'red') #red
set_pixel(int(dx+r*x), int(dy+r*y), grp_color('blue')) #blue
draw_string(36, 0, str(prev_outs), grp_color(0)) #white
draw_string(36, 16, str(prev_pai), grp_color(0)) #white
draw_string(0, 176, 'AC:Quit', grp_color(0))
#white


このように、タプル型のRGBで色指定するよりも、カラーコードや文字列で指定する方が、コーデイングが楽で分かりやすくなると思います。これを実現したくて、今回 grp_color() を作り、circle() を拡張しました。 

詳しくは、monteca2.py をダウンロードして確認してください。

monteca2 




目 次

前の記事 - 4. Casio Python への移植

次の記事 - 6. グラフィックス出力関数の追加





応援クリックをお願いします。励みになるので...
にほんブログ村 IT技術ブログ 開発言語へ


 


keywords: fx-CG50Pythonプログラミング入門プログラミングプログラム関数電卓

リンク集 | ブログ内マップ


関連記事

テーマ : プログラム関数電卓
ジャンル : コンピュータ

コメントの投稿

非公開コメント

最新記事
検索フォーム
最新コメント
カテゴリ
C# (3)
Visitors
Online Counter
現在の閲覧者数:
プロフィール

やす (Krtyski)

Author:やす (Krtyski)
since Oct 30, 2013


プログラム電卓は、プログラムを作って、使ってナンボ!

実際に触って気づいたこと、自作プログラム、電卓プログラミングについて書いています。

なお管理人はカシオ計算機の関係者ではなく、Casio Basicが面白いと感じる1ユーザーです。


写真: 「4駆で泥んこ遊び@オックスフォード郊外」

リンク
月別アーカイブ
Sitemap

全ての記事を表示する

ブロとも申請フォーム

この人とブロともになる

QRコード
QR