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${name}。两者都在上面使用。

于 2012-12-08T02:14:17.513 回答