python - Python/Openpyxl 重复数据
问题描述
我正在创建一个程序,使用 python 和 openpyxl 将所有单个引号移动到一个单引号矩阵中,但是当尝试加载模型信息时,它似乎是从第一个引号重复模型。每个报价都是一个单独的 excel 文件,这让我感到困惑,因为我在获取报价信息时没有问题,即名称、日期等,但是每个报价的模型列表都是相同的,而不是从每个报价中提取模型.
数据结构:
class Model:
SKU = None
cost = None
qty = None
qty_remaining = None
class Quote:
name = None
number = None
start_date = None
end_date = None
models = []
从每个报价电子表格中获取数据的函数:
def load_quote(filename):
quote_wb = load_workbook(filename=filename, data_only=True, read_only=True)
quote_sheet = quote_wb.active
quote = Quote()
quote.number = quote_sheet['A2'].value
quote.number = quote.number[9:len(quote.number)]
quote.name = quote_sheet['A3'].value
quote.name = quote.name[14:len(quote.name)]
quote.start_date = quote_sheet['A6'].value
quote.start_date = quote.start_date[14:len(quote.start_date)]
quote.end_date = quote_sheet['A7'].value
quote.end_date = quote.end_date[12:len(quote.end_date)]
for row_vals in quote_sheet.iter_rows(min_row=12, max_row=250, min_col=1, max_col=9, values_only=True):
model = Model()
if row_vals[0] is not None:
model.SKU = row_vals[0]
model.cost = row_vals[4]
model.qty = row_vals[6]
model.qty_remaining = row_vals[8]
quote.models.append(model)
else:
continue
return quote
每个报价的格式相同,报价编号在单元格 A2 中,名称在单元格 A3 中,开始日期在单元格 A4 中,结束日期在单元格 5 中。
从第 12 行到第 250 行是这种格式的每个模型:
| 货号 | 说明 | 成本 | 原始数量 | 使用数量 | 剩余数量 |
我不需要描述或使用的数量,所以我忽略了这些。如果 quote_sheet 变量基于遍历文件夹中的每个文件而发生变化,并且它正在从每个文件中获取所有报价信息,为什么它没有从每个文件中获取模型信息?
不确定函数调用是否有帮助,但这里也是如此:
quotes = []
for file in os.listdir(os.chdir(directory)):
if file.endswith(".xlsx"):
quote = load_quote(file)
quotes.append(quote)
解决方案
Quote
和的所有属性Model
都在类级别上定义——它们是类属性。类属性在类的所有实例之间共享。
int
对于像or这样的不可变数据,这不是问题str
,因为通过编写:
q1 = Quote()
q1.name = 'quote_name'
您实际上是在运行时创建了一个绑定到实例的新实例属性 ,这允许实例在您询问其名称时避免查找类属性。name
q1
Quote.name
但是,由于Quote.models
它是一个可变数据(列表),它在所有Quote
. 如果您附加到该列表,则此就地操作将反映在该类的任何实例中。
您可以通过以下简短示例看到此行为:
class Quote:
name = None
number = None
start_date = None
end_date = None
models = []
q1 = Quote()
q2 = Quote()
q1.models.append('x')
print(q2.models) # output: ['x']
解决此问题的最简单方法是Quote.models
通过在方法中定义它来转换为适当的实例属性__init__
。通过这种方式,每个Quote
实例都使用附加到其models
属性的唯一、独立的列表来创建:
class Quote:
name = None
number = None
start_date = None
end_date = None
def __init__(self):
self.models = []
这应该足以解决您的问题,尽管为了清楚起见,我真的建议将所有类属性从适当的实例属性转换为适当的实例属性Quote
。Model
推荐阅读
- node.js - 找不到模块“aproba”
- python - 在 Pycharm 中关闭 matplotlib 图
- android - 如何仅针对 TabLayout 中的特定片段停止活动的旋转?
- angular - ngAfterViewInit 与 ngAfterContentChecked
- azure - 无法将实体添加到 Cosmos DB - 表
- tomcat - Tomcat初始化期间的Java NumberFormatException
- wpf - 如何将以下 xaml 语句转换为代码?
- angular - 如何将平铺层从 OpenStreetMap 更改为 Stamen
- c# - 使用 Selenium 在 textArea 中输入完整的 html
- php - 如何使用 php 将 2 个以上的数组插入 mysql 数据库