在python中从函数返回左值

在python中从函数返回左值,python,Python,[对不起,我是Python新手。虽然这似乎是一个非常基本的问题,但在向听众提问之前,我做了尽职调查,试图避免真正愚蠢的问题] 我试图找出从函数返回l值的正确习惯用法。假设我有一个包含64个对象的容器,我希望能够返回对这些对象的引用 class ChessBoard: def __init__(self): self.squares = [None for x in range(64)] square( row, col ): return sel

[对不起,我是Python新手。虽然这似乎是一个非常基本的问题,但在向听众提问之前,我做了尽职调查,试图避免真正愚蠢的问题]

我试图找出从函数返回l值的正确习惯用法。假设我有一个包含64个对象的容器,我希望能够返回对这些对象的引用

class ChessBoard:
    def __init__(self):
        self.squares = [None for x in range(64)]

    square( row, col ):
        return self.squares(row*8+col)    <---- I'd like this to be l-value
类棋盘:
定义初始化(自):
self.squares=[范围(64)内x无]
正方形(行、列):
返回self.squares(row*8+col)在Python中,所有内容都是引用。唯一的问题是
None
是不可变的,因此不能使用返回的引用来更改值

您也不能重写赋值运算符,因此不会出现这种特殊的行为。但是,一个很好且非常灵活的解决方案是重写和方法来实现类的订阅运算符(
[]
):

class ChessBoard(object):
  def __init__(self):
    self.squares = [None] * 64

  def __setitem__(self, key, value):
    row, col = key
    self.squares[row*8 + col] = value

  def __getitem__(self, key):
    row, col = key
    return self.squares[row*8 + col]
用法:

>>> c = ChessBoard()
>>> c[1,2] = 5
>>> c[1,2]
5

正如Niklas指出的,不能返回l值

但是,除了覆盖订阅之外,您还可以使用(描述符的应用程序:)创建对象属性,当从中读取或分配给该属性时,该属性将运行代码。

(不是回答标题中的问题,而是回答您的“如何处理此数据结构?”问题:)对于您的数据结构,一个更具Python风格的解决方案是使用列表列表:

# define a function that generates an empty chess board
make_chess_board = lambda : [[None for x in xrange(8)] for y in xrange(8)]

# grab an instance
b = make_chess_board()

# play the game!
b[0][0] = Piece(Shapes.ROOK, Colors.White)
b[0][1] = Piece(Shapes.BISHOP, Colors.White)

# Or use tuples:
b[0][0] = (Shapes.ROOK, Colors.White)
b[0][1] = (Shapes.BISHOP, Colors.White)

您可以尝试类似的方法,但代价是必须使用伪造的[:]索引器:

class Board:
    def __init__(self):
        self.squares=[None for x in range(64)]
    def square(self, row, col):
        squares=self.squares
        class Prox:
            def __getitem__(self, i):
                return squares[row*8+col]
            def __setitem__(self, i, v):
                squares[row*8+col]=v
        return Prox()
那你就可以了

b=Board()
b.square(2,3)[:]=Piece('Knight')
if b.square(x,y)[:] == Piece('King') ...
等等。实际上,你在[s]中放了什么并不重要,它必须是某种东西


(这是从Perl6使用的代理中得到的想法)

注意,3.x中的定义有点难看,因为参数列表中元组解包的特例采用了挪威蓝色。您必须定义
def\uuuuu setitem\uuuuuuuuuuuuuuuuuuuuuuuo(self,row\u col,value):row,col=row\u col;self.squares[row*8+col]=value
@delnan:谢谢,我更改了它,因为其余的是版本无关的。我认为删除此功能的选择是不幸的,如果使用得当,它会非常有用。但这并不能解决这个特殊问题,因为这里没有要拦截的属性设置。但是,它可以用来启用类似于
board.square(0,0).value=Piece(…)
。不正确。我找到了一种使用globals()和locals()的方法。见@Logan-True。您没有找到返回左值的方法,您找到了在locals/globals字典中设置值的方法。您可以发布您从何处获得此想法的来源吗?
b=Board()
b.square(2,3)[:]=Piece('Knight')
if b.square(x,y)[:] == Piece('King') ...