やりたいことは見出しと逆のこと。プリミティブかどうかではなく、「プリミティブでないので何かヘンなこと」をしたい。
そして宗教問題:
In Python, everything is an object; even ints and bools. So if by ‘primitive’ you mean “not an object” (as I think the word is used in Java), then there are no such types in Python.
嘘です。宗教問題でもなんでもなくて。Python では「3」という数値でさえも object である、てわけです。(ちなみにこれの正確な理解をするのに一番いいのは Python C API を理解すること、だったりします。)
完璧な解はないんじゃないかと思う。
まず、「特定のモジュールに属するタイプかどうか」を知ることが目的ならば、これが近いといえば近い:
1 class NewStyleClassInModuleBbb(object):
2 pass
1 # this example for Python from 2.2 to 2.7
2 class NewStyleClass(object):
3 pass
4 nscobjAaa = NewStyleClass()
5 print(nscobjAaa.__class__.__module__)
6
7 import bbb
8 nscobjBbb = bbb.NewStyleClassInModuleBbb()
9 print(nscobjBbb.__class__.__module__)
10
11 print([].__class__.__module__)
12 print((3).__class__.__module__)
13
14 import re
15 rgx = re.compile(r"^$")
16 print(rgx.__class__.__module__)
1 me@host: ~$ python aaa.py
2 __main__
3 bbb
4 __builtin__
5 __builtin__
6 _sre
7 me@host: ~$
今の場合「bbb」が既知で、「bbbに属するか」が知りたいのならこれでいい。ただ、パッケージまで特定出来ないので、標準添付ライブラリの名前と衝突してると混乱するであろう。
また、この例の場合でも、「ライブラリはライブラリ、組み込み型は組み込み型」でいいのであれば、__builtin__
が返るのは参考になるであろう。
なお、「bbb」が既知で、「bbbに属するか」を完全にしたくて、今 bbb.py が以下として:
1 import hashlib
2 import re
3
4 class NewStyleClassInModuleBbb1(object):
5 pass
6
7 class NewStyleClassInModuleBbb2(object):
8 a = 1
9 b = NewStyleClassInModuleBbb1()
10 c = hashlib.md5()
11 d = re.compile(r"^$")
例えば以下:
1 # this example for Python from 2.2 to 2.7
2 class NewStyleClass(object):
3 pass
4 nscobjAaa = NewStyleClass()
5
6 import bbb
7 nscobjBbb = bbb.NewStyleClassInModuleBbb2()
8
9 import sys
10 import inspect
11
12 print(
13 inspect.getmodule(nscobjAaa) is sys.modules['__main__'])
14 # => True
15
16 print(
17 inspect.getmodule(nscobjBbb) is bbb)
18 # => True
19
20 print( # a = 1
21 inspect.getmodule(nscobjBbb.a))
22 # => None
23 print( # a = 1
24 inspect.getmodule(nscobjBbb.a) is bbb)
25 # => False
26
27 print( # b = bbb.NewStyleClassInModuleBbb1()
28 inspect.getmodule(nscobjBbb.b))
29 # => <module 'bbb' from '/home/youwashark/bbb.pyc'>
30 print( # b = bbb.NewStyleClassInModuleBbb1()
31 inspect.getmodule(nscobjBbb.b) is bbb)
32 # => True
33
34 print( # c = hashlib.md5()
35 inspect.getmodule(nscobjBbb.c))
36 # => None
37 print( # c = hashlib.md5()
38 inspect.getmodule(nscobjBbb.c) is bbb)
39 # => False
40
41 print( # d = re.compile(r"^$")
42 inspect.getmodule(nscobjBbb.d))
43 # => None
44 print( # d = re.compile(r"^$")
45 inspect.getmodule(nscobjBbb.d) is bbb)
46 # => False
うまくいっているように見えるかもしれないが、hashlib や re のモジュールが取れない(None)のと同じことが起こる(bbb、aaa を「インストール」してみればいい)ので、実はダメ。これはちょっと勘弁して欲しいよ。
無論以下のような果てしないアプローチでも良い:
1 primitive = (int, str, bool, 以下延々...)
2
3 def is_primitive(thing):
4 return isinstance(thing, primitive)
これで良いかどうかはやはり目的によるであろう。
この件は、大変釈然としないので、もちっと研究しようと思う。なんかこれじゃあんまりだ、っと。