【问题标题】:How to format triple quoted text into a triple quoted print statement如何将三引号文本格式化为三引号打印语句
【发布时间】:2017-09-21 18:22:32
【问题描述】:

所以目前我正在开发一个基于文本的项目,其中包括乐透。问题是我想在已经有三引号的打印语句中使用三引号文本数字。基本上我想做这样的事情:

num1  = """
 ______   
/ ___  \  
\/   \  \ 
   ___) / 
  (___ (  
      ) \ 
/\___/  / 
\______/   

"""
print("""
 ______________
|             |
|             |
|             |
|     {a}     |
|             |
|             |
|             |
""".format(a=num1))

这只是一个概念,我知道这实际上不起作用。如果我尝试做这样的事情,它只会将非格式化文本推送到下一行。我应该逐行打印吗?我是否需要使用%s 而不是.format()?无论如何,我希望我清楚地传达了我的问题。

-宙斯

【问题讨论】:

  • 您是否希望它在num1 的每一行周围添加左右边框?
  • 格式化只是将一个字符串替换为另一个字符串,它不会尝试理解布局并重现它。
  • 是的,我希望在三个不同的框中有三个数字
  • 您需要编写自己的函数,将num1 拆分为行,并在| ... | 字符串中打印每一行。您必须调整它周围的空格数,以使边框全部对齐。
  • 我认为没有任何内置功能可以自动执行此操作。

标签: python python-3.x formatting


【解决方案1】:

通用解决方案:

下面的function 应该做你想做的事。它接受variable 数量的参数,其中*argprints 将它们格式化,并排放置在框中。它的工作方式是将传入的数字压缩在一起,然后为每个数字在它们之间打印行。它还会在数字上方和下方打印线条以完成方框。

def printNums(*arg):
   nums = [n.split("\n")[1:-1] for n in arg]
   print("_" * (sum([len(n[0]) for n in nums]) + len(nums) + 1))
   rows = zip(*nums)
   for r in rows:
      for n in r:
         print("|", end='')
         print(n, end='')
      print("|")
   print("_" * (sum([len(n[0]) for n in nums]) + len(nums) + 1))

用你的号码:

num1  = """
 ______   
/ ___  \  
\/   \  \ 
   ___) / 
  (___ (  
      ) \ 
/\___/  / 
\______/  
"""

我们可以用4调用function,例如:

printNums(num1, num1, num1, num1)

哪个输出:

