objectとtypeの関係を図にまとめた

なお、図では以下のようなクラスを使いました。

# 何も継承指定しないとobjectを継承したことになる(※Python3から)
class Foo: pass
# Fooを継承
class Bar(Foo): pass

# 独自のメタクラスを作成して使用
class MyType(type): pass
class Hoge(metaclass=MyType): pass

# クラスのインスタンス化
f = Foo()
b = Bar()
h = Hoge()

# ビルトインタイプのインスタンス化
n = 123
s = 'hello'

object

クラスの継承元を辿っていくと必ずobjectにたどり着きます。

f:id:itasuke:20171210224844p:plain

# 再掲
class Foo: pass
class Bar(Foo): pass

# ごく普通の継承
print(Foo.__bases__[0] is object)  # True
print(Bar.__bases__[0].__bases__[0] is object)  # True !!

# ビルトインタイプも同様
print(int.__bases__[0] is object)  # True
print(str.__bases__[0] is object)  # True

なぜ __bases__[0] のように複数形なのかというと、多重継承できるからです。

type

Pythonではクラスも含め全てがオブジェクトということになっています。では「そのオブジェクトはどのクラスから作られたの?」という質問を繰り返すと必ずtypeに辿り着きます。

f:id:itasuke:20171210224841p:plain

# 再掲
n = 123
s = 'hello'
f = Foo()
b = Bar()
h = Hoge()

# あなたのクラスは...?
print(n.__class__ is int)  # True
print(s.__class__ is str)  # True
print(f.__class__ is Foo)  # True
print(b.__class__ is Bar)  # True
print(h.__class__ is Hoge)  # True

# あなたのクラスのクラスは...?
print(n.__class__.__class__ is type)  # True
print(s.__class__.__class__ is type)  # True
print(f.__class__.__class__ is type)  # True
print(b.__class__.__class__ is type)  # True
print(h.__class__.__class__ is MyType)  # True !!
print(h.__class__.__class__.__class__ is type)  # True !!

issubclass / isinstance という関数もあるけれど

実は issubclassisinstance 関数を使うと、継承関係を一発で調べることができます。

print(issubclass(Bar, Foo))  # True
print(issubclass(Bar, object))  # True

print(isinstance(b, Bar))  # True
print(isinstance(b, Foo))  # True
print(isinstance(Bar, type))  # True
print(isinstance(Hoge, MyType))  #True !!

一方で、これらの関数は実際の継承関係になくても、継承していることにしてしまうことがあるので、この記事では使いませんでした。

from collections.abc import Sequence

print(issubclass(str, Sequence))  # True !!
print(isinstance('hello', Sequence))  # True !!

# str は Sequence なんぞ継承しとらんぞ
print(str.__mro__)  # (<class 'str'>, <class 'object'>)

なぜこんな機能が必要かというと、↓このような型チェックのために使います。ダックタイピングってやつです。

import collections.abc

# 何も継承しない(objectは除く)
class ZZZ:
    def __len__(self):
        return 0

def print_length(obj):
    # 抽象基底クラスの確認
    if isinstance(obj, collections.abc.Sized):
        print('あなたの長さは %d です' % len(obj))
    else:
        print('あなたに長さはありません')

# 長さのあるオブジェクト達
print_length('hello')  # 5
print_length([1, 2, 3])  # 3
print_length({'A':'ei', 'B':'bee'})  # 2
print_length(ZZZ())  # 0

# 長さのないオブジェクト達
print_length(None)  # なし
print_length(open)  # なし
print_length(123)  # なし

以上です。

PowerShellとファイルの日付についてちょっとしたこと

PowerShellを使うとファイルやフォルダーの日付を簡単に変更できますが、

(Get-Item c.txt).LastWriteTime = '2012/3/4 5:6:7'

ちゃんと小数点以下まで指定しないと、日付を変更したことがばれます。

Get-Item *.txt | Select-Object Name,{$_.LastWriteTime.ToString('yyyy/MM/dd HH:mm:ss.fffffff')}

f:id:itasuke:20171214160136p:plain

少し前に、証拠データの日付を書き換えた検察官がいて問題になったことがあります。遠隔操作ウイルス事件もそうですが、日本ではあまりフォレンジックとかやらないんでしょうか。

どれくらい昔の日付に設定できる?

ウィキペディア調べるとNTFSはファイルの日付を1601年1月1日 0時0分0秒 (UTC) から100ナノ秒単位で保持しているようです。論理的にはこの日付に設定できるはずですが、実際にやってみるとできません。

(Get-Item c.txt).LastWriteTimeUtc = '1601/1/1'

これはWindowsAPIの仕様で、SetFileTime関数に基点となる日付からきっかり 0 秒後が指定されるとスルーされてしまうのです *1。そういうわけで、0時0分0.0000001秒が、設定できる最も古い日付ということになります。

(Get-Item c.txt).LastWriteTimeUtc = '1601/1/1 0:0:0.0000001'

f:id:itasuke:20171214160127p:plain

ところで、C言語のFILETIME構造体と.NETのDateTime構造体は少し仕様が違います。分解能は同じですが、後者は基点が西暦1年になっています *2。なので、PowerShell側で以下のような日付を作ることは可能ですが、

$dt = [datetime] '0001/1/1'

