0

C++ プログラムを生成する Python プログラムを作成しています。次のようなコードのインスタンスがたくさんあります。

class TestBlock(object):
    def __init__(self, mod, name, casetype, generator):
        self.mod = mod
        self.name = name
        self.casetype = casetype
        self.generator = generator

    def fullname(self):
        return "{mod}.{name}".format(**self.__dict__)

    def write_cases(self, outf):
        outf.write("const {casetype} {mod}_{name}[] = {{\n"
                   .format(**self.__dict__))
        for case in self.generator():
            outf.write("  { " + case + " },\n")
        outf.write("};\n\n")

この"text {subst}".format(**self.__dict__)構築は、 のインスタンス変数を名前付き置換として使用できるようにする唯一の方法でselfあり、見苦しく、好きではありません。書けるようになりたい"text {subst}".format(self)です; これは可能ですか?私はそれ"text {0.subst}".format(self)が箱から出してすぐ"text {subst}".format(**self)に動作し、いくつかの特別な方法で動作するようにすることができることを認識していますが、それらの両方にはまだ余分な問題があります.

4

4 に答える 4

2

機能を関数でラップできます。

def fmt(msg, obj):
    return msg.format(**obj.__dict__)

それで:

def fullname(self):
    return fmt("{mod}.{name}", self)
于 2012-12-07T22:53:08.153 に答える
1

いいえ、あなたが望むことをするための一般的な方法はありません。__getitem__項目アクセスを属性アクセスに委譲する (つまりobj['foo']、 と同じにする) メソッドを持つように、クラスを作成できますobj.foo。ただし、アイテム アクセスを他の目的に使用することはできません。また、アイテムへのアクセスをこのように定義していないサードパーティ クラスに対しては、これを行うことはできません。

別の方法として、オブジェクトをラップするマッピング オブジェクトを作成するユーティリティ関数を作成することもできます。その場合はそのようにします"text {subst}".format(wrapper(self))が、「{0.subst}」がすでに「あまりにもひどい」ものである場合は、おそらく満足できないでしょう。

このformatメソッドは、任意の名前空間の名前をフォーマット文字列にマッピングするための汎用的なものではありません。オブジェクトの属性ではなく、キーをマッピングにマップします。オブジェクトの属性をマップしたい場合は、何らかの方法でそれらをマッピングに入れる必要があります。「{0.subst}」はそれほど悪くありません。

于 2012-12-07T22:27:44.947 に答える
0

なんらかの理由で string.format を使用する必要がない場合 (たとえば、文字列を使用しているだけで、フォーマットのミニ言語は必要ない場合)、次のようなものが役立つ場合があります。

import re


SUB_RE = re.compile(r"{(.*?)}")

class Formattable(object):
   def format(self, s):
      def repl(matchobj):
         var = matchobj.group(1).strip()
         try:
            retval = getattr(self, var)
         except AttributeError:
            retval = "ERROR"
         return retval

      return SUB_RE.sub(repl, s)



class Test(Formattable):
   def __init__(self, foo, bar, baz):
      self.foo = foo
      self.bar = bar
      self.baz = baz

t = Test('myFoo', 'bbbbbar', 'BAZZZZ')
print t.format("foo = {foo}")
print t.format("bar = {bar} but baz is {baz}")

版画

foo = myFoo
bar = bbbbbar but baz is BAZZZZ
于 2012-12-07T22:34:02.243 に答える
0

を使用してこのようなものはどうですかstring.Template:

from string import Template

class TestBlock(object):
    def __init__(self, mod, name, casetype, generator):
        self.mod = mod
        self.name = name
        self.casetype = casetype
        self.generator = generator

    def subst(self, format):  # added method
        return Template(format).substitute(self.__dict__)

    def fullname(self):
        return self.subst("$mod.$name")

    def write_cases(self, outf):
        outf.write(self.subst("const $casetype ${mod}_$name[] = {{\n"))
        for case in self.generator():
            outf.write("  { " + case + " },\n")
        outf.write("};\n\n")

import sys

def generator():
    for v in ['normal', 'extraordinary']: yield v

tb = TestBlock('somemod', 'somename', 'somecasetype', generator)

sys.stdout.write('fullname: '+tb.fullname()+'\n')
tb.write_cases(sys.stdout)

出力:

fullname: somemod.somename
const somecasetype somemod_somename[] = {{
  { normal },
  { extraordinary },
};

$name置換は、またはのいずれかを使用して、2 つの異なる方法でトリガーできることに注意してください${name}。上記の両方が使用されました。

于 2012-12-08T02:14:17.513 に答える