ゆくゆくは有へと

おかゆ/彼ノ∅有生 の雑記

input と print を使わずに標準入出力

アホ記事です。

Python の組み込み関数 open はパス渡さずに整数渡すと、そのファイルディスクリプタのファイルオブジェクトを渡してくれます。

言わずもがな(言ってほしい人向け:ファイル記述子 - Wikipedia)、0 を渡せば標準入力から読み取れるようになるし、1 を渡せば標準出力に書き込めるようになります。

まずは標準入力。

> python
Python 3.5.1 |Anaconda custom (64-bit)| (default, Feb 16 2016, 09:49:46) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> f = open(0)
>>> f.read()
aiueo
^Z
'aiueo\n'
>>> stdin.readline()
aiueo
'aiueo\n'

EOFを忘れずに(Winなら Ctrl+C)。1行だけ読みたいなら、readline()を使いましょう。ちなみに、このファイルオブジェクトを閉じようとすると Python が落ちます(例外があがるんじゃなくて最初ビビった)。

次に標準出力。

> python
Python 3.5.1 |Anaconda custom (64-bit)| (default, Feb 16 2016, 09:49:46) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> with open(1, 'w') as f:
...   f.write("HELLO!\n")
...
HELLO!
7
>>> f = open(1, 'w')
>>> f.write("aaa")
3
>>> f.flush()
aaa>>> f.close()

出力のほうは、close() されるまでバッファされて、まとめて出力されるようです。というか、close()時にフラッシュされるからっぽいので、すぐに出力したい場合はflush()しましょう。ちなみに HELLO! の下にある 7 についてですが、これは f.write("HELLO!\n") の返り値です(どうやら書き込んだ文字数っぽい)

open関数やファイルオブジェクトについてはこちらをどうぞ。

threading の同期制御の概念的なメモ

17.1. threading — スレッドベースの並列処理 — Python 3.5.2 ドキュメント

Lock

まあロックはロックやろ。データの所有権みたいなもの

厳密にはデータの所有権ではなくて、諸々のデータを用いた行動の実行権か。諸々のデータを「一人占め」して安全に行動を実行できるための。

とはいえ、Lockの権利は他の人にぶん取られることがあるから、気が済むまで悠々と行動できるわけではないよね

RLock

こっちは他の人にいきなり権利をぶん取られることはない。

再帰ロックという名の通り、所有中は何回もロックかけれる。なんのためにするんだろ?おかゆに誰か教えて。

Semaphore

これは wikipedia にもあったけど、「図書室のたとえ」が分かりやすかった

ある図書室に学習用の個室が10部屋あり、それぞれの学習室は一度に1人の学生が使用するとする。争奪戦が始まらないよう、学生はフロントデスクで学習室の使用を申し込むことになっている。学習室を使用し終えたら、学生はフロントに立ち寄ってその学習室が空いたことを知らせなければならない。全ての学習室が埋まっている場合、学生はフロントで部屋が空くのを待つ。
フロントの図書係はどの学習室が空いているかは把握しておらず、単に空いている部屋数のみを知っている。学生が申し込んできたとき、図書係はその数から1を引く。学生が学習室の利用を終えたとき、図書係はその数に1を加える。学習室の使用許可が与えられたとき、その部屋は必要なだけ使い続けることができ、したがって事前に学習室を予約することはできない。

Condition

「条件変数」っていうらしい。

自分にとってイイ感じになるまでロック手放して、イイ感じになったらまたロック取得して作業するときに使う

一方で、「共有リソース更新したぞ」ってのを他のスレッドにnotifyできる。この機能のおかげで「いい感じになったら動く」というのができる。

ロックとちがって自発的に待つことができる wait。待って、誰かが notify してくれたらいそいそと動く、みたいなことができる。

Barrier

協力プレイ系ゲームの「複数人で押さないと動かない岩とか扉」みたいなやつ

.wait して、指定人数が wait したらブロックが外れる。まさにダンジョンの仕掛け

Event

「よ~い、ドン」

誰かが「いいよ」っていうまで待機するためのもの。

ちょっとConditionと似てるよね。

それっぽい図を書くことで分かった気になるぜ(__init_subclass__)

Python3.6出ましたね!

主要なものとしては

あたりでしょうか。上2つは割とそのままで、3つ目はそもそもasync関連を勉強してからじゃないとなので、4つ目が現状の知識で一番楽しいかなという感じ。

atsuoishimoto.hatenablog.com

PEP 487 -- Simpler customisation of class creation | Python.org

わかった気になれる図

f:id:waraby0ginger:20161227061812p:plain

あまり真に受けないでください