_____________________________________________
| ______   | ______   | ______   | ______   |
|/ ___  \  |/ ___  \  |/ ___  \  |/ ___  \  |
|\/   \  \ |\/   \  \ |\/   \  \ |\/   \  \ |
|   ___) / |   ___) / |   ___) / |   ___) / |
|  (___ (  |  (___ (  |  (___ (  |  (___ (  |
|      ) \ |      ) \ |      ) \ |      ) \ |
|/\___/  / |/\___/  / |/\___/  / |/\___/  / |
|\______/  |\______/  |\______/  |\______/  |
_____________________________________________

我希望这是你想要的!当然,这里我们将重复的 ASCII 艺术用于 3 数字,如果这是您的应用程序想要的,您可以制作其他数字并适当地调用它们。 :)

希望这会有所帮助!

【讨论】:

  • @Mr.Zeus 谢谢:)
【解决方案2】:

我认为没有任何内置的 python 可以帮助您解决这个问题。我建议您只寻找一个合适的 ascii 文本库来轻松构建那种类型的 ascii 文本脚本,figlet 是现有的数百个脚本之一。

如果您想自己编写代码,我只需安装 pillow 并使用它来用我想要的形状填充自定义缓冲区,请看下面的 5 分钟示例,该示例“呈现”文本和矩形到这样的缓冲区。请注意,它没有进行越界检查,并且可能很慢……但我想您可以在此基础上开始工作:

from PIL import Image, ImageFont, ImageDraw


class AsciiBuffer():

    def __init__(self, width, height):
        self.font_size = 15
        self.font = ImageFont.truetype('arialbd.ttf', self.font_size)
        self.width = width
        self.height = height
        self.clear()

    def clear(self):
        self.buffer = [['*' for x in range(self.width)]
                       for y in range(self.height)]

    def draw_text(self, x0, y0, text):
        size = self.font.getsize(text)
        image = Image.new('1', size, 1)
        draw = ImageDraw.Draw(image)
        draw.text((0, 0), text, font=self.font)

        for y in range(size[1]):
            line = []
            for x in range(size[0]):
                if image.getpixel((x, y)):
                    self.buffer[y0 + y][x0 + x] = ' '
                else:
                    self.buffer[y0 + y][x0 + x] = '#'

    def draw_rectangle(self, x0, y0, w, h, fill=' '):
        for y in range(h):
            for x in range(w):
                self.buffer[y0 + y][x0 + x] = fill

    def render(self):
        for y in range(self.height):
            print(''.join(self.buffer[y]))

if __name__ == "__main__":
    k = 20
    ab = AsciiBuffer(k * 3 + 4, k * 3 + 4)
    n = 1
    for i in range(3):
        for j in range(3):
            x = 1 + (k + 1) * i
            y = 1 + (k + 1) * j
            ab.draw_rectangle(x, y, k, k)
            ab.draw_text(x + int(k / 4), y, str(n))
            n += 1
    ab.render()

输出:

重构:

无论如何,上面的代码有很多问题,其中之一是 AsciiBuffer 类与 PIL 耦合,当这个类应该尽可能虚拟时,例如,只绘制“文本精灵”就可以了,所以这里有一点重构,我将向您展示如何从多行字符串(例如您在问题中发布的字符串)或从 PIL 呈现的某些系统字体生成“文本精灵”:

import sys
from PIL import Image, ImageFont, ImageDraw


class SpriteGenerator():

    def __init__(self):
        pass

    def from_multiline_string(self, text, length):
        buf = []

        for l in text.splitlines():
            buf.append(list(l) + [' '] * (length - len(l)))

        return buf

    def from_pil(self, text, font_name='arialbd.ttf', font_size=15):
        font = ImageFont.truetype(font_name, font_size)
        size = font.getsize(text)
        image = Image.new('1', size, 1)
        draw = ImageDraw.Draw(image)
        draw.text((0, 0), text, font=font)
        buf = []

        for y in range(size[1]):
            line = []
            for x in range(size[0]):
                if image.getpixel((x, y)):
                    line.append(' ')
                else:
                    line.append('#')
            buf.append(line)

        return buf


class AsciiBuffer():

    def __init__(self, width, height):
        self.width = width
        self.height = height
        self.clear()

    def clear(self):
        self.buffer = [['*' for x in range(self.width)]
                       for y in range(self.height)]

    def draw_sprite(self, x0, y0, sprite):
        for y, row in enumerate((sprite)):
            for x, pixel in enumerate(row):
                self.buffer[y0 + y][x0 + x] = pixel

    def draw_rectangle(self, x0, y0, w, h, fill=' '):
        for y in range(h):
            for x in range(w):
                self.buffer[y0 + y][x0 + x] = fill

    def render(self):
        for y in range(self.height):
            print(''.join(self.buffer[y]))

if __name__ == "__main__":
    num  = """


 ______
/ ___  \\
\\/   \\  \\
   ___) /
  (___ (
      ) \\
/\\___/  /
\\______/
"""

    k = 15
    ab = AsciiBuffer(k * 3 + 4, k * 3 + 4)
    sg = SpriteGenerator()
    n = 1

    for i in range(3):
        for j in range(3):
            x = 1 + (k + 1) * i
            y = 1 + (k + 1) * j
            ab.draw_rectangle(x, y, k, k)
            if n == 3:
                ab.draw_sprite(
                    x + int(k / 4), y, sg.from_multiline_string(num, 11))
            else:
                ab.draw_sprite(
                    x + int(k / 4), y, sg.from_pil(str(n), font_size=k))
            n += 1

    ab.render()

输出:

【讨论】:

  • 这是一个非常酷的模块,感谢您花时间编写这么多代码,但我正在进行的项目将没有任何第三方模块。我希望这个答案会帮助(我相信它会)很多人。再次感谢!
猜你喜欢
  • 2015-06-19
  • 1970-01-01
  • 2018-01-12
  • 2013-07-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多