エンジニアのサブルーチン

あまり注目されない組み込みのシステムエンジニアをやっています。エンジニア業界のこととか、勉強したこととかを不定期に更新していきます。

Python100本ノック 4問目

f:id:code_sugar:20190824122351p:plain

解答

num_select = (1, 5, 6, 7, 8, 9, 15, 16, 19)
letters = "Hi He Lied Because Boron Could Not Oxidize Fluorine. New Nations Might Also Sign Peace Security Clause. Arthur King Can."
result = {}

word = letters.split(' ')

for (num, gen) in enumerate(word,1):
  if num in num_select:
    result[gen[0:1]] = num
  else:
    result[gen[0:2]] = num

print(result)

学んだこと

辞書型配列

いわゆるハッシュのこと

辞書の新規作成
dic = {} #空の辞書作成
dic{"key1": "value1", "key2": "value2"} #キーバリュー型で直接的な作成
dic["key"] = "value" #変数的に作成する 

enumerate

for文でイテレーションするイテラブルオブジェクトの他にインデックス番号も同時にイテレートすることができる便利なもの

lists = ['test1','test2','test3','test4']

for (i, list) in enumerate(lists):
  print(i, list)

#(0, 'test1')
#(1, 'test2')
#(2, 'test3')
#(3, 'test4')

第2引数に開始番号を指定できる。

lists = ['test1','test2','test3','test4']

for (i, list) in enumerate(lists, 1):
  print(i, list)

#(1, 'test1')
#(2, 'test2')
#(3, 'test3')
#(4, 'test4')

Python100本ノック 3問目

f:id:code_sugar:20190823001856p:plain

split(' ')したのはいいものの ,や.が含まれてるから、これをどう処理したらいいかわからなかった。

解答

target = 'Now I need a drink, alcoholic of course, after the heavy lectures involving quantum mechanics.'
result = []

words = target.split(' ')
for word in words:
    result.append(len(word) - word.count(',') - word.count('.'))

print(result)


各メソッドの解説

append()

append()で配列に新しく要素を追加します

list = []
list.append('test1')  # ==>['test1']
list.append('test2') # ==>['test1', 'test2']

count()

指定した引数を探し出して数えてくれる。

...

ちょっと俺的にはスッキリしない解答です(もっとスマートな解答を求めていた)

Python100本ノック 2問目

1問目は0問目と同じ解法なので割愛。

f:id:code_sugar:20190822231344p:plain

解答

car1 = 'パトカー'
car2 = 'タクシー'
result = ''

for (x,y) in zip(car1, car2):
 result += x + y

print(result) # ==> 'パタトクカシーー'

for文

反復処理ではwhileかforがよく使われると思う。
pythonの反復処理は少々面白い。
一般的によく見るコードは下記のようなものかと。

 letters = ['list1' , 'list2', 'list3' , 'list4']
 num = 0
 while num < len(letters):
   print(letters[num])
   current += 1

# >>> list1,list2,list3,list4

けどpythonだともっと簡単に描ける

letters = ['list1', 'list2', 'list3', 'list4']
for letter in letters:
  print(letter)

# ==> list1,list2,list3,list4

たった三行でかけちゃう。 
これは各イテレーションごとにlettersの中の要素をletterという変数に格納し、それをprintで出力しているだけです。

zip()

この for文には複数のシーケンスをイテレートできるzip()という物がある。

car1 = 'パトカー'
car2 = 'タクシー'
result = ''
for (x,y) in zip(car1, car2): # list(zip(car1, car2)) ==>[('パ', 'タ'),('ト', 'ク'),('カ', 'シ'),('ー', 'ー')]
    result += x + y

print(result) # ==> 'パタトクカシーー'

car1,car2の要素がイテレーションごとにx,yに格納されるだけのお話でした。

Python100本ノック 0問目

DjangoだけやってもPythonを理解しているとは全くもって言えないので、
「言語処理100本ノック 2015」 というサイトを使ってpythonをしっかりと深掘りしていきたいと思います。

1日目 第1章--第0問

f:id:code_sugar:20190822205834p:plain

早速わからない(ゴミ)。調べて導き出した答えはこう。

letters = 'stressed'
letters[-1::-1]  # ==> 'desserts'

たった2行の処理がなんでわからないのか....
とにかく、自分なりの解釈をまとめる。

文字列の取得

pythonの文字列はシーケンスなので配列のように[値]で先頭から何番目の文字列でも自由に取得できる

letters = 'abcdef'
letters[0] = 'a'  # 1番目の文字列を取得
letters[1] = 'b' # 2番目の文字列を取得

#文字数以上の数値を入力してみる
letters[10000]  # ==> IndexError: string index out of range 

文字列の一部を取得

スライスという物を使えば簡単に部分的に文字列を取得したりできる。

letters[start:end:step]

[start:end:step]とはstart,end,stepにそれぞれ値を入れることで、
step文字列ごとにstartで指定した値からend-1 までのシーケンスを取得する

letters = 'abcdef'

letters[:] # ==> 'abcdef' 先頭から末尾まで取得
letters[2:] # ==> 'cdef' startオフセット(先頭から2番目)から末尾まで取得
letters[1:3] # ==> 'bc' startからend-1まで取得
letters[::3] # ==> 'ad'先頭から3文字置きに末尾まで
# 本問
letters[-1::-1] # ==> 'fedcba' 先頭から-1(末尾)から-1文字ごと(逆順で)最後まで

