简体   繁体   English

Python:将实例变量传递给类方法

[英]Python: passing instance variable to class method

I am using xlsxwriter and I have created a class where I have created a workbook. 我正在使用xlsxwriter并且创建了一个在其中创建工作簿的类。 Then I have added 2 worksheets to it. 然后,我向其中添加了2个工作表。 Now I have written a method that's writing data to one of the worksheets, but now I would like to use it on both worksheets. 现在,我已经编写了一种将数据写入其中一个工作表的方法,但是现在我想在两个工作表中都使用它。 This is a simple example to explain the situation: 这是一个简单的示例来说明这种情况:

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)

Now I'd like to use the write_data method for both worksheets, so I thought I'd pass the worksheet as a parameter, but unfortunately it's not that simple, as I cannot pass the instance variable self.ws1 or self.ws2 . 现在,我想在两个工作表中都使用write_data方法,因此我想将工作表作为参数传递,但是不幸的是,它不是那么简单,因为我无法传递实例变量self.ws1self.ws2

So the question is: how can I do that? 所以问题是:我该怎么做?

I came up with a very nasty solution, like this: 我想出了一个非常讨厌的解决方案,例如:

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

but honestly I don't like it. 但说实话我不喜欢 Is there a proper way to do it, or is it like a completely unreasonable thing? 是否有适当的方法来做,还是完全不合理?

Instead of the if block, better use workbook.get_worksheet_by_name() method 最好使用workbook.get_worksheet_by_name()方法代替if块

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

EDIT: or you can use getattr() function, eg 编辑:或者您可以使用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

I'd do something like this: 我会做这样的事情:

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)

By using defaultdict , you don't need to explicitly keep a line count variable for each worksheet. 通过使用defaultdict ,您无需为每个工作表显式保留行数变量。 The write_data function accepts a new parameter ws so that you can set the worksheet that should be written to. write_data函数接受新参数ws以便您可以设置应写入的工作表。 Writing a row can be factored into a separate method to reduce code duplication. 可以将写一行分解为一个单独的方法,以减少代码重复。

Does this answer your question? 这回答了你的问题了吗?

Edit: 编辑:

a default value cannot access self , but you can work around this quite easily: 默认值不能访问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)

Maybe you should consider to have an extra class ExcelWorksheet , in order to put all logic related to them inside: 也许您应该考虑有一个额外的类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

This way, you can refactor your code to this: 这样,您可以将代码重构为:

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)

With vars(self), you can access any element of the object as a dictionnary. 使用vars(self),您可以作为字典访问对象的任何元素。

Then vars(self)["ws1"] is like self.ws1 and vars(self)["ws2"] is like self.ws2 然后vars(self)[“ ws1”]就像self.ws1,而vars(self)[“ ws2”]就像self.ws2

Then you just have to pass a key argument "ws1" or "ws2" in write_data. 然后,您只需要在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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM