default eye-catch image.

(今さら)Docker composeでWordPress環境を用意する

Hello World. docker-composeを使ってコンテナ間の繋がりを定義してみるデモに超速で入門する。 ゼロから書くと不要な時間を要するので、こちらを参考にさせていただいた。 写経する中でポイントを咀嚼していく。 ~/dockercompose_test というディレクトリを作成し、 その中で作業する。 docker-compose.yml 構成を記述する設定ファイル。ymlで書く。 ansibleでymlには慣れているので嬉しい。 version: \"3\" services: db: image: mysql:5.7 #container_name: \"mysql57\" volumes: - ./db/mysql:/var/lib/mysql restart: always environment: MYSQL_ROOT_PASSWORD: root_pass_fB3uWvTS MYSQL_DATABASE: wordpress_db MYSQL_USER: user MYSQL_PASSWORD: user_pass_Ck6uTvrQ wordpress: image: wordpress:latest #container_name: \"wordpress\" volumes: - ./wordpress/html:/var/www/html - ./php/php.ini:/usr/local/etc/php/conf.d/php.ini restart: always depends_on: - db ports: - 8080:80 environment: WORDPRESS_DB_HOST: db:3306 WORDPRESS_DB_NAME: wordpress_db WORDPRESS_DB_USER: user WORDPRESS_DB_PASSWORD: user_pass_Ck6uTvrQ ルートはservices. 名称の理解がフワフワだが、コンテナをサービスと読んでいることが多いくらいの認識. 配下に db と wordpress が存在する。おなじみの構成を定義している。 db dbの定義についてパラメタを追っていく. パラメタ 値 説明 image mysql57 pull してくるイメージを書く. mysql57という名前のイメージをpullする. volumes - ./db/mysql:/var/lib/mysql コンテナ内の/var/lib/mysql を ホストの./db/mysql にマウントする(で良いか?) restart always 再起動ポリシー(コンテナ終了時に再起動するための仕組み)を設定する.再起動ポリシーを設定しておくことで、Dockerデーモンの起動時やホストOSの起動時に自動的にコンテナを開始できる。 alwaysの他にいくつかあるか今はスキップ. environment MYSQL_ROOT_PASSWORD: root_pass_fB3uWvTSMYSQL_DATABASE: wordpress_dbMYSQL_USER: userMYSQL_PASSWORD: user_pass_Ck6uTvrQ コンテナの環境変数を定義する. 環境変数名はコンテナ依存. wordpress wordpressの定義についてパラメタを追っていく. パラメタ 値 定義 image wordpress:latest pull してくるイメージを書く. wordpressという名前のイメージをpullする. バージョンは最新. volumes ./wordpress/html:/var/www/html./php/php.ini:/usr/local/etc/php/conf.d/php.ini コンテナ内のディレクトリをホストのディレクトリにマウントする.マウント先を定義する. restart always 再起動ポリシーをalwaysに設定.内容はdbと同じ. depends_on - db サービスの依存関係を定義する.要は起動する順番を定義する. wordpressのdepends_onにdbを設定することで,wordpressよりも先にdbを起動できる.dbの起動が完了するまで待ってくれるという意味ではない! Control startup and shutdown order in Compose. ports 8080:80 コンテナの80番をホストの8080にマップする. http://localhost:8080 とかするとコンテナの80番が開く. environment WORDPRESS_DB_HOST: db:3306WORDPRESS_DB_NAME: wordpress_dbWORDPRESS_DB_USER: userWORDPRESS_DB_PASSWORD: user_pass_Ck6uTvrQ wordpressコンテナの環境変数を設定する.環境変数はコンテナ依存. docker compose up 以下で定義したdocker-compose.ymlに基づいて構築が始まる. -dはDetachedMode. これによりバックグラウンドで実行される. $ docker-compose up -d ホストで http://localhost:8080 を開くと以下の通り. 永続化の確認 言語を設定しwordpressのインストールを完了させる. db(MySQL)に加えられた変更はホストにマウントされたファイルに反映される. 以下により環境を停止した後, 再度upしたとしても, ホストにマウントされたファイルへの変更が反映され, インストール済みの状態で立ち上がる. $ docker-compose down $ docker-compose up -d まとめ docker-compose を使った WordPress環境構築のデモに超速で入門した. 一緒にコンテナを永続化するデモにも入門した.