他にも色々文字列に関するメソッドあるけど、今回の問題と関係ないので割愛します

djangoでプロジェクトを立ち上げてからテンプレートで「HelloWorld」を出すまでの流れ

djangoを本格的に学び始めて2日ほどたった。入門書はだいたい読み終えたし、大まかに把握はした。よし、アプリを作ろう。

あれ?ここどうするんだっけ...

俺は基本のデータの流れすら、覚えられてなかった。まぁ、2日で完璧に覚えられるわけがない


ということで今回は個人用メモみたいなものになるけど、Pyhonの代表的WebフレームワークDjango」でプロジェクトファイルを作成してから

HelloWorldを出すまでの流れを出来るだけ詳しくかいていこうと思います!

...
とりあえず環境構築の過程は割愛します。出来上がったファイル構成はこう
f:id:code_sugar:20190818004822p:plain

フォルダの説明


urls.py
  Railsでいうところのルーティングファイル。 アクセス時のURLパターンを読み取り、パターン別にviews.pyの各クラス、もしくはメソッドに処理を流す

views.py
  Railsでいうところのコントローラ。urls.pyから流れて来たリクエストを処理する。

Templates
  htmlなどの保存場所。原則としてその更に下にファイルを置いてその中にhtmlフォルダを入れる。


今回のテーマの一番重要な3つのファイルとフォルダについて説明しました。

HelloWorldを表示する

TestAppファイル以下のurls.pyを以下のように編集する
f:id:code_sugar:20190818010850p:plain

include は指定したモジュールを呼び出す。今回はHelloWorldファイル内のurls.pyを呼び出している。
TestAppのurls.py内に全てのルーティングを設定できるが、アプリケーション別にurls.pyを作ってルーティングしないとまとまりが悪くなるので原則としてこの形をとる



そしてHelloWorldファイル内のurls.pyはこう
f:id:code_sugar:20190818013420p:plain

カレントディレクトリからviews.pyをimportしている。

ここでは、urlでhello/が呼び出されたらhelloメソッドを呼ぶようにルーティングをとっている。

そして処理はviews.pyに流れ
f:id:code_sugar:20190818013636p:plain

ここでrenderでTemplates内にある HelloWorldファイルの中にあるhello.htmlを呼び出してreturnしている

この一連の処理の流れを経て我々の元にHelloWorldが送られてくる
f:id:code_sugar:20190818013815p:plain

おはよう世界

...

注意するべきなのは、アプリ内でテンプレートを使用するときはsettingファイルをこう編集しないといけないf:id:code_sugar:20190818014012p:plain
これで使えるようになります。

...

個人的に気をつけなければいけないこと

とりあえず、from django.http import HttpResponse 書いとけ

テンプレートを使うなら from django.shortcuts import renderを書くのを忘れるな

というか、外部から何かを呼び出すならimportを忘れちゃだめ。何かを呼ぶ→importしないと って考えを常に持つこと。

...

以上です。頭の中を整理できました。 おやすみ世界

strftimeを使わず、I18nを使って時間表示をスマートにする

strftimeメソッドは日付データを編集し、文字列として変換できる便利なメソッドです。

f:id:code_sugar:20190815204703p:plain

この場合、DBに保存されてるcreated_at内の日付データを取得しそれをstrftimeメソッドの()内に表記されてる書式文字列(%Yなら年 %mなら月を表す)を用いて文字列として変換します。



これは確かに便利だけど、strftimeを何度も使用する場面が出てきた時、書式文字列を何度も書くのは面倒臭いし、見にくい。タイポも誘発しやすいと思う。strftimeでいい場面の方が圧倒的に多いのでは?



なのでI18nを使ってもっと見やすく簡潔してみる
f:id:code_sugar:20190815204713p:plain

config/locals内にあるja.ymlを編集。
I18nはキーとバリューからなるデータ構造となっている。


I18nはviewの中ではtまたはl(今回の場合はl)で呼び出せる。
f:id:code_sugar:20190815204748p:plain
第一引数に日付データ、第二引数にformat: 'キー'で第一引数の日付データが第二引数で指定したキーに対応したバリューに沿って文字列として変換される。


こうすることでスマートに表示できる(と個人的には思いました)

固定の値を扱う時便利なEnumについて解説

Enumとは?

Enum(列挙型)とは複数の定数を一つにまとめられる便利な型です。
Enumはモデルで定義します。
f:id:code_sugar:20190731165839p:plain
このように定数bad,nomal,goodはそれぞれ0,10,20という数値と紐づいている。(数値が飛び飛びなのは、新しく項目を追加する場合を考慮している。)

statusカラムはあらかじめinteger型、boolen型を指定して置かなければなりません。

それによってDB上ではint型,boolen型で保存されます。先ほど定義した数値がそれぞれ保存されますが、DBから取り出すとき、Enumで紐づけされた文字列が数値の代わりに取り出されます。

Enumを使うメリット

  • 数字として管理してるから静的オブジェクトとして扱えるので安全性が高い
  • 文字列が変わっても数値で管理しているので変更しやすい
  • 可読性が良い

デメリット

実際に使ってみる

あらかじめusersコントローラーのtestアクションでUserクラスのインスタンスをnewしています。
f:id:code_sugar:20190731170007p:plain
これによってenumで定義した文字列がセレクトボックスが表示される
f:id:code_sugar:20190731170657p:plain