というわけで(ひとつのユースケース

UMLのクラス図の矢印の方向でも察せる通り、継承関係を知ってるのはサブクラス側だけで、スーパークラスは誰が自分を継承してるのかということは知りません。

なので、下々のクラスどもを一括して管理したいようなとき、1つの方法としては、特定のメタクラスで生成してあげて、そのメタクラス側で生成したクラスのことを覚えておく…というのがあります。メタクラスは自分が誰を生成したのかということは知ってますから、別にどうってことないですよね。(というのが分かった気になれる図の左側)

でもそういうことするためにわざわざメタクラス学ばないといけないというのも学習障壁がしんどい。

というわけで、Python3.6では、めちゃくちゃ大雑把に言って、スーパークラスが「誰が自分を継承したか」ということを知れるようになりました。これによって、誰かが自分を継承したときに何か反応を起こすことができるようになります(__init_subclass__)し、まさに下々のクラスどもを一括して管理できるようにもなります。

というのは半分嘘で(ええ・・・)、もう少し真面目に言うと、__init_subclass__はクラスメソッドであり、このメソッドを実装しているスーパークラスを継承する際に、サブクラスがこのメソッドを呼び出します。呼び出すと言っても、そのクラスメソッドは(オーバーライドしない限り)スーパークラスのものですから、「継承時にスーパークラス__init_subclass__メソッドを呼び出す」ことには変わりありません。

スーパークラスがサブクラスを弄るという説明は(見た目的にはそれに近いことが起こりますが)微妙で、まあ単に親クラスのクラスメソッドの呼び出しです。

まあ、自分が持ってないクラス変数なら、親を探索するのはどんなメソッドでも同じですから、キモは「継承時呼び出し」というところですね。

PEP-487 の例を参考に(『Effective Python』項目34はまさにこれのメタクラスバージョンです):

class PluginBase:
    subclasses = []

    def __init_subclass__(cls, xxx, **kwargs):
        super().__init_subclass__(**kwargs)
        print(cls)
        cls.subclasses.append(cls)
        cls.xxx = xxx


class C(PluginBase, xxx=10):
    ...


class D(PluginBase, xxx=20):
    ...

クラスCとDは__init_subclass__を実装しているPluginBaseのサブクラスであり、これらがPluginBaseを継承するタイミングで、このメソッドが(サブクラスから)呼ばれます(なので、clsに入るのはサブクラスであるCやDです)。

PluginBase は subclasses リストをクラス変数として持っており、そこに呼び出したクラス cls を追加していくわけですね(cls.subclasses.append(cls)に10分くらい戸惑っていましたが、cls.subclassesスーパークラス(PluginBase)の変数を参照しようとしてるわけですね。でもこれ、C, Dがクラス定義でsubclasses変数持ってたらそっちにアクセスされちゃうのでダメです。なので、__class__.subclassesでアクセスするのがより安全だとは思います)。

で、今まで親クラスやメタクラスなど書いてたところに、__init_subclass__が引数として取る値を入れれるようになりました。上の例ではxxxがそれです。指定外のキーワード引数は kwds に吸収されるっぽい。

これが何に使えるのか…というところですが、メタクラスの代理としてスーパークラスを用いるためとしてこの機能があることを踏まえると、今までのクラス生成時におけるクラス変数の調整のところを代替できるようになるんじゃないですかね(しらんけど)。

もうちょいまともに見てみる

メタクラスがそれに従うクラスを生成するときに引数としてとるのは

  • クラス名
  • 親クラスのタプル
  • そのクラスの属性辞書

の3つです。ところで、__init_subclass__ においては、この3つは

  • クラス名:cls.__name__
  • 親クラスのタプル:cls.__mro__[1:]
  • 属性辞書:cls.__dict__

でアクセス可能ですから、実際、メタクラス__new__でできたことの大抵は__init_subclass__でできるようになったんじゃないかと思います。

『Effective Python』の項目33, 34, 35 のようなことは__init_subclass__(と__set_name__)で実現できるようになったと思います。

たとえば、具象クラスのチェックが抽象クラスに書けるようになったのはなかなかお得な感じがします。Effective Python 33のソースコードを書き換えてみました:

class Polygon:
    sides = None

    @classmethod
    def interior_angles(cls):
        return (cls.sides - 2) * 180

    def __init_subclass__(cls, sides, **kwds):
        if sides < 3:
            raise ValueError("Polygons need 3+ sides")
        cls.sides = sides


class Triangle(Polygon, sides=3):
    pass


class FalsePolygon(Polygon, sides=2):
    pass

Polygon を基底クラスとして、これを継承するサブクラスの sides は3以上であることをサブクラス生成/継承時にチェックします。

sides をわざわざ引数として渡さずに、クラス定義の中に書いてしまってもいいとは思いますが、まあチェック時に値を属性辞書から取り出すようにするかどうかの違いしかないですね。

当該PEPによれば、__init_subclass__メタクラス__new__内部で実行されるようなので、ここで例外があがればクラス自体生成されないことになるようです(この辺りはインスタンス生成の__init__と挙動が少し異なりますね(インスタンスの場合、__init__が失敗してもインスタンス自体は作られてしまうので))。

この例を見ると、抽象基底クラス(ABC)とかなり相性がよさそうに見えますね!今までは具象クラスで実装してほしいクラス変数は、ABCではとりあえず None にしておいて書いておくという方法しかなかったですが、__init_subclass__ の引数として必須にしておけば、具象化のためにその値が必要だということが分かる上に、姑息にNoneを入れて変数の存在を示唆する必要もなくなりますので、お役立ちって感じです。

あと(ケースとして必要かは微妙ですが)、サブクラスはその属性をもっていてほしいが、スーパークラスには持たせたくない、かつ、だけどサブクラスでその属性の値を指定しない場合はデフォルト値を想定したい、というようなときは、デフォルト引数としてその値を渡せばいいですよね。

おわり

メタクラスのメタな操作がスーパークラスまで降りてきたことで、メタいことが学習障壁を低くして実現できるようになったってだけの話ではありますが、ABCがその具象化に対する責任を持てるようになったというのは結構偉大なことかとは思います。

とはいえ、単純にメタいことをスーパークラスに書いちゃえるということは、それだけ概念的に混乱するリスクも増えるということでしょうし、その辺りは注意しないといけないかもしれません。

まあメタメタ言ってますが、スーパークラスのサブクラスへの干渉という観点でみれば、そんなメタメタしくはない気もします。見方によりますね。上の方で半分嘘と言いながら説明した「スーパークラスが誰から継承を受けたか知れるように(そしてある程度操作できるように)なった」という観点が増えたと思えばいいかもしれない。学習障壁云々の話をしましたが、実際じゃあこのカスタムメソッドを説明するときに「今まではメタクラスでやってたことがね」という導入はメタクラスの概念を持ちこんでしまってるわけであまりよろしくはないと思います。メタクラスで実現していたという事実はあったとしても、あくまでクラスレベルでの関係性としてこのカスタムメソッドを捉えて説明しないことには本格的な学習障壁の低下にはならんでしょう。そうなると、「スーパーからサブ方向への接触を可能にする」という形になるんじゃないかと思います。

話かわって。THEメタといえば、動的なクラス生成がありますが、これもそんな凝ったものでなければtypeと__init_subclass__だけで十分まかなえそうだし、クラスレベルでかなりやれることが増えたなという感じはします!

ま、メタクラスを使わない方法でいえば、今までもクラスデコレータがありましたけどね!それに加えてもう一つ新しい方法が増えたというくらいに考えるのがいいかも。

もやもやのメモ

構造体のセレクタ

golang.jp

セレクタは自動的に構造体へのポインタの間接参照を行います。xが構造体へのポインタ型のときx.yは(*x).yの簡略形として使用可能です。フィールドyも同じく構造体へのポインタ型のときx.y.zも同様に(*(*x).y).zの簡略形です。xが*A型の匿名フィールドを持ち、かつAも同様に構造体であるなら、x.fは(*x.A).fの簡略形です。

どおりで!

new()

golang.jp

組み込み関数newはパラメータに型Tを取り、型*Tの値を返します。

なるほどなあっ!

make()

golang.jp

スライス、マップ、チャネルはnewによる間接的なメモリ割り当てを必要としない、参照型です。組み込み関数makeはパラメータに型Tを取ります。このTはスライス、マップ、チャネル型でなければなりません。またオプションとして式のリスト(作成する種類によって異なる)を取ります。makeはT型(*Tではない)を返します。

なるほどなあっっ?

www.geocities.jp

スライスが配列へのポインタをもって云々というのは分かる(参照してる感が理解できる)けど、マップはどうしてるんだろ?キャパシティ云々のこと考えると、やっぱバックで適当に配列見繕ってマップパターンを実現してるのかな?

日本人のロジバン学習ロードマップ(たぶん)

オチ

学習 - La Lojban

ここを適宜読もう!

はじめに

この記事は、日本人(注:英語の教材を読むよりは日本語の教材を読む方が楽な人のことを指しています)がロジバンを学びたいときにどこを読んでいけばいいのかというのを書いたものです。

ですが、やっぱり最終的には英語のドキュメントにあたることになります。仕方ないですね。英語力も鍛えてください。

ここでは、できる限り基本は日本語で学べるような道を用意します。

まずはここから

間違ったスタートダッシュ

ロジバン - Wikipedia

やめときましょう(先人のアドバイス)。

正しいスタートダッシュ

はじめてのロジバン 第2版 - はじめてのロジバン第2版

は?宣伝です。

とは言え、ロジバンに興味をもって学ぼうとした人が訪れる場所は大抵「はじロジ」っぽいので、やっぱりここをオススメします。

「ニューゲーム」はほぼ完成(メンテナンスのみ)しているので安心して読めますが、その続編である「つよくてコンティニュー」はいまだ執筆中のようです(ようです?)。

とはいえ、とりあえず「ニューゲーム」だけでも読んでおけば、語彙も基本中の基本はそこそこ、文法は割りかし適度に追えるようになれるはずです。「つよコン」は…、出来上がってるところまで読んで、書き上がり次第フォローしていきましょう。

サプリメント

「はじロジ第2版」は音声に関してはめっきりなので、発音が気になるという人はこちらもオススメします:

ko lojbo .iu ロジバン入門

日本語の音声講座で、毎回の終わりに発音講座があります。そこだけ聞いてもよし、もちろん文法講座のところも聞いてよし。

その次は?

「はじロジ2」が完結すれば、この寄り道はいらないんですが、現状はここに立ち寄るのがベターらしいです。

seesaawiki.jp

「はじロジ2」を読んでいれば、入門コースは飛ばしても大丈夫だと思います。「PSの傾向」くらいは読んでてもいいかもしれない(雑学程度だけど)。

初級コースをかいつまみましょう。たとえば:

  • 品ある品詞:brivla の下位分類、gismu, lujvo, fu'ivla に関する簡単な説明がある
  • 命題を項に(抽象詞):{tu'a}の説明がある
  • 項で項を(pe,ne):{po}, {po'e} の説明がある(けど、実際に使う機会はほとんどない気がするので飛ばしてもOK)
  • アレ、云々(省略語):そこまで重要な話でもないが、体系的に語を覚えたいなら。

冠詞のところ、数詞のところ、分配性と集団性は読まなくてもいいです。というか読まないほうがいいかもしれない。理由は単に「分かりにくい」からで、はじロジ2でもっと分かりやすい解説がくるのを待ったほうがいいです。

補助資料や補習資料も気になるものに目を通せばいいと思います。

サプリメント

分配性と集団性についてどうしても気になる人で、かつ、論理学の素養がある程度ある人はここを読むのをおすすめします:

gadri の論理学的観点からの解説 - La Lojban

ただ…、まあそんな気にするものでもないです(アドバイス)。最近のロジバンはこのあたり特に考えなくても簡単に使えるようになっています。

その次は?

lojban wave lessons(おかゆはLWLと略す)を読みましょう!日本語訳版は現在2つあって、現在はlojban wikiの方がメインです。経緯としては、まず「味噌煮込みロジバン」での日本語訳があり、それが wiki に移行されました:

lojban wavelessons 日本語版 - La Lojban

misonikomilojban.blogspot.jp

はじロジと難易度・内容はそこまで変わりませんが、定番の講座ではあるので、一読をおすすめします。はじロジとは異なる視点でロジバンを理解しておくのも大事なことです。

サプリメント

Lojban Wave Lessons - La Lojban

英語版(原書)です。最後の数章は日本語に訳されていないので、どうしても読みたい場合は英語で読むことになります(が、まあこの時点で読まなくてもいい気はしないでもないです)。

割と読んできたけど?

ロジバン大全: The Complete Lojban Language 日本語抄訳

おかゆはCLLと略します。いわゆるロジバンの仕様書のようなものです。が、微妙に仕様が古いところがあります(特に冠詞まわりの意味論)。ので、あくまで参考ということで読むのがいいと思います。細かい仕様はCLLを見ないとどうにもならないことは確かにあります。

ただ、完読は結構しんどいとは思うので、気になるところだけ読みましょう。20章の「セルマホ目録」は便利な索引です。

サプリメント

The Lojban Reference Grammar

LRG。CLL日本語抄訳の底本(1.0)の改訂版。

さらにロジバンを知りたい人へ

ここからは英語になります。

BPFK Sections - La Lojban

BPFKは、ロジバンの意味論をいまいちど整理しようとして動いている委員会(公式)です。BPFK Sections は委員会によって整理・提案されている各機能語の意味論が載っています。CLLが微妙に気に食わないときはここを読んで気に入りましょう。

BPFK sections に載ってない場合は、各メーリスを覗くと色々分かるかもしれません。

  • ロジバン相談室:日本のロジバンメーリス
  • lojban:ロジバンのメーリス
  • BPFK:さっき言ったBPFKのメーリス(これについては英語どころかほぼ完全にロジバンだけによる議論です♡)

あ、あと、wiki 見ると何かあるかもしれませんね:

Lojban

このあたりを調べ尽くして無いようなら、多分ないです。

おわりに

まあオチは最初に書いたので言うことはないんですが、とりあえずこっちに来て一緒に苦しみ楽しみましょう!