この日付をNTFSのファイルに指定するとWin32エラーになるのはそういう理由です。

(Get-Item c.txt).LastWriteTimeUtc = $dt
# "LastWriteTimeUtc" の設定中に例外が発生しました:
# "有効な Win32 FileTime ではありません。"

以上です。

*1:そもそもPowerShellはSetFileTime関数を使っているのかという疑問がありますが、少なくとも Process Monitor で見る限り呼び出しているようです。また、FILETIME構造体も日付の仕様はNTFSと同じです。

*2:http://referencesource.microsoft.com/#mscorlib/system/datetime.cs,131 コメントより

EvernoteClipper.exeの常駐設定

Evernoteのクライアントをインストールすると、EvernoteClipper.exeが常駐するようになる。自動起動から外しておいても、Evernoteのクライアントと一緒に起動してきて、クライアント終了後に常駐する。

自分はウェブをクリップする時、この機能は使わず、範囲選択してからコピー&ペーストしている。EvernoteClipper.exeを起動させておくと、極わずかだがメモリとCPUサイクルを余計に消費するので、以前は icacls でアクセス許可を変更し実行拒否にしていた。(ファイルの削除で対処すると、インストーラーが起動してきて元に戻そうとする)

icacls EvernoteClipper.exe /deny "everyone:(x)"

しかし、アップデートごとにこれを実行するのは面倒くさくて、しばらく放置していたのだが、今日ふと検索してみると、レジストリーに起動させなくなるオプションがあるのね。

discussion.evernote.com

Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\Software\Evernote\Evernote]
"StartEvernoteClipper"=dword:00000000

f:id:itasuke:20171213123722p:plain

これで起動しなくなったっぽい。

マイナスはリテラルの一部じゃなくて演算子

二乗したのに符号がマイナスなんだけど「こいつ虚数か?」と思ったら、単純に ** が先に評価されているだけでした。

>>> -1 ** 2
-1
>>> (-1) ** 2
1

よく読むと、チュートリアルにも記載されてるし。

- よりも ** の方が優先度が高いので、-3**2-(3**2) として解釈され、結果は -9 になる。こういうふうに解釈されないよう (-3)**2 にすると 9 という結果が得られる。

Since ** has higher precedence than -, -3**2 will be interpreted as -(3**2) and thus result in -9. To avoid this and get 9, you can use (-3)**2.

https://docs.python.org/3/tutorial/introduction.html#id3

きっとあまりにも間違える人が多いので、わざわざ注意書きしてあるんでしょうね。なんかすいません。

そもそも - ってリテラルの一部じゃなくて演算子なのね。-1 を ast で分解させるとこの通り。

>>> import ast
>>> ast.dump(ast.parse('-1'))
'Module(body=[Expr(value=UnaryOp(op=USub(), operand=Num(n=1)))])'

つまり、こういうことです。

class SmileParty:
    def __neg__(self):
        return 'ネガティブから'
    def __pos__(self):
        return 'ポジティブに'

s = SmileParty()
print(-s)
print(+s)
print('切り替える')

www.youtube.com

Fallout3 に出てくるゲイリーの元ネタ?

住人が全員ゲイリーという名前のクローン人間ばかりになっている核シェルターが Fallout 3 に登場する。

先日、本を読んでいたら、このゲイリーの元ネタっぽいものを見つけた。本のタイトルは「平均思考は捨てなさい」(原題:THE END OF AVERAGE)だ。

子供たちを組織化して教育を施し、工場での仕事を「完璧に」こなす労働者に仕立て上げるため、テイラー主義者は科学的管理法の中心的な教義に従って教育制度全体の構造の見直しに取り組んだ。すなわち、平均を使ってあらゆるものを標準化したのだ。例えば、全米の学校が「ゲイリー・プラン」を採用する。これはインディアナ州工業都市ゲイリーに由来するもので、(以下略)

Googleブックス立ち読みページより問題部分を太字にして引用。)

なんとなく、この社会思想には覚えがあるなと思っていたら、Falloutの世界観にそっくりじゃん。しかもゲイリー・プランって。

すぐに英語版ウィキペディアで詳細を調べてみたのだが、そうしたら William Wirt (ウィリアム・ワート?)なる教育家が出てきた。

f:id:itasuke:20171129191714p:plain:w300 *1

「ゲイリー!ゲイリーなのか?」

なんか、この人、ゲイリーに似てない? 目の下の皺とか、髪型とか、眉毛の角度とかが一致してるように見えるんだけど。

画一的な労働者に画一的な作業をさせて最高の生産性を実現しようというテーラー主義の夢は、ひょっとしたらひょっとして、Falloutの世界でクローン技術と出会い、そして無残にも失敗した、ということになっているのかもしれない。

以上が小生の推測なんだけど、確証を求めて色々思い当たる所を英語で検索してみたのだが、この件について言及しているところは1つもなかった。というわけで真相はよくわからん。

追記

そういえば古典的SF小説「すばらしい新世界」にも受精卵の分割によるクローンや、それによる社会階層の話が出てくる。Falloutのテーマでもあるレトロフューチャーってやつは、こういう世界観の元で作られたのかもしれないね。洋ゲーのシナリオはたまにこういう発見があるから面白い。

*1:画像はウィキメディア・コモンズとGoogle画像検索より引用してトリミング+レベル調整