Python:将实例变量传递给class方法
Python: passing instance variable to class method
我正在使用 xlsxwriter
并且我创建了一个 class 并在其中创建了一个工作簿。然后我向其中添加了 2 个工作表。
现在我已经编写了一种将数据写入其中一个工作表的方法,但现在我想在两个工作表上都使用它。这是一个简单的例子来说明情况:
import xlsxwriter
class ExcelWorkbook():
def __init__(self, filename):
self.wb = xlsxwriter.Workbook(filename)
self.ws1 = self.wb.add_worksheet('Num')
self.ws1LineCount = 0
self.ws2 = self.wb.add_worksheet('Result')
self.ws2LineCount = 0
def write_data(self, data, title):
self.ws1.write_row(self.ws1LineCount, 0, title)
self.ws1LineCount += 1
self.ws1.write_row(self.ws1LineCount, 0, data)
self.ws1LineCount += 1
xlsxWorkbook = ExcelWorkbook('Test2.xlsx')
numArr = (0.000000520593523979187, 13.123456789, 1.789456, 0.002345, 0.00123, 1)
titleBar = ('Date', 'quantity', 'Average [m]', 'Standard Dev [m]', 'Test', 'Success')
xlsxWorkbook.write_data(numArr, titleBar)
现在我想对两个工作表都使用 write_data
方法,所以我想我应该将工作表作为参数传递,但不幸的是,它并没有那么简单,因为我无法传递实例变量self.ws1
或 self.ws2
.
所以问题是:我该怎么做?
我想到了一个非常糟糕的解决方案,像这样:
def write_data(self, data, title, instance = 'ws1'):
if instance == 'ws1':
instance = self.ws1
lineCounter = self.ws1LineCount
elif instance == 'ws2':
instance = self.ws2
lineCounter = self.ws2LineCount
instance.write_row(self.ws1LineCount, 0, title)
lineCounter += 1
instance.write_row(self.ws1LineCount, 0, data)
lineCounter += 1
但老实说我不喜欢它。有什么正确的做法吗,还是完全不合理的事情?
使用 vars(self),您可以将对象的任何元素作为字典访问。
那么 vars(self)["ws1"] 就像 self.ws1 而 vars(self)["ws2"] 就像 self.ws2
然后你只需要在 write_data.
中传递一个关键参数 "ws1" 或 "ws2"
def write_data(self, data, title, key='ws1'):
instance = vars(self)[key]
lineCounter = vars(self)[key+"LineCount"]
instance.write_row(lineCounter , 0, title)
lineCounter += 1
instance.write_row(lineCounter , 0, data)
lineCounter += 1
我会这样做:
from collections import defaultdict
import xlsxwriter
class ExcelWorkbook():
def __init__(self, filename):
self.wb = xlsxwriter.Workbook(filename)
self.ws1 = self.wb.add_worksheet('Num')
self.ws2 = self.wb.add_worksheet('Result')
self._line_counts = defaultdict(int)
def write_data(self, ws, data, title):
self._write_row(ws, title)
self._write_row(ws, data)
def _write_row(self, ws, content):
ws.write_row(self._line_counts[ws], 0, content)
self._line_counts[ws] += 1
xlsxWorkbook = ExcelWorkbook('Test2.xlsx')
numArr = (0.000000520593523979187, 13.123456789, 1.789456, 0.002345, 0.00123, 1)
titleBar = ('Date', 'quantity', 'Average [m]', 'Standard Dev [m]', 'Test', 'Success')
xlsxWorkbook.write_data(xlsxWorkbook.ws1, numArr, titleBar)
xlsxWorkbook.write_data(xlsxWorkbook.ws2, numArr, titleBar)
通过使用 defaultdict
,您无需为每个工作表显式保留行数变量。 write_data
函数接受一个新参数 ws
以便您可以设置应写入的工作表。写一行可以分解成一个单独的方法来减少代码重复。
这是否回答了您的问题?
编辑:
默认值无法访问 self
,但您可以很容易地解决此问题:
def write_data(self, data, title, ws=None):
if ws is None:
ws = self.ws1
self._write_row(ws, title)
self._write_row(ws, data)
而不是 if 块,最好使用 workbook.get_worksheet_by_name()
方法
def write_data(self, data, title, ws = 'Num'):
wsheet = self.wb.get_worksheet_by_name(ws)
wsheet.write_row(self.ws1LineCount, 0, title)
lineCounter += 1
wsheet.write_row(self.ws1LineCount, 0, data)
lineCounter += 1
编辑:或者您可以使用 getattr() 函数,例如
def write_data(self, data, title, ws = 'ws1'):
wsheet = getattr(self, ws, self.ws1))
wsheet.write_row(self.ws1LineCount, 0, title)
lineCounter += 1
wsheet.write_row(self.ws1LineCount, 0, data)
lineCounter += 1
也许你应该考虑多一个class ExcelWorksheet
,以便将所有相关的逻辑放在里面:
class ExcelWorksheet(object):
def __init__(self, workbook, name):
self.wb = workbook
self.ws = self.wb.add_worksheet(name)
self.wsLineCount = 0
def write_data(self, data, title):
self.ws.write_row(self.wsLineCount, 0, title)
self.wsLineCount += 1
self.ws.write_row(self.wsLineCount, 0, data)
self.wsLineCount += 1
这样,您可以将代码重构为:
class ExcelWorkbook(object):
def __init__(self, filename):
self.wb = xlsxwriter.Workbook(filename)
self.ws1 = ExcelWorksheet(self.wb, 'Num')
self.ws2 = ExcelWorksheet(self.wb, 'Result')
xlsxWorkbook = ExcelWorkbook('Test2.xlsx')
numArr = (0.000000520593523979187, 13.123456789, 1.789456, 0.002345, 0.00123, 1)
titleBar = ('Date', 'quantity', 'Average [m]', 'Standard Dev [m]', 'Test', 'Success')
xlsxWorkbook.ws1.write_data(numArr, titleBar)
xlsxWorkbook.ws2.write_data(numArr, titleBar)
我正在使用 xlsxwriter
并且我创建了一个 class 并在其中创建了一个工作簿。然后我向其中添加了 2 个工作表。
现在我已经编写了一种将数据写入其中一个工作表的方法,但现在我想在两个工作表上都使用它。这是一个简单的例子来说明情况:
import xlsxwriter
class ExcelWorkbook():
def __init__(self, filename):
self.wb = xlsxwriter.Workbook(filename)
self.ws1 = self.wb.add_worksheet('Num')
self.ws1LineCount = 0
self.ws2 = self.wb.add_worksheet('Result')
self.ws2LineCount = 0
def write_data(self, data, title):
self.ws1.write_row(self.ws1LineCount, 0, title)
self.ws1LineCount += 1
self.ws1.write_row(self.ws1LineCount, 0, data)
self.ws1LineCount += 1
xlsxWorkbook = ExcelWorkbook('Test2.xlsx')
numArr = (0.000000520593523979187, 13.123456789, 1.789456, 0.002345, 0.00123, 1)
titleBar = ('Date', 'quantity', 'Average [m]', 'Standard Dev [m]', 'Test', 'Success')
xlsxWorkbook.write_data(numArr, titleBar)
现在我想对两个工作表都使用 write_data
方法,所以我想我应该将工作表作为参数传递,但不幸的是,它并没有那么简单,因为我无法传递实例变量self.ws1
或 self.ws2
.
所以问题是:我该怎么做?
我想到了一个非常糟糕的解决方案,像这样:
def write_data(self, data, title, instance = 'ws1'):
if instance == 'ws1':
instance = self.ws1
lineCounter = self.ws1LineCount
elif instance == 'ws2':
instance = self.ws2
lineCounter = self.ws2LineCount
instance.write_row(self.ws1LineCount, 0, title)
lineCounter += 1
instance.write_row(self.ws1LineCount, 0, data)
lineCounter += 1
但老实说我不喜欢它。有什么正确的做法吗,还是完全不合理的事情?
使用 vars(self),您可以将对象的任何元素作为字典访问。
那么 vars(self)["ws1"] 就像 self.ws1 而 vars(self)["ws2"] 就像 self.ws2
然后你只需要在 write_data.
中传递一个关键参数 "ws1" 或 "ws2"def write_data(self, data, title, key='ws1'):
instance = vars(self)[key]
lineCounter = vars(self)[key+"LineCount"]
instance.write_row(lineCounter , 0, title)
lineCounter += 1
instance.write_row(lineCounter , 0, data)
lineCounter += 1
我会这样做:
from collections import defaultdict
import xlsxwriter
class ExcelWorkbook():
def __init__(self, filename):
self.wb = xlsxwriter.Workbook(filename)
self.ws1 = self.wb.add_worksheet('Num')
self.ws2 = self.wb.add_worksheet('Result')
self._line_counts = defaultdict(int)
def write_data(self, ws, data, title):
self._write_row(ws, title)
self._write_row(ws, data)
def _write_row(self, ws, content):
ws.write_row(self._line_counts[ws], 0, content)
self._line_counts[ws] += 1
xlsxWorkbook = ExcelWorkbook('Test2.xlsx')
numArr = (0.000000520593523979187, 13.123456789, 1.789456, 0.002345, 0.00123, 1)
titleBar = ('Date', 'quantity', 'Average [m]', 'Standard Dev [m]', 'Test', 'Success')
xlsxWorkbook.write_data(xlsxWorkbook.ws1, numArr, titleBar)
xlsxWorkbook.write_data(xlsxWorkbook.ws2, numArr, titleBar)
通过使用 defaultdict
,您无需为每个工作表显式保留行数变量。 write_data
函数接受一个新参数 ws
以便您可以设置应写入的工作表。写一行可以分解成一个单独的方法来减少代码重复。
这是否回答了您的问题?
编辑:
默认值无法访问 self
,但您可以很容易地解决此问题:
def write_data(self, data, title, ws=None):
if ws is None:
ws = self.ws1
self._write_row(ws, title)
self._write_row(ws, data)
而不是 if 块,最好使用 workbook.get_worksheet_by_name()
方法
def write_data(self, data, title, ws = 'Num'):
wsheet = self.wb.get_worksheet_by_name(ws)
wsheet.write_row(self.ws1LineCount, 0, title)
lineCounter += 1
wsheet.write_row(self.ws1LineCount, 0, data)
lineCounter += 1
编辑:或者您可以使用 getattr() 函数,例如
def write_data(self, data, title, ws = 'ws1'):
wsheet = getattr(self, ws, self.ws1))
wsheet.write_row(self.ws1LineCount, 0, title)
lineCounter += 1
wsheet.write_row(self.ws1LineCount, 0, data)
lineCounter += 1
也许你应该考虑多一个class ExcelWorksheet
,以便将所有相关的逻辑放在里面:
class ExcelWorksheet(object):
def __init__(self, workbook, name):
self.wb = workbook
self.ws = self.wb.add_worksheet(name)
self.wsLineCount = 0
def write_data(self, data, title):
self.ws.write_row(self.wsLineCount, 0, title)
self.wsLineCount += 1
self.ws.write_row(self.wsLineCount, 0, data)
self.wsLineCount += 1
这样,您可以将代码重构为:
class ExcelWorkbook(object):
def __init__(self, filename):
self.wb = xlsxwriter.Workbook(filename)
self.ws1 = ExcelWorksheet(self.wb, 'Num')
self.ws2 = ExcelWorksheet(self.wb, 'Result')
xlsxWorkbook = ExcelWorkbook('Test2.xlsx')
numArr = (0.000000520593523979187, 13.123456789, 1.789456, 0.002345, 0.00123, 1)
titleBar = ('Date', 'quantity', 'Average [m]', 'Standard Dev [m]', 'Test', 'Success')
xlsxWorkbook.ws1.write_data(numArr, titleBar)
xlsxWorkbook.ws2.write_data(numArr, titleBar)