objectとtypeの関係を図にまとめた
- 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にたどり着きます。
# 再掲 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に辿り着きます。
# 再掲 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 という関数もあるけれど
実は issubclass や isinstance 関数を使うと、継承関係を一発で調べることができます。
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')}
少し前に、証拠データの日付を書き換えた検察官がいて問題になったことがあります。遠隔操作ウイルス事件もそうですが、日本ではあまりフォレンジックとかやらないんでしょうか。
どれくらい昔の日付に設定できる?
ウィキペディアで調べると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'
ところで、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)"
しかし、アップデートごとにこれを実行するのは面倒くさくて、しばらく放置していたのだが、今日ふと検索してみると、レジストリーに起動させなくなるオプションがあるのね。
Windows Registry Editor Version 5.00 [HKEY_CURRENT_USER\Software\Evernote\Evernote] "StartEvernoteClipper"=dword:00000000
これで起動しなくなったっぽい。
マイナスはリテラルの一部じゃなくて演算子
二乗したのに符号がマイナスなんだけど「こいつ虚数か?」と思ったら、単純に **
が先に評価されているだけでした。
>>> -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('切り替える')
Fallout3 に出てくるゲイリーの元ネタ?
住人が全員ゲイリーという名前のクローン人間ばかりになっている核シェルターが Fallout 3 に登場する。
先日、本を読んでいたら、このゲイリーの元ネタっぽいものを見つけた。本のタイトルは「平均思考は捨てなさい」(原題:THE END OF AVERAGE)だ。
子供たちを組織化して教育を施し、工場での仕事を「完璧に」こなす労働者に仕立て上げるため、テイラー主義者は科学的管理法の中心的な教義に従って教育制度全体の構造の見直しに取り組んだ。すなわち、平均を使ってあらゆるものを標準化したのだ。例えば、全米の学校が「ゲイリー・プラン」を採用する。これはインディアナ州の工業都市ゲイリーに由来するもので、(以下略)
(Googleブックスの立ち読みページより問題部分を太字にして引用。)
なんとなく、この社会思想には覚えがあるなと思っていたら、Falloutの世界観にそっくりじゃん。しかもゲイリー・プランって。
すぐに英語版ウィキペディアで詳細を調べてみたのだが、そうしたら William Wirt (ウィリアム・ワート?)なる教育家が出てきた。
「ゲイリー!ゲイリーなのか?」
なんか、この人、ゲイリーに似てない? 目の下の皺とか、髪型とか、眉毛の角度とかが一致してるように見えるんだけど。
画一的な労働者に画一的な作業をさせて最高の生産性を実現しようというテーラー主義の夢は、ひょっとしたらひょっとして、Falloutの世界でクローン技術と出会い、そして無残にも失敗した、ということになっているのかもしれない。
以上が小生の推測なんだけど、確証を求めて色々思い当たる所を英語で検索してみたのだが、この件について言及しているところは1つもなかった。というわけで真相はよくわからん。