default eye-catch image.

(今さら)DockerでWordPress環境を用意する

最小の手数でHello world. とりあえず最小の手数でwordpressを起動してみる。 イメージのダウンロード docker pullでMySQLとWordPressのイメージをダウンロードする。 イメージはサービス単位。 \"MySQL\"を実現するためのOSとミドルウェア。 \"WordPress\"を実現するためのOSとミドルウェア。例えばWebサーバも含んでいる。 まずはMySQL。 $ docker pull mysql:5.7.21 5.7.21: Pulling from library/mysql 2a72cbf407d6: Pull complete 38680a9b47a8: Pull complete 4c732aa0eb1b: Pull complete c5317a34eddd: Pull complete f92be680366c: Pull complete e8ecd8bec5ab: Pull complete 2a650284a6a8: Pull complete 5b5108d08c6d: Pull complete beaff1261757: Pull complete c1a55c6375b5: Pull complete 8181cde51c65: Pull complete Digest: sha256:691c55aabb3c4e3b89b953dd2f022f7ea845e5443954767d321d5f5fa394e28c Status: Downloaded newer image for mysql:5.7.21 docker.io/library/mysql:5.7.21 次にWordPress。何も指定しないと最新が落ちる様子。 $ docker pull wordpress Using default tag: latest latest: Pulling from library/wordpress bb79b6b2107f: Pull complete 80f7a64e4b25: Pull complete da391f3e81f0: Pull complete 8199ae3052e1: Pull complete 284fd0f314b2: Pull complete f38db365cd8a: Pull complete 1416a501db13: Pull complete be0026dad8d5: Pull complete 7bf43186e63e: Pull complete c0d672d8319a: Pull complete 645db540ba24: Pull complete 6f355b8da727: Pull complete aa00daebd81c: Pull complete 98996914108d: Pull complete 69e3e95397b4: Pull complete 5698325d4d72: Pull complete b604b3777675: Pull complete 57c814ef71bc: Pull complete ed1877bc3d14: Pull complete 673ead1d3971: Pull complete Digest: sha256:46fc3c784d5c4fdaa46977debb83261d29e932289a68739f1e34be6b27e04f87 Status: Downloaded newer image for wordpress:latest docker.io/library/wordpress:latest MySQLコンテナを起動 コンテナ(イメージ)を起動する。 $ docker run --name test-mysql -e MYSQL_ROOT_PASSWORD=test-pw -d mysql 013a2eb6b5b1c0b0f61e85cace6540ec036be80c9f85e8c9b5ed3e114a4cc8e8 パラメタは以下の通り。 Option Value 説明 --name test-mysql コンテナに名前を付ける。この例であれば test-mysql -e MYSQL_ROOT_PASSWORD=test-pw コンテナの環境変数を設定する。MYSQL_ROOT_PASSWORDという環境変数としてtest-pwを設定 -d - DetachedMode(Background)を指定する。指定がない場合Foregroud. WordPressコンテナを起動 WordPressコンテナを起動する。 $ docker run --name test-wordpress --link test-mysql:mysql -d -p 8080:80 wordpress a1301075d3667de7eddd9edc0c46edaeb4346a5c46ef444538c9cf9987f31471 パラメタは以下の通り。 Option Value 説明 --link test-mysql:mysql コンテナを連携させる。書式は --link [コンテナ名]:[エイリアス]。test-mysqlがコンテナ名(前述)で、mysqlがそのエイリアス。 -p 8080:80 HostとGuestのポートマッピング。Hostの8080をGuestの80にマッピングする。 Hostの8080にWordPressコンテナ内の80がマップされた。 http://localhost:8080/ でWordPressの言語選択画面が表示される。 非同期で起動したコンテナにアタッチ docker execで非同期に起動したWordPressコンテナ内のディレクトリにアクセスできる。 この例だと/var/www/html。 ゴニョゴニョいじると変更が反映される。 $ docker exec -it test-wordpress /bin/bash root@a1301075d366:/var/www/html# もちろん、コンテナを落とすと変更は失われる。 まとめ DockerでWordPressを動かすデモに超速で入門した。

