Python3中能否在类外实现类似@property的属性行为?
问题描述
在操作二维数组时,每次使用grid[row][column]读写值过于繁琐,希望用cell=(i,j)单变量跟踪单元格,实现如下写法并能实际更新网格对应单元格:
def value(cell): row, column = cell return grid[row][column] value(cell) += 5
已知可通过类中的@property实现,但希望无需创建外部类即可达成。当前完整代码如下:
from typing import List from itertools import product class Solution: def minPathSum(self, grid: List[List[int]]) -> int: m, n = len(grid), len(grid[0]) def cell_above(cell): row, column = cell return (row-1, column) def cell_to_the_left(cell): row, column = cell return (row, column-1) def value(cell): row, column = cell return grid[row][column] def add_value(cell, val): row, column = cell grid[row][column] += val first_row = ((0, i) for i in range(1, n)) first_column = ((j, 0) for j in range(1, m)) cells = product(range(1, m), range(1, n)) last_cell = (m-1, n-1) for cell in first_row: add_value(cell, value(cell_to_the_left(cell))) for cell in first_column: add_value(cell, value(cell_above(cell))) for cell in cells: add_value(cell, min(value(cell_above(cell)), value(cell_to_the_left(cell)))) return value(last_cell)
期望将代码后半部分改写为:
for cell in first_row: value(cell) += value(cell_to_the_left(cell)) for cell in first_column: value(cell) += value(cell_above(cell)) for cell in cells: value(cell) += min(value(cell_above(cell)), value(cell_to_the_left(cell)))
尝试过以下代码但报错:
def value_setter(cell): row, column = cell def set_value(val): grid[row][column] = val return set_value def value(cell): row, column = cell return property(lambda : grid[row][column], value_setter(cell)) for cell in first_row: val = value(cell) val += value(cell_to_the_left(cell))
错误信息:
TypeError: unsupported operand type(s) for +=: 'property' and 'property'
val += value(cell_to_the_left(cell))
Line 34 in minPathSum (Solution.py)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ret = Solution().minPathSum(param_1)
Line 59 in _driver (Solution.py)
_driver()
Line 70 in(Solution.py)
请问能否用内置property函数或其他功能实现预期行为?
可行方案
property是为类属性设计的,直接返回property对象无法支持+=这类操作,因为它不是数值类型。可以通过定义一个轻量的内部代理类来实现需求,无需创建外部类:
实现代码
修改minPathSum函数,添加内部代理类并替换原有读写逻辑:
from typing import List from itertools import product class Solution: def minPathSum(self, grid: List[List[int]]) -> int: m, n = len(grid), len(grid[0]) def cell_above(cell): row, column = cell return (row-1, column) def cell_to_the_left(cell): row, column = cell return (row, column-1) # 内部代理类,支持原地操作和数值转换 class _CellProxy: def __init__(self, grid, row, col): self.grid = grid self.row = row self.col = col def __iadd__(self, other): # 处理 += 操作,兼容代理对象和普通数值 if isinstance(other, _CellProxy): self.grid[self.row][self.col] += other.grid[other.row][other.col] else: self.grid[self.row][self.col] += other return self # 支持转换为数值,适配min等函数 def __int__(self): return self.grid[self.row][self.col] def __float__(self): return float(self.grid[self.row][self.col]) def __repr__(self): return str(self.grid[self.row][self.col]) def value(cell): row, col = cell return _CellProxy(grid, row, col) first_row = ((0, i) for i in range(1, n)) first_column = ((j, 0) for j in range(1, m)) cells = product(range(1, m), range(1, n)) last_cell = (m-1, n-1) # 直接使用期望的简洁写法 for cell in first_row: value(cell) += value(cell_to_the_left(cell)) for cell in first_column: value(cell) += value(cell_above(cell)) for cell in cells: value(cell) += min(value(cell_above(cell)), value(cell_to_the_left(cell))) # 转换为数值返回结果 return int(value(last_cell))
原理说明
_CellProxy类封装了对网格单元格的引用,通过实现__iadd__方法支持+=操作,直接修改原网格中的值。- 实现
__int__和__float__方法,确保value(cell)可以被当作普通数值参与min等函数的计算。 value函数接收cell参数后返回对应代理实例,从而实现简洁的读写语法。
扩展提示
如果需要支持更多运算符(如-=、*=),只需在_CellProxy类中实现对应的魔术方法(__isub__、__imul__等)即可。
内容的提问来源于stack exchange,提问作者mookie320
相关产品推荐
相关产品推荐

