如何将三引号文本格式化为三引号打印语句

时间:2017-09-21 18:22:32

标签: python python-3.x formatting

所以目前我正在开发一个基于文本的项目,包括一个乐透。麻烦的是我想在已经有三重引号的print语句中使用三引号文本号。基本上我想做这样的事情:

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

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

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

-Zeus

2 个答案:

答案 0 :(得分:1)

我认为没有任何python内置可以帮助你解决这个问题。我建议你只需要找一个合适的ascii文本库来构建那种类型的ascii-text脚本,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()

输出:

enter image description here

<强>重构:

在任何情况下,上面的代码都有多个问题,其中之一是类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()

输出:

enter image description here

答案 1 :(得分: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  = """
 ______   
/ ___  \  
\/   \  \ 
   ___) / 
  (___ (  
      ) \ 
/\___/  / 
\______/  
"""

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

printNums(num1, num1, num1, num1)

输出:

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

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

希望这有帮助!