default eye-catch image.

Dart文法 型と関数

型 基本型 全ての変数はオブジェクト。用意されている型は以下の通り。 数値型は int と double。 int IS num, double IS num となる num型がある。 論理型は bool 文字列型は String リストは List<T> 連想配列は Map<K, V> Runes,Symbolもあり Gneric型とdynamic Generic型がある。 List list = [1, 2, 3]; List list2 = [\'a\', 100, 3.14]; int, double など, どの型を使うか想定はあるが Dart言語で表現できない場合に dynami型を使う。 何型となるか想定がない場合, 全ての型の基底型である Objectを使う。 型推論 var で宣言して, 式の評価時に型を決める。 以下, x はforEachで初めて int であることが決まる。 var hoge = \"hogehoge\"; [1, 2, 3].forEach((x) => print(x*2)); 変数 Non Null By Default (NNBD) NNBDがOFFの場合、変数のデフォルト値は Null。 変数に Null を代入できるし, 変数は Nullになる可能性がある。 NNBDがONの場合、あえて指定しなければ Nullにすることはできない。 int x = Null; //コンパイルエラー int? x = Null; //OK FlutterでNNBDを有効にするには、 プロジェクトディレクトリの下にある analysis_options.yaml を書き換える。 analyzer: enable-experiment: - non-nullable finalとconst finalを付けると変数宣言時以外で値が書き換わらないことを保証できる。 変数が指しているメモリが書き換わらないことは保証していないので、 例えば以下のようにfinalなListの要素を書き換えることはできる。 final List l = [1,2,3]; l[1] = 10; //OK constを付けると値がコンパイル時に確定していることを表せる。 finalに加えて変数が指しているメモリが書き換わらないことも保証する。 const List l = [1,2,3]; l[1] = 10; //ng 可視性識別子 Dartには可視性識別子はない。プレフィックスとして _ を書くと可視性が下がる. 関数 基本形とシンタックスシュガー 関数の書き方。 戻り値の型 functionName(引数の型 引数) { return 戻り値; } 戻りが式の場合、まとめて書ける。 戻り値の型 functionName(引数の型 引数) => 式; void main() { print(getReverseValue(true).toString()); print(getReverseValue2(true).toString()); } bool getReverseValue(bool x) { return !x; } bool getReverseValue2(bool x) => !x; 名前付きパラメータ 引数に名前を付けて、呼ぶときに名前毎に値を渡せる。 名前付きパラメータは任意となる。 戻り値の型 functionName({引数の型 引数1, 引数の型 引数2}) { return 戻り値; } functionName(引数1: hoge, 引数2: fuga); void main() { print(myFunction(param1: 100, param2: \"hoge\")); print(myFunction(param1: 500)); // param2は任意だが myFunction内で参照してエラー } String myFunction({int param1, String param2}) => param1.toString() + param2;

default eye-catch image.

SNS Count Cache… WP_DEBUG=TRUEでinfoをerrorに吐くのは仕様です

あまりこういうことは書かないのだけれども、あんまりだったので記事にしておく。 FacebookやTwitterのシェア数、フォロー数などをバックグラウンドで取得するWordPressプラグイン \"SNS Count Cache\"。 なんか大量にエラーログを吐くので調べてみたら、 WP_DEBUGが立っているとinfoレベルのログをerror_log()で吐く仕様...。 開発環境でエラーログ確認しないのだろうか...。 class SCC_Logger { /** * Class constarctor * Hook onto all of the actions and filters needed by the plugin. */ protected function __construct() { self::log( \'[\' . __METHOD__ . \'] (line=\' . __LINE__ . \')\' ); } /** * Output log message according to WP_DEBUG setting * * @param string $message Message. * @return void */ public static function log( $message ) { if ( WP_DEBUG === true ) { if ( is_array( $message ) || is_object( $message ) ) { error_log( print_r( $message, true ) ); } else { error_log( $message ); } } } } log()というメソッド名でerror_log()を呼ぶというのは想像の斜め上で、 デバッグ初手のアイデアとして浮かばなかった。 /** * Class constarctor * Hook onto all of the actions and filters needed by the plugin. */ private function __construct() { SCC_Logger::log( \'[\' . __METHOD__ . \'] (line=\' . __LINE__ . \')\' ); load_plugin_textdomain( self::DOMAIN, false, basename( dirname( __FILE__ ) ) . \'/languages\' ); add_action( \'init\', array( $this, \'initialize\' ) ); register_activation_hook( __FILE__, array( $this, \'activate_plugin\' ) ); register_deactivation_hook( __FILE__, array( $this, \'deactivate_plugin\' ) ); add_action( \'admin_menu\', array( $this, \'register_admin_menu\' ) ); add_action( \'admin_print_styles\', array( $this, \'register_admin_styles\' ) ); add_action( \'admin_enqueue_scripts\', array( $this, \'register_admin_scripts\' ) ); // add_action( \'admin_notices\', array( $this, \'notice_page\' ) ); add_action( \'wp_ajax_\' . $this->ajax_action, array( $this, \'get_cache_info\' ) ); add_action( \'wp_dashboard_setup\', array( $this, \'add_wp_dashboard_widget\' ) ); add_action( \'deleted_post\' , array( $this, \'clear_cache_deleted_post\' ) ); add_filter( \'plugin_action_links_\' . plugin_basename( __FILE__ ), array( $this, \'add_plugin_action_links\' ), 10, 4 ); }

default eye-catch image.

Pythonデータ構造2

引き続きPythonデータ構造。 入れ子のリスト内包 入れ子のリスト内包を説明するために転置行列が使われていてわかりやすい。 このあたりがデータ処理用言語である所以な気がする。 matrix = [ [1,2,3,4], [5,6,7,8], [9,10,11,12] ] # 全行を出力 for i in range(4): for x in matrix: print(x) [1, 2, 3, 4] [5, 6, 7, 8] [9, 10, 11, 12] # 全行のi列目をリスト化 for i in range(4): v = [row[i] for row in matrix] print(v) [1, 5, 9] [2, 6, 10] [3, 7, 11] [4, 8, 12] # 同じことをワンライナーで v = [[row[i] for row in matrix] for i in range(4)] print(v) [1, 5, 9] [2, 6, 10] [3, 7, 11] [4, 8, 12] リストの要素削除 del文で要素を削除する。 a = [1,2,3,4,5] del a[3] print(a) [1, 2, 3, 5] del a[:] print(a) [] タプル 似て非なるデータ構造リストとタプル。リストは変更可能。タプルは変更不能。 タプルの要素として変更可能な変数を含めることはできる。 作り方が特殊。要素をカンマ区切りで並べるとタプルができる。 要素が1個の場合は、他の変数と区別が付かないので末尾にカンマを配置する。 要素が0個の場合は、()とする。 empty = () print(empty) () tupple = 100,200,300 print(tupple) (100, 200, 300) onetupple = 100, print(onetupple) (100,) 集合 データ分析用言語なのでこういうのは豊富。順序無し、重複無しのデータを格納する。 重複データを加えるときに重複が除去される。 hoge = {\'hoge1\',\'hoge2\',\'hoge3\',\'hoge4\'} print(hoge) set([\'hoge4\', \'hoge1\', \'hoge2\', \'hoge3\']) fuga = {\'fuga1\',\'fuga1\',\'fuga1\'} print(fuga) set([\'fuga1\']) リスト内包と同じ書き方で集合内包を記述できる。 v = {x for x in \'abcdefg\' if x not in \'abc\'} set([\'e\', \'d\', \'g\', \'f\']) ディクショナリ 連想配列。key-valueを格納する。 初期化の方法が複数あるので流してみる。 dic = dict([(\'hoge\',100),(\'fuga\',500),(\'hogehog\',1000),(\'fugafuga\',2000)]) print(dic) {\'fugafuga\': 2000, \'fuga\': 500, \'hogehog\': 1000, \'hoge\': 100} dic2 = dict(hoge=100, fuga=500, hogehgoe=1000, fugafuga=2000) print(dic2) {\'fugafuga\': 2000, \'fuga\': 500, \'hogehgoe\': 1000, \'hoge\': 100} ループ内でディクショナリのKeyValueを一度に取る方法を試してみる。 for k,v in dic.items(): print(k,v) (\'fuga\', 500) (\'hogehog\', 1000) (\'hoge\', 100) ちなみに、普通のリストは先頭から0,1,2,.... のように順序数が振られているはずで、 それを取得するにはenumerate()関数を使う。ループ外で変数を確保してループ内でインクリメントしたりしない。 l = [\'hoge\',\'fuga\',\'hogehoge\',\'fugafuga\'] (0, \'hoge\') (1, \'fuga\') (2, \'hogehoge\') (3, \'fugafuga\') 2つ以上のシーケンスにループをかけるとき普通はn重ループを書くと思うけれども、 Pythonはzip()関数とアンパッキングを使って1行で書くことができる。 これは良くみるし、Pythonのキモである気がする。 qq = [\'aaa1\', \'bbb1\',\'ccc1\',\'ddd1\'] rr = [100, 200, 300, 400] for q, r in zip(qq,rr): print(\'The value of qq is {0}. The value of rr is {1}\'.format(q,r)) The value of qq is aaa1. The value of rr is 100 The value of qq is bbb1. The value of rr is 200 The value of qq is ccc1. The value of rr is 300 The value of qq is ddd1. The value of rr is 400 逆順,ソート後ループ 正順のシーケンスにreversed()関数をかますと非破壊で逆順ソートできる。 それをループに使うと逆順ループができる。 sorted()関数をかますと非破壊でシーケンスをソートできる。 それをループに使うとソート後ループができる。 n = [1,2,3,4,5,6] for i in reversed(n): print(i) 6 5 4 3 2 1 r = [\'alpha\',\'beta\',\'gamma\',\'omega\',\'epsilon\'] for i in sorted(r): print(i) alpha beta epsilon gamma omega 演算子の優先順位 比較演算子は全て同じ優先順位。以下は左から順に比較が行われる。 まずa<bの比較が行われ、次にb==cの比較が行われる。a<bかつb==cであれば以下は真。 a < b == c 不思議な感じだけれども、これにより以下の比較がワンライナーでできる。 a > 1 and a <3 1 < a < 3 ブール演算子は比較演算子よりも優先順位が低い。 and,orの優先順位は同じ。notはand,orより高い。以下は同じ。 A and not B or C (A and (not B)) or C ブール演算は左から順番に評価され、途中で結論が確定したときに評価は中断される。 Cと異なり、式の途中で代入することはできない。つまり以下みたいなことはできない。 if a=10<20: シーケンスの比較 同じシーケンス型の変数を比較できる。辞書順で要素を比較していき全てが同じであれば真を返す。 両者が異なっていれば、異なっていた箇所の要素の辞書順の大小を返す。 いずれかが片方のサブセットである場合、短い方が小、長い方が大となる。

default eye-catch image.

Pythonデータ構造

リスト 覚えるものでもないのだけれども一度は通しておきたいリストのメソッド。 大方の言語と違って、基本的に破壊的メソッドだらけ。 append()で末尾に追加。 v = [] v.append(10) v[len(v):] = [30] print(v) [10 20] リストを伸長。 r = [20] v.extend(r) print(v) [10 20 30] リストに挿入。 v.insert(0,100) print(v) [100, 10, 30, 20] 要素の削除。 v.remove(10) print(v) [100, 30, 20] 要素のインデックス。indexOf(...)みたいな。 要素が無いと-1を返しそうだけれどもエラー。 idx = v.index(20) print(idx) idx2 = v.index(1000) print(idx2) ValueError: 1000 is not in list 含まれる要素xの個数を返す不思議なメソッド。 cnt = v.count(20) print(cnt) 要素を逆順にする。コピーしたものを逆順にするのではなくそのものを逆順にする。 v.reverse() [20, 30, 100] コピーする。 vv = v.copy() vv[0] = \'hoge\' print(v) print(vv) [20, 30, 100] [\'hoge\', 30, 100] リスト内包 例えば0から9までの値の2乗のリストを作成するコードは以下。 squares = [] for x in range(10): squares.append(x**2) [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] Pythonっぽくワンライナーで書くとこうなる。 map関数は高階関数。第1引数として関数、第2引数としてシーケンスを取る。 lambdaは関数のSyntaxSugarなので第1引数はlambdaも渡せる。 渡したシーケンスの全要素についてlambda式を実行した結果を返す。 range(10)は0から9まで。lambda x:x**2は引数を2乗する。 なのでmap(lambda x: x**2, range(10))は、0 1,4,9,...を返す。 それをlist()でリスト化する。 squares = list(map(lambda x: x**2, range(10))) print(squares) [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] Pythonでは、これが言語仕様で出来るようになっている。リスト内包。 []の中の最初は式。式に続けてfor式,if式を書ける。 squares2 = [x**2 for x in range(10)] print(squares2) [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] より複雑な式,for式をリスト内包にしてみる。以下は等価。 cs = [] for x in [1,2,3]: for y in [3,1,4]: if x != y: cs.append((x,y)) print(cs) [(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)] cs2 = [(x,y) for x in [1,2,3] for y in [3,1,4] if x != y] print(cs2) [(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)] 色々な書き方が出来る。戻り値をタプルにしたい場合は()で囲う必要がある。 vec = [-4, -2, 0 ,2, 4] cs3 = [x*2 for x in vec] print(cs3) [-8, -4, 0, 4, 8] cs4 = [x for x in vec if x >= 0] print(cs4) [0, 2, 4] cs5 = [(x, x**2) for x in range(10)] print(cs5) [(0, 0), (1, 1), (2, 4), (3, 9), (4, 16), (5, 25), (6, 36), (7, 49), (8, 64), (9, 81)] 以下面白い。リスト内包には入れ子の関数も含められる。 from math import pi cs6 = [str(round(pi, i)) for i in range(1,6)] print(cs6)

default eye-catch image.

Python制御構造2

任意引数 大方の言語と同じように任意引数を定義できる。任意引数の位置に渡した引数はタプルに変換される。 複数の変数を1つのタプルに変換する操作を、詰める(pack)と言ったりする。 もちろん任意引数の後はキーワード引数しか置けない。 def concat(*args,sep=\"/\"): return sep.join(args) val=concat(\'hoge\',\'fuga\',\'hogehoge\',\'fugafuga\') print(val) hoge/fuga/hogehoge/fugafuga unpack 逆に1つのタプルなりリストを複数の変数にバラすことをunpackと言ったりする。 hoge = [1,2,3] x,y,z = hoge print(x) print(y) print(z) 1 2 3 lambda 大方の言語と同じように無名関数を書ける。lambdaは1行しか書けない。 中では関数になっている。関数が関数外の変数を参照できるのと同様に lambdaからlambda外の変数を参照できる。 def make_incrementor(n): return lambda x:x+n f = make_incrementor(42) v =f(0) print(v) 42 r =f(10) print(r) 52 関数アノテーション 関数の引数、戻り値に付加情報を付けることができる。 PHPのTypeHintingみたいに、引数の型,戻り値の型を書ける。 型として実在しないクラスを指定するとエラーになる。 def f(hoge: str, fuga: str = \'fuga\') -> str: print(\"Annotations:\", f.__annotations__) print(\"Arguments:\", hoge, fuga) return hoge + \' and \' + fuga f(\'1\',\'2\') Annotations: {\'hoge\': , \'fuga\': , \'return\': } Arguments: 1 2 コーディングスタイル Pythonのコーディングスタイル。なんだかその理由がどうでも良い感じ。 やるのであればRubyのように外れたらエラーにするべきだし。 インデントはスペース4個。タブは使わない。 79文字以下で折り返す。 関数、クラス、関数内の大きめのブロックを分離するために空白行を使用 コメントは文末ではなく行として独立すべき docstringを使う 演算子の周囲やカンマの後ろはスペースをいれる。 括弧のすぐ内側にはスペースをいれない。 関数名、メソッドはlower_case_with_underscores UTF-8を使う。

default eye-catch image.

python制御構造1

個人的には、言語に入門する際にはオンラインより書籍が適切と考えている。 そして最初の一冊はなるべく薄いものを選ぶべきと考えている。 読んだ後、あえて文章として書き出すと良さそう。行間なりツボを自分の言葉でおまとめ。 あそこにこう書いてあった..というように思い出せると良いかなと。 まずは制御構造。 if ... elif ... else ブロックの開始はコロン。ブロックはインデントで表現。 else ifは繋げて書く。elif,elseはオプション。 x = 20 if x < 0: print("負の値") elif x == 0: print("ゼロ") elif x == 1: print("いち") else: print("その他") for 初期値、終了値、増分を書くCスタイルと違う。シーケンスに対してforeachをかけるスタイルのみ。 ループにかけたからといってシーケンスがコピーされることはなく変更することができる。 当然不安定なのでシーケンスをコピーしてループに使うべき、。 words = [1,2,3,4,5] for x in words: print(x) # for x in words[:] words.insert(0,x) シーケンスを最後まで読み終わった後に実行するブロックを定義できる。 forと同じインデント位置にelseを書く。 words = [1,2,3,4,5] for x in words: print(x) else: print(\"finish\") 1 2 3 4 5 finish range ループはシーケンスを処理するのみなので、シーケンスが無い場合は作る必要がある。 nからn-1ならrange(n)。初期値、終了値、ステップはrange(初期値,終了値,ステップ)。 range(n)はシーケンスを作るのではなく反復可能体を返す。つまり、range()の応答時には シーケンスはメモリ確保されておらず評価時に初めてメモリ確保される。ref.C++ iterator。 for x in range(10): print(x**2) 0 1 4 9 16 25 36 49 64 81 for x in (range(0,10,3)) print(x) 0 3 6 9 シーケンスを最初から最後までなめるのは以下。 ary = [\"hoge1\",\"hoge2\",\"hoge3\"] for x in range(len(ary)): print(ary[x]) hoge1 hoge2 hoge3 break,continue forループ,whileループを抜ける構文。 breakでforループを抜けた場合、for,whileに対応するelse:ブロックは評価されない。 words = [1,2,3,4,5] for x in words: print(x) if x==3: break else: print(\"finish\") 1 2 3 pass, ... pass,または...と書くと何もしない行を書くことができる。 コードに対称性が無くなったときにあえて書いておきたくなりそう。 これは悪くないかも.. words = [1,2,3,4,5] for x in words: print(x) if x==3: ... # don\'t forget elif x==4: pass # don\'t forget else: print(\"finish\") 1 2 3 4 5 finish 関数 関数の書き方。大方の言語のようにドキュメンテーションのやり方がある。 何故か関数の中に書く。docstringという。不思議。 後で自動集計してくれる。他のフォーマットを知っておきたい。 形式言語処理っぽい書き方だと、defの実行により新しいシンボル表が作られる。 関数内のあらゆる代入は新しいシンボル表に書かれる。(ローカルスコープ)。 関数内ではこのシンボル表しか参照することができず、implicitにグローバル変数を 参照できない。ほぅほぅ。 ローカルスコープからは、global識別子によりシンボルを修飾することで初めてグローバルの シンボル表にアクセスできる。 実引数がコピーされてローカルシンボル表に加えられるのではない。 関数の実引数の参照がローカルシンボル表に加えられる。 def fib(n): \"\"\"nまでのフィボナッチ級数\"\"\" a,b = 0,1 while a < n: print(a, end=' ') a,b = b, a+b print() fib(100) 0 1 1 2 3 5 8 13 21 34 55 89 関数名は1つのシンボルとして使える。以下のように f = fib f(100) 0 1 1 2 3 5 8 13 21 34 55 89 関数は\"return 値\"により値を返す。\"return\"またはreturnを書かない場合,Noneを返す。 関数のデフォルト値 大方の言語と同じ書き方でデフォルト値を書ける。 def fib(n=100): \"\"\"nまでのフィボナッチ級数\"\"\" a,b = 0,1 while a < n: print(a, end=' ') a,b = b, a+b print() fib() 0 1 1 2 3 5 8 13 21 34 55 89 関数のデフォルト値は1回しか評価されない。最初に1度だけ評価された後使い回される。 以下は\"[1],[2],[3]\"とならない。 def hoge(x,L=[]): L.append(x) return L [1] [1, 2] [1, 2, 3] こう書いておくと期待通りになる。 def fuga(x,L=None): if L is None: L = [] L.append(x) return L キーワード引数 大方の言語と同じ書き方でキーワード引数を書ける。 引数の位置から解放される。キーワード引数でない引数は前に持ってくる。 def fib(n=100): \"\"\"nまでのフィボナッチ級数\"\"\" a,b = 0,1 while a < n: print(a, end=' ') a,b = b, a+b print() fib(n=200) 0 1 1 2 3 5 8 13 21 34 55 89 144

default eye-catch image.

PHP7.4の新仕様 … PHP RFC: FFI – Foreign Function Interface

PHP7.4の新仕様 FFI,Foreign Function Interface について。Python的な...。 PHP7の時点で既にバイトコードになっていてPHP8からJITによるネイティブ化だったような。 PHP5.xから7.0で劇的に速くなった記憶があり、速度を追求するような機運があるのは確か。 投票システムの不備で\"賛成24、反対15,過半数越えだから採択\"みたいになり、 その後過半数から2/3に更新された、という経緯から、望まれない仕様なのは確かそう。 WordPressが速くなるのは嬉しいけども不毛すぎ..。 脱PHPが必要。 FFI is one of the features that made Python and LuaJIT very useful for fast prototyping. It allows calling C functions and using C data types from pure scripting language and therefore develop “system code” more productively. For PHP, FFI opens a way to write PHP extensions and bindings to C libraries in pure PHP. <?php / create FFI object, loading libc and exporting function printf() $ffi = FFI::cdef( \"int printf(const char *format, ...);\", // this is regular C declaration \"libc.so.6\"); // call C printf() $ffi->printf(\"Hello %s!n\", \"world\"); // create gettimeofday() binding $ffi = FFI::cdef(\" typedef unsigned int time_t; typedef unsigned int suseconds_t; struct timeval { time_t tv_sec; suseconds_t tv_usec; }; struct timezone { int tz_minuteswest; int tz_dsttime; }; int gettimeofday(struct timeval *tv, struct timezone *tz); \", \"libc.so.6\"); // create C data structures $tv = $ffi->new(\"struct timeval\"); $tz = $ffi->new(\"struct timezone\"); // calls C gettimeofday() var_dump($ffi->gettimeofday(FFI::addr($tv), FFI::addr($tz))); // access field of C data structure var_dump($tv->tv_sec); // print the whole C data structure var_dump($tz);

default eye-catch image.

PHPで統計アプリを作れるか否か

LaravelをAPIサーバにして同期的にsklearnのPCAを実行するアプリを作ってみました。 jQyery/bootstrap/chart.jsがフロント、APIサーバはLaravel+MySQL。 Laravel製APIがGET/POSTに対してPythonコードを実行します(Shellで...)。 exec()でPythonを起動するため無茶苦茶重いし、 ろくにエラーハンドリングできません。 結論から書けば同期的なアプリをこの構造で作るのは無理があります。 バックエンドが無茶苦茶重くてどうせバッチ実行になるのであれば、 上記の問題は結構問題なくなって、これでも良いかなと思い始めます。 MS系のInteroperabilityで、多言語が動的に結合するやつがありますが、 あんな感じでLL言語をglueできれば楽なのになと思います。 PSRの多言語拡張みたいなやつで、PHPからPythonのクラスを使うとか...