13
4

3 に答える 3

8

更新 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のオブジェクトを修正する方法については...まあ、そのコードを見ずにどうすればわかりますか??? コードを教えてください。それについて考えると約束します。わかりました、私はそれについて考えています... 今のところアイデアはありません。

于 2010-02-22T16:17:07.223 に答える
6

したがって、問題は、以下のようなクラスが奇妙に動作することです

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
于 2010-02-22T16:21:22.920 に答える
3

あなたの問題は、ビルトインを拡張しようとしていることだと思います。マジック__メソッドはビルトインに対して呼び出されません。私はあなたがこのような(テストされていない)ある種のラップアンドデリゲートをしなければならないと思います(多分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
'***'

ですから、間違いなくいくつかの矛盾が起こっています...

于 2010-02-22T16:45:24.513 に答える