3 に答える
更新 2:水平バーの下にある、OP で説明されている動作を示すクラスの簡単な例を含む、元の回答を見つけてください。Python のソース (v. 2.6.4) を調べたときに推測できたことについては、次のとおりです。
ファイルInclude/unicodeobject.h
には次の行が含まれています(私の(やや古い)チェックアウトの番号436-7):
#define PyUnicode_AS_UNICODE(op) \
(((PyUnicodeObject *)(op))->str)
これは、書式設定コードのいたるところで使用されています。これは、私が知る限り、文字列の書式設定中に、から継承するすべてのオブジェクトunicode
に到達することを意味し、そのユニコード文字列バッファを呼び出すことなく直接使用できるようにします。 Python メソッド。パフォーマンスに関する限り、これは良いことだと思います(そして、この回答に対するコメントでのユルゲンの推測と非常に一致しています)。
OPの質問については、これはおそらく、この特定のユースケースでAnurag Unyalのラッパークラスのアイデアのようなものが受け入れられる場合にのみ、OPが望むように物事を機能させることができることを意味します. そうでない場合、今私の頭に浮かぶ唯一のことは、このクラスのオブジェクトを文字列に補間されるstr
/unicode
どこでもラップすることです...うーん。(誰かがすぐに指摘するよりクリーンなソリューションが欠けていることを心から願っています!)
(更新:これは、OPに彼のクラスのコードが含まれる約1分前に投稿されましたが、とにかくここに残します(1)推測/コードの下の説明の最初の試みのために、(2)簡単な例のためにこの動作を生成する方法について (Anurag Uniyal は、それ以来unicode
、 を介してではなく、 のコンストラクタを直接呼び出す別のものを提供していますsuper
)、(3) 後で何かを編集して、OP が目的の動作を取得するのを支援できるようにすることを期待しています。)
OPが説明するように実際に機能するクラスの例を次に示します(Python 2.6.4、非推奨の警告が生成されます- /usr/bin/ipython:3: DeprecationWarning: object.__init__() takes no parameters
):
class Foo(unicode):
def __init__(self, msg):
super(unicode, self).__init__(msg)
def __str__(self): return 'str msg'
def __repr__(self): return 'repr msg'
def __unicode__(self): return u'unicode msg'
IPython でのいくつかの相互作用:
In [12]: print(Foo("asdf"))
asdf
In [13]: str(Foo("asdf"))
Out[13]: 'str msg'
In [14]: print str(Foo("asdf"))
-------> print(str(Foo("asdf")))
str msg
In [15]: print(str(Foo("asdf")))
str msg
In [16]: print('%s' % Foo("asdf"))
asdf
どうやら文字列補間はこのオブジェクトを(の実装をunicode
直接呼び出す) のインスタンスとして扱いますが、他の関数はそれを のインスタンスとして扱います。これが内部でどのように発生し、なぜこのように機能するのか、バグなのか機能なのか、私には本当にわかりません。unicode
__str__
Foo
OPのオブジェクトを修正する方法については...まあ、そのコードを見ずにどうすればわかりますか??? コードを教えてください。それについて考えると約束します。わかりました、私はそれについて考えています... 今のところアイデアはありません。
したがって、問題は、以下のようなクラスが奇妙に動作することです
class Msg(unicode):
def __init__(self, s):
unicode.__init__(self, s)
__unicode__ = __repr__ = __str__ = lambda self: "my message"
msg = Msg("another message")
print str(msg)
print unicode(msg)
print "%s"%msg
これは印刷します
my message
my message
another message
なぜこれが起こるのか、またはそれを修正する方法はわかりませんが、メッセージをラップすることによる非常に大雑把な試みですが、OPの問題に役立つかどうかはわかりません
class MsgX(object):
def __init__(self, s):
self._msg = Msg(s)
__unicode__ = __repr__ = __str__ = lambda self: repr(self._msg)
msg = MsgX("another message")
print str(msg)
print unicode(msg)
print "%s"%msg
出力:
my message
my message
my message
あなたの問題は、ビルトインを拡張しようとしていることだと思います。マジック__
メソッドはビルトインに対して呼び出されません。私はあなたがこのような(テストされていない)ある種のラップアンドデリゲートをしなければならないと思います(多分Anuragは私をパンチに打ち負かしました):
class Message(object):
def __init__(self, strvalue, domain, default='my message'):
self.msg = zope.i18nmessageid.Message(strvalue,domain,default)
def __getattr__(self,attr):
return getattr(self.msg,attr)
def __repr__(self):
return repr(zope.i18n.interpolate(self.msg.default, self.msg.mapping))
def __str__(self):
return zope.i18n.interpolate(self.msg.default, self.msg.mapping)
def __unicode__(self):
return zope.i18n.interpolate(self.msg.default, self.msg.mapping)
アップデート1-ビルトインのサブクラスに対して__
メソッドが呼び出されるようです
>>> class Z(int):
... def __add__(self,other): return self*other
... def __str__(self): return "***"
...
>>> a = Z(100)
>>> a + 2
200
>>> a
100
>>> str(a)
'***'
>>> "%s" % a
'***'
ですから、間違いなくいくつかの矛盾が起こっています...