从python中的函数返回左值

时间:2012-04-01 14:25:42

标签: python

[抱歉,我是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

然后,从课外我想:

board = ChessBoard()
board.square(0,0) = Piece( Shapes.ROOK, Colors.White )    <-- I'm getting an error here
board.square(0,1) = Piece( Shapes.BISHOP, Colors.White )
... etc.

所以,我希望函数'at'返回一个左值(类似于C ++中的引用),但是我找不到类似于语言中的引用或指针的东西。如果我在包含一个棋子的每个方格中存储列表,我可以做类似的事情:board.square(0,0)[0] = Piece - 但它似乎很疯狂(或者可能不是 - 正如我所说,我是语言的新手。)

您将如何处理此数据结构?

4 个答案:

答案 0 :(得分:9)

在Python中,所有是一个参考。唯一的问题是None 不可变,因此您无法使用返回的引用来更改值。

您也无法覆盖赋值运算符,因此您不会遇到这种特殊行为。但是,一个好的,非常灵活的解决方案是覆盖__setitem____getitem__方法来为类实现订阅运算符([]):

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

答案 1 :(得分:1)

正如尼克拉斯指出的那样,你无法返回一个l值。

但是,除了覆盖订阅之外,您还可以使用properties(描述符的应用程序:http://docs.python.org/howto/descriptor.html)来创建对象属性,该属性在读取或分配时运行代码。

答案 2 :(得分:1)

(不是在标题中回答你的问题,而是你的“你将如何处理这种数据结构?”问题:)对于你的数据结构,一个更加pythonic的解决方案是使用列表列表:

# 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)

答案 3 :(得分:1)

你可以尝试类似这样的事情,代价是不得不伪造[:]索引器:

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中,它只是必须是某种东西。

(从Proxies Perl6用于实现此目的的想法)