「Read」タグの記事が11件件あります
全てのタグを見る人工無脳を作ってみる (1)入力文の末尾に文字列を追加
さて、最初は単純にユーザの入力文の末尾に予め定義されている文字列を付け足して応答するだけのものです。
ソースコード
package info.yukun.chatterbot;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class SimpleChatterBot {
private String botName = "chatterbot";
private String callStr = "なにかしゃべってよ(>_<)";
private String[] suffixResponses = {
"ってアレですね、わかります(^^)b",
"ですか?わかりません(>_<)",
"って何?日本語でおk('`)b"};
public void go() {
try {
BufferedReader stdReader = new BufferedReader(new InputStreamReader(System.in));
System.out.print("INPUT : ");
String response;
String input;
while ((input = stdReader.readLine()) != null) { // ユーザの入力待ち
if (input.equals("")) { // 入力が無かった
response = callStr;
} else {
response = decorateInput(input) + getSuffixResponse();
}
System.out.print(botName + ": " + response);
System.out.print("\nINPUT : ");
}
stdReader.close();
System.out.println("\nPROGRAM END");
} catch (Exception e) {
e.getStackTrace();
System.exit(-1); // プログラムを終了
}
}
private String getSuffixResponse() {
int rand = (int) (Math.random() * suffixResponses.length);
return suffixResponses[rand];
}
private String decorateInput(String input) {
return "「" + input + "」";
}
public static void main(String[] args) {
SimpleChatterBot bot = new SimpleChatterBot();
bot.go();
}
}
getSuffixResponse()メソッド内で使われているMath.random()は、
static double random() 0.0 以上で、1.0 より小さい正の符号の付いた double 値を返します。
ですので、「Math.random() * 配列の長さ」 は「0~配列の長さ-1」 を意味します。
実行結果の例
INPUT : こんにちは
chatterbot: 「こんにちは」って何?日本語でおk('`)b
INPUT : え、
chatterbot: 「え、」ですか?わかりません(>_<)
INPUT : いえ、聞き返しただけです。
chatterbot: 「いえ、聞き返しただけです。」って何?日本語でおk('`)b
INPUT :
chatterbot: なにかしゃべってよ(>_<)
INPUT : 最近どうですか?
chatterbot: 「最近どうですか?」ってアレですね、わかります(^^)b
INPUT :
PROGRAM END
なんだかー、それはかとなくばかにしていますねf^^; 最初はJavaで書いていきますが、実装する機能の種類やリリースする環境によっては恐らく途中でOOをサポートする他の言語に変更するかも。
Java: ユーザからの(標準)入力を取得 - System.inとInputStreamReaderクラス
コマンドプロンプトからキーボード(標準)入力を取得するプログラムです。 肝心の標準入力を取得する手続きはSystem.inフィールドですが、これはバイトストリームでの読み込みを行うメソッドしか持たないので、InputStreamReaderクラスでラップすることでバイトストリームを文字列に変換出来るメソッドに任せます(read()メソッド)。 しかし、InputStreamReader#read()メソッドは一文字毎にしか読み込めず非効率な面があるので、最後にBufferedReaderクラスでラップすることで入力文字をバッファに格納し一行まとめて読み込めるようにします。(readLine()メソッド)。 このように、高水準のコンポーネントにSystem.inのような低水準のコンポーネントを渡して、その中で低水準メソッドを制御する手法はTemplate Methodパターンに通じるものがあるかも。The Open-Closed Principleですね。
ソースコード
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class ReadLineSample {
public static void main(String[] args) {
try {
BufferedReader stdReader =
new BufferedReader(new InputStreamReader(System.in));
System.out.print("INPUT : ");
String line;
while ((line = stdReader.readLine()) != null) { // ユーザの一行入力を待つ
if (line.equals("")) line = "<空文字>";
System.out.print("OUTPUT: " + line);
System.out.print("\nINPUT : ");
}
stdReader.close();
System.out.println("\nPROGRAM END");
} catch (Exception e) {
e.getStackTrace();
System.exit(-1); // プログラムを終了
}
}
}
実行結果
文字列を入力した後Enterキーを押すと入力した文字がOUTPUTされます。
INPUT : Hello World!
OUTPUT: Hello World!
INPUT : こんにちは。
OUTPUT: こんにちは。
INPUT :
OUTPUT: <空文字>
INPUT :
PROGRAM END
プログラムを終了する際は、プロンプト上でCtrl+CかCtrl+Zを押してください。それでreadLine()の戻り値はnullとなりwhileループを抜けます。ここでの注意は、単に文字を何も入力せずEnterキーだけ打つと空文字を返すことです(≠null)。 対して、C言語でこういった処理の場合は環境に合わせた改行文字も読み込こんでいます。たぶん、JavaではInputStreamReaderのreadのどこかの段階でその辺は上手く処理されているのかな?気が向いた時に確認してみようかな。
Python: ファイル読み込み時の例外の扱い例 - try、except、else、finallyブロック
ファイルのパスや名前のミス、パーミッションの権限が無い等が原因でファイルを読み込めない場合がある。そのような場合、すなわち例外が発生した際にそこで処理を中断して、発生した例外に合わせた処理ブロックにジャンプする構文が、try:~except Error:~構文。 今回は、コマンドライン引数で英文テキストファイル名を指定し、スクリプト内でファイル内容を読み込み、単語数をカウントし出力するスクリプトを以って、オプションのelse、finallyブロックを含めた例外ブロックの扱いを確認する。 ただし、ここでの「単語」とは、簡単に考える為、1つの空白文字で区切られた文字列とする。
ソースコード
# -*- coding: UTF-8 -*-
import sys
script_name = sys.argv[0]
try:
arg = sys.argv[1]
f = open(arg, 'r')
except IndexError:
print 'Usage: %s TEXTFILE' % script_name
except IOError:
print '"%s" cannot be opened.' % arg
else:
print arg, 'contains', len(f.read().split(' ')), 'words.'
f.close()
finally:
print 'n"%s" process end.' % script_name
quit()
print 'Not reach this line.'
コードの説明
tryブロック
まず、例外を発生させる恐れのある行は、tryブロック内に書く。 ここで発生する可能性がある例外はコマンドライン引数が格納されているリストへのアクセス部分であるsys.argv[1]。[]演算子で存在しない要素を参照する例外。また、ファイルを開くopen(arg, 'r')も冒頭の理由で例外発生の可能性もある。
exceptブロック
exceptブロックは、tryブロックで例外が発生した場合にのみ実行されるブロックです。その為、例外が発生しない場合は実行されない。 発生する可能性のある例外のタイプ毎にexceptブロックを書けば、そのタイプ毎の例外への対処処理を書くことが出来る。
except TYPE_AError:
TYPE_AErrorが発生した際のとある処理...
except TYPE_BError:
TYPE_BErrorが発生した際のとある処理...
elseブロック (オプション)
elseブロックは全てのexceptブロックの後に書く(任意なので書かなくても構わない)。 elseブロックはtryブロックで例外が発生しなかった場合にのみ実行されるブロック。今回は、ファイルの読み込みとクローズに使用している。
finallyブロック (オプション)
finallyブロックはtryブロックで例外が発生するしないに関わらず実行されるブロック(任意なので書かなくても構わない)。
実行結果
読み込むテキストファイルを以下の_aLine.txt_とする。 aLine.txt
Unless I set the standard where I am in any level, I'll be puzzled about what I should do from now on.
コマンドラインで適切な引数を与えた場合
$ python excp01.py aLine.txt
aLine.txt contains 22 words.
"excp01.py" process end.
存在しないファイル名を引数を与えた場合
$ python excp01.py texfile.tex
"texfile.tex" cannot be opened.
"excp01.py" process end.
コマンドライン引数を与えなかった場合
$ python excp01.py
Usage: excp01.py TEXTFILE
"excp01.py" process end.
例外オブジェクト名をpython処理系に聞いてみる
どんなメソッドや関数、演算子が、どのような例外を投げるのか予測が付かない場合もある。そんな場合、一旦はスクリプトを実行してエラーを確認する。 SyntaxError: invalid syntax以外のエラーがある場合、例えば、
$ python excp01.py
Traceback (most recent call last):
File "excp01.py", line 5, in
arg = sys.argv[1]
IndexError: list index out of range
のような場合は、最終行の行頭のIndexErrorが例外名となる。
何でも例外任せにしていいの?
計算量が増える為、良くない。今プログラムのコマンドライン引数の確認を、 if len(sys.argv) != 2: ホニャララ とすると整数の比較ですむが、例外のキャッチに任せると、例外インスタンスを生成し送出という計算量の大きい処理が掛かる。ネットワーク接続やファイル読み書きなどのIOでは例外はイベント駆動で発生する為、例外制御が必須ですが、それ以外では使用しない。
ドキュメント
Rで統計: CSVファイルの読み込み - read.csv()メソッド
読み込むCSVファイルは2007年度のセリーグの打撃成績の順位です。
参考:2007年度 セントラル・リーグ 個人打撃成績(規定打席以上)
batting2007.csv
順位,打率,安打
1,0.346,193
2,0.343,204
3,0.318,172
4,0.313,177
5,0.31,175
6,0.308,155
7,0.302,122
8,0.302,118
9,0.3,120
10,0.3,139
プロンプト
> read.csv("batting2007.csv")
順位 打率 安打
1 1 0.346 193
2 2 0.343 204
3 3 0.318 172
4 4 0.313 177
5 5 0.310 175
6 6 0.308 155
7 7 0.302 122
8 8 0.302 118
9 9 0.300 120
10 10 0.300 139
> batting$安打
[1] 193 204 172 177 175 155 122 118 120 139
read.csv()メソッドでCSVファイルを読み込み、そのデータフレームをbatting変数に格納しています。
実行結果を見ると、ファイル1行目のフィールド(列)名が変数名を表し、2行目以降がテーブル本体を表していることが分かります。これによって、例えば安打の列を抽出したい場合は、batting$安打と指定すればOKです。
ただ、毎回々々「batting$安打」と指定するのは億劫ですので、以下のコマンドで簡略化します。
> attach(batting)
> 安打
[1] 193 204 172 177 175 155 122 118 120 139
>
attach()関数によってワークスペースにオブジェクトが保存され、データフレーム内の変数名のみでのアクセスが可能になります。
read.csv()メソッドのheader引数にFALSEを指定した場合
read.csv()メソッドはデフォルトでheader引数にTRUEが指定されていますが、以下のようにFALSE(必ず大文字)を指定することも出来ます。その場合の動作は以下のようになります。
> batting <- read.csv("batting2007.csv", header=FALSE)
> batting
V1 V2 V3
1 順位 打率 安打
2 1 0.346 193
3 2 0.343 204
4 3 0.318 172
5 4 0.313 177
6 5 0.31 175
7 6 0.308 155
8 7 0.302 122
9 8 0.302 118
10 9 0.3 120
11 10 0.3 139
> batting$V3
[1] 安打 193 204 172 177 175 155 122 118 120 139
Levels: 118 120 122 139 155 172 175 177 193 204 安打
>
ファイル1行目の列名がテーブル本体のデータセットに組み込まれていることが分かります。この場合の列へのアクセスは上の実行結果から、batting$V3と分かります。フィールド(列)名(一行目)を省略したCSVファイルを読み込みたい場合にはこのオプション引数を指定します。
Python: テキストファイルの行頭に行番号を追加
コマンドラインで指定されたテキストファイルの行頭に行番号を追加し、そのデータを新たなファイルに書き出すスクリプトです。
ソースコード
#!/usr/bin/python
# coding: UTF-8
import sys
argvs = sys.argv
argc = len(argvs)
if (argc != 3):
print 'Usage: $ python %s target_file making_file' % argvs[0]
quit()
f = open(argvs[1])
lines2 = f.readlines()
f.close()
nf = open(argvs[2], 'w')
i = 1
for line in lines2:
nf.write('%3d: %s' % (i, line))
i = i + 1
nf.close()
仮にこのソースコードをfile05a.pyというファイルで保存した場合、使用する際はプロンプトに以下のように打ち込みます。
実行結果
プロンプト
> python file05a.py file05a.py file05a-l.txt
この結果、生成されたファイルが下記になります。
file05a-l.txt
1: #!/usr/bin/python
2: # coding: UTF-8
3:
4: import sys
5:
6: argvs = sys.argv
7: argc = len(argvs)
8: if (argc != 3):
9: print 'Usage: $ python %s target_file making_file' % argvs[0]
10: quit()
11: f = open(argvs[1])
12: lines2 = f.readlines()
13: f.close()
14: nf = open(argvs[2], 'w')
15: i = 1
16: for line in lines2:
17: nf.write('%3d: %s' % (i, line))
18: i = i + 1
19: nf.close()
Rで統計: *.Rソースファイルの読み込みと実行 - source()関数
これまでの例は数行のコマンドでしたのでプロンプトに直接を打っていましたが、何十行というロジックをプロンプトに順々に打っていくのは非効率です。今回は、予め外部のテキストファイルにソースコードを書き、そのファイルをプロンプトから呼び出す手順を次の例で示します。
以下のソースコードを拡張子Rのテキストファイルで保存し、プロンプトから読み込んで実行してみましょう。
test.R
batting2007 <- c(193, 204, 172, 177, 175, 155, 122, 118, 120, 139)
print(batting2007)
このテキストファイルを作業ディレクトリにおきます。なお、作業ディレクトリの設定方法はこちらをご覧ください。→作業ディレクトリの設定と確認 - setwd()、getwd()関数
プロンプト
> source("test.R")
[1] 193 204 172 177 175 155 122 118 120 139
>
print()関数を用いて画面へ出力しています。
ここで、この状態のままプロンプトで以下のように入力すると、
> summary(batting2007)
Min. 1st Qu. Median Mean 3rd Qu. Max.
118.0 126.2 163.5 157.5 176.5 204.0
> mean(batting2007)
[1] 157.5
>
このように、読み込んだソースファイル中の変数が使えることが分かります。これは、関数宣言等を別ファイルに保存し、プロンプトから呼び出したい場合によく使います。
Python: 指定したパスのディレクトリ中のファイル一覧を出力
あるディレクトリから特定のファイルを検索したい場合、探索対象ディレクトリ内のファイルを全て取得する必要があります。今回は、引数にディレクトリを指すパスを指定することによって、そのディレクトリの内容を取得する関数を2つ示します。
ソースコード
# coding: Shift_JIS
import os # osモジュールのインポート
# os.listdir('パス')
# 指定したパス内の全てのファイルとディレクトリを要素とするリストを返す
files = os.listdir('C:\Python25\')
for file in files:
print file
実行結果の一例
DLLs
Doc
include
Lib
libs
LICENSE.txt
lxml-wininst.log
NEWS.txt
PIL-wininst.log
pysqlite-wininst.log
pysqlite2-doc
python.exe
pythonw.exe
README.txt
Removelxml.exe
RemovePIL.exe
Removepysqlite.exe
Scripts
tcl
Tools
w9xpopen.exe
ワイルドカードでリスティング対象を指定
globモジュールのglob()関数の引数内にワイルドカード「*」を含めることが出来ます。これによって、より手軽に目的のファイルを探索することが出来ます。
ソースコード
# coding: Shift_JIS
import glob
# パス内の全ての"指定パス+ファイル名"と"指定パス+ディレクトリ名"を要素とするリストを返す
files = glob.glob('C:\Python25\*.*') # ワイルドカードが使用可能
for file in files:
print file
os.listdir()と異なり、glob.glob()は取得したファイル文字列には先頭に探査ディレクトリ(引数)のパスが付いています。
実行結果の一例
C:Python25LICENSE.txt C:Python25lxml-wininst.log C:Python25NEWS.txt C:Python25PIL-wininst.log C:Python25pysqlite-wininst.log C:Python25python.exe C:Python25pythonw.exe C:Python25README.txt C:Python25Removelxml.exe C:Python25RemovePIL.exe C:Python25Removepysqlite.exe C:Python25w9xpopen.exe
リファレンス
Python: コマンドライン引数の取得 - sys.argv変数
コマンドラインで与える引数によってプログラムの挙動を変えたいという場面はよくあります。Python ではコマンドライン引数は sys モジュールの argv 属性に文字列を要素とするリストとして格納されています。そして、リストの先頭要素(sys.argv[0])はスクリプトファイル名となっています。
ソースコード
# coding: Shift_JIS
import sys # モジュール属性 argv を取得するため
argvs = sys.argv # コマンドライン引数を格納したリストの取得
argc = len(argvs) # 引数の個数
# デバッグプリント
print argvs
print argc
print
if (argc != 2): # 引数が足りない場合は、その旨を表示
print 'Usage: # python %s filename' % argvs[0]
quit() # プログラムの終了
print 'The content of %s ...n' % argvs[1]
f = open(argvs[1])
line = f.readline() # 1行読み込む(改行文字も含まれる)
while line:
print line
line = f.readline()
f.close
text.txt
It is meaningless only to think my long further aims idly.
It is important to set my aims but at the same time I should confirm my present condition.
Unless I set the standard where I am in any level, I'll be puzzled about what I should do from now on.
実行結果
引数を指定しない場合
$ python argv01.py
['argv01.py']
1
Usage: # python SCRIPTNAME.py filename
引数を指定した場合
$ python argv01.py text.txt
['argv01.py', 'text.txt']
2
The content of text.txt ...
It is meaningless only to think my long further aims idly.
It is important to set my aims but at the same time I should confirm my present condition.
Unless I set the standard where I am in any level, I'll be puzzled about what I should do from now on.
リファレンス
Python: CSVファイルの読み込み - csv.readerオブジェクト
ソースコード
#!/usr/bin/python
# coding: UTF-8
# CSVファイルの読み込み
import csv
filename = "table01.csv"
csvfile = open(filename)
print csvfile
for row in csv.reader(csvfile):
print row # 1行のリスト
for elem in row:
print elem, # 行の中の要素
print
csvfile.close()
print csvfile
CSVファイル (table01.csv) (番号,名前)
1,aki
2,hiro
3,norika
4,kaede
実行結果
<open file 'table01.csv', mode 'r' at 0x01BECCC8>
['1', 'aki']
1 aki
['2', 'hiro']
2 hiro
['3', 'norika']
3 norika
['4', 'kaede']
4 kaede
<closed file 'table01.csv', mode 'r' at 0x01BECCC8>

