我正在尝试创建一个简单的Python表类,它接受列表作为内容列表,然后构建一个可以打印到终端的表字符串表示。我想要的一个功能是在表格的单元格中包装文本。
我很高兴使用模块textwrap
来确定适当的文本换行。
基本上,对于以下内容
[
["heading 1", "heading 2"],
["some text", "some more text"],
["lots and lots and lots and lots and lots of text", "some more text"]
]
我想要生成的表示形式如下:
-------------------------------
|heading 1 |heading 2 |
-------------------------------
|some text |some more text|
-------------------------------
|lots and lots |some more text|
|and lots and | |
|lots and lots | |
|of text | |
-------------------------------
我的问题是:如果由textwrap
确定的文本换行的列表表示,我如何实现多行单元格?
我的代码如下:
import textwrap
import subprocess
def terminalWidth():
return(
int(
subprocess.Popen(
["tput", "cols"],
stdout = subprocess.PIPE
).communicate()[0].decode("utf-8").strip("\n")
)
)
class Table(object):
def __init__(
self,
content = None,
widthTable = None,
columnDelimiter = "|",
rowDelimiter = "-"
):
self.content = content
if widthTable is None:
self.widthTable = terminalWidth()
self.columnDelimiter = columnDelimiter
self.rowDelimiter = rowDelimiter
def value(self):
self.numberOfColumns = len(self.content[0])
self.widthOfColumns =\
self.widthTable / self.numberOfColumns -\
self.numberOfColumns * len(self.columnDelimiter)
self.tableString = ""
for row in self.content:
for column in row:
self.tableString =\
self.tableString +\
self.columnDelimiter +\
textwrap.wrap(column, self.widthOfColumns)
self.tableString =\
self.tableString +\
self.columnDelimiter +\
"\n" +\
self.widthTable * self.rowDelimiter +\
"\n" +\
return(self.tableString)
def __str__(self):
return(self.value())
def main():
table1Content = [
["heading 1", "heading 2"],
["some text", "some more text"],
["lots and lots and lots and lots and lots of text", "some more text"]
]
table1 = Table(
content = table1Content,
widthTable = 15
)
print(table1)
if __name__ == '__main__':
main()
答案 0 :(得分:2)
这是一个完成你想要的课程:
import textwrap
class Table:
def __init__(self,
contents,
wrap,
wrapAtWordEnd = True,
colDelim = "|",
rowDelim = "-"):
self.contents = contents
self.wrap = wrap
self.colDelim = colDelim
self.wrapAtWordEnd = wrapAtWordEnd
# Extra rowDelim characters where colDelim characters are
p = len(self.colDelim) * (len(self.contents[0]) - 1)
# Line gets too long for one concatenation
self.rowDelim = self.colDelim
self.rowDelim += rowDelim * (self.wrap * max([len(i) for i in self.contents]) + p)
self.rowDelim += self.colDelim + "\n"
def withoutTextWrap(self):
string = self.rowDelim
for row in self.contents:
maxWrap = (max([len(i) for i in row]) // self.wrap) + 1
for r in range(maxWrap):
string += self.colDelim
for column in row:
start = r * self.wrap
end = (r + 1) * self.wrap
string += column[start : end].ljust(self.wrap)
string += self.colDelim
string += "\n"
string += self.rowDelim
return string
def withTextWrap(self):
print(self.wrap)
string = self.rowDelim
# Restructure to get textwrap.wrap output for each cell
l = [[textwrap.wrap(col, self.wrap) for col in row] for row in self.contents]
for row in l:
for n in range(max([len(i) for i in row])):
string += self.colDelim
for col in row:
if n < len(col):
string += col[n].ljust(self.wrap)
else:
string += " " * self.wrap
string += self.colDelim
string += "\n"
string += self.rowDelim
return string
def __str__(self):
if self.wrapAtWordEnd:
return self.withTextWrap()
else:
return self.withoutTextWrap()
if __name__ == "__main__":
l = [["heading 1", "heading 2", "asdf"],
["some text", "some more text", "Lorem ipsum dolor sit amet."],
["lots and lots and lots and lots and lots of text", "some more text", "foo"]]
table = Table(l, 20, True)
print(table)
withTextWrap()
使用您提到的textwrap
模块,并使用其输出来构建表格表示。在玩这个的同时,我还想出了一种方法(几乎),你可以在textwrap
方法中看到withoutTextWrap()
模块。我说“差不多”,因为textwrap
模块在一个单词的末尾正确地打破了行,而我的方法在包装点直接打破了字符串。
因此,如果您创建第三个构造函数参数设置为True
的表,则使用textwrap
模块,该模块将生成此输出:
|--------------------------------------------------------------|
|heading 1 |heading 2 |asdf |
|--------------------------------------------------------------|
|some text |some more text |Lorem ipsum dolor |
| | |sit amet. |
|--------------------------------------------------------------|
|lots and lots and |some more text |foo |
|lots and lots and | | |
|lots of text | | |
|--------------------------------------------------------------|
如果该参数为False
,则会调用非textwrap
版本:
|--------------------------------------------------------------|
|heading 1 |heading 2 |asdf |
|--------------------------------------------------------------|
|some text |some more text |Lorem ipsum dolor si|
| | |t amet. |
|--------------------------------------------------------------|
|lots and lots and lo|some more text |foo |
|ts and lots and lots| | |
| of text | | |
|--------------------------------------------------------------|
希望这有帮助。