python - 单个函数中的 Python 变量范围很奇怪 - 尽管每个对象都是单独实例化的,但所有实例共享相同的对象
问题描述
我正在制作一些将普通表行解析为分层数据结构的函数。
有两个数据类 - ProductInfo :单品,如 T 恤 - OptionInfo :单品选项,如'yellow-XXL'、'blue-XL'
这些都写在单个 xl 表中。像 ProductInfo 头,它作为 ProdctOption 的尾行。所以我决定像某种状态机一样解析它。
如果 row 是 Single Product,则创建 ProductInfo 的新实例并使用空 List 初始化 ProductInfo.options。
如果已经遇到 Product(head) 并且当前行是 Option,则推入实例化 ProductInfo 的列表。
如果再次遇到 Product,则追加 ProductInfo int reulstList
但最终的结果真的很奇怪。所有 ProductInfo 共享它的选项,如果 10 个产品有 100 个选项,则每个产品包含 100 个选项,尽管其中大多数不是它的选项。
它看起来像下面,
- 产品 T 恤 -> [('white', 'XL'), ('red', 'XL'), ('rainbow', '270'), ('yellow', '260')]
- Product Sneakers -> [('white', 'XL'), ('red', 'XL'), ('rainbow', '270'), ('yellow', '260')] (如你所见, 前 2 个选项是 T 恤,后 2 个选项是运动鞋)
数据类看起来像这样
class OptionInfo:
def __init__(self, ProductId: int = None, ProductCode: str = None, Barcode: str = None, Color: str = None, Size: str = None, OptionDescription:str = None):
self.ProductId = ProductId
self.ProductCode = ProductCode
self.Barcode = Barcode
self.Color = Color
self.Size = Size
self.OptionDescription = OptionDescription
class ProductInfo:
def __init__(self, ProductId = None, ProductBaseCode: str = None, ProductBaseBarcode: str = None, HasOption: bool = False, MajorCategory: str = None, MiddleCategory: str = None, MinorCategory: str = None, Gender: str = None, Supplier: str = None, OriginCountry: str = None, ProductName: str = None, TemporaryProductionPrice: float = None, SalesPrice: float = None, OptionList: List['OptionInfo'] = [], PredefinedCategory: str = None):
self.ProductId = ProductId
self.ProductBaseCode = ProductBaseCode
self.ProductBaseBarcode = ProductBaseBarcode
self.HasOption = HasOption
self.MajorCategory = MajorCategory
self.MiddleCategory = MiddleCategory
self.MinorCategory = MinorCategory
self.Gender = Gender
self.Supplier = Supplier
self.OriginCountry = OriginCountry
self.ProductName = ProductName
self.TemporaryProductionPrice = TemporaryProductionPrice
self.SalesPrice = SalesPrice
self.OptionList = OptionList
self.PredefinedCategory = PredefinedCategory
逻辑代码如下
def parseSheet(xlPath: str) -> List['ProductInfo']:
log('PRODUCT >> Parsing xl for {}'.format(xlPath))
wb = openpyxl.load_workbook(xlPath)
ws = wb.active
resultSet: List['ProductInfo'] = []
prInfo: ProductInfo = None
allowOptions: bool = False
for rownum in range(2, ws.max_row+1):
if ws.cell(row=rownum, column=CL_ProductName).value == '' or ws.cell(row=rownum, column=CL_ProductName).value is None: break
isRepr = ws.cell(row=rownum, column=CL_IsRepr).value
if isRepr is 1 or isRepr == '1':
if prInfo is not None:
resultSet.append(prInfo)
prInfo = None
allowOptions = False
allowOptions = True
prInfo = ProductInfo(
ProductBaseCode =ws.cell(row=rownum, column=CL_ProductCode).value if ws.cell(row=rownum, column=CL_ProductCode).value != '' else None,
HasOption =True,
ProductName =ws.cell(row=rownum, column=CL_ProductName).value if ws.cell(row=rownum, column=CL_ProductName).value != '' else None,
TemporaryProductionPrice=float(ws.cell(row=rownum, column=CL_ProdPrice).value) if ws.cell(row=rownum, column=CL_ProdPrice).value != '' and ws.cell(row=rownum, column=CL_ProdPrice).value is not None else 0,
SalesPrice =float(ws.cell(row=rownum, column=CL_SalesPrice).value) if ws.cell(row=rownum, column=CL_SalesPrice).value != '' and ws.cell(row=rownum, column=CL_SalesPrice).value is not None else 0,
PredefinedCategory =ws.cell(row=rownum, column=CL_PredCategory).value if ws.cell(row=rownum, column=CL_PredCategory).value != '' else None
)
elif isRepr == 'isOption':
if allowOptions is False or prInfo is None:
raise Exception('Sheet row order seems strange, check please near {}'.format(rownum))
prInfo.OptionList.append(
OptionInfo(
ProductCode =ws.cell(row=rownum, column=CL_ProductCode).value if ws.cell(row=rownum, column=CL_ProductCode).value != '' else None,
Barcode =ws.cell(row=rownum, column=CL_Barcode).value if ws.cell(row=rownum, column=CL_Barcode).value != '' else None,
OptionDescription =ws.cell(row=rownum, column=CL_OptionDesc).value if ws.cell(row=rownum, column=CL_OptionDesc).value != '' else None
)
)
elif isRepr is 0 or isRepr == '0':
if prInfo is not None:
resultSet.append(prInfo)
prInfo = None
allowOptions = False
prInfo = ProductInfo(
ProductBaseCode =ws.cell(row=rownum, column=CL_ProductCode).value if ws.cell(row=rownum, column=CL_ProductCode).value != '' else None,
HasOption =False,
ProductName =ws.cell(row=rownum, column=CL_ProductName).value if ws.cell(row=rownum, column=CL_ProductName).value != '' else None,
TemporaryProductionPrice=float(ws.cell(row=rownum, column=CL_ProdPrice).value) if ws.cell(row=rownum, column=CL_ProdPrice).value != '' and ws.cell(row=rownum, column=CL_ProdPrice).value is not None else 0,
SalesPrice =float(ws.cell(row=rownum, column=CL_SalesPrice).value) if ws.cell(row=rownum, column=CL_SalesPrice).value != '' and ws.cell(row=rownum, column=CL_SalesPrice).value is not None else 0,
PredefinedCategory =ws.cell(row=rownum, column=CL_PredCategory).value if ws.cell(row=rownum, column=CL_PredCategory).value != '' else None,
OptionList=[OptionInfo(
ProductCode =ws.cell(row=rownum, column=CL_ProductCode).value if ws.cell(row=rownum, column=CL_ProductCode).value != '' else None,
Barcode =ws.cell(row=rownum, column=CL_Barcode).value if ws.cell(row=rownum, column=CL_Barcode).value != '' else None,
OptionDescription =ws.cell(row=rownum, column=CL_OptionDesc).value if ws.cell(row=rownum, column=CL_OptionDesc).value != '' else None
)]
)
else:
raise Exception('Invalid repr in sheet {} at {}'.format(isRepr, rownum))
return resultSet
值isRepr
决定是Product还是Option,1表示是Product,'isOption'表示是上层Product的option(isRepr为1),0表示是没有option的Product。
我认为,prInfo
被怀疑为原因。但我不明白它的可变范围。如何区分变量声明和分配给变量?可能吗?我该如何解决这个问题。我怀疑原因,但不确定为什么会发生。
解决方案
推荐阅读
- c - 我编写了一个 C 程序,它在编译时嵌入了自己的源代码,并在运行时显示它。这算不算奎因?
- android - 仅在特定片段上打开键盘时移动布局(WebView)
- r - magrittr 管道中的 WOE
- java - 错误:即使它是公共变量也找不到符号?
- typescript - 如何使一组装饰器在 Typescript 中易于重用
- python - Python套接字从CSV问题扫描多个IP
- python - 预测后如何生成准确的掩码
- powershell - Powershell:Export-Excel 不导出数据行,仅导出标题
- python - 多列文本文件到字典
- javascript - 尝试将 Google Analytics 添加到 Chrome 扩展程序