2012-04-01 7 views
8

[残念ながら、私は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. 

、私は(C++での参照のようなもの)左辺値を返す「での」関数をしたいと思いますが、私はすることができます言語内の参照やポインタに似ているものは見つかりません。私がリストを1つのピースを含む各正方形に格納した場合、私は次のようなことをすることができます:board.square(0,0)[0] = Piece - それは狂っているかもしれません私はその言語に新しい)。

どのようにこのデータ構造にアプローチしますか?

答えて

8

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 
+0

注意。'def __setitem __(self、row_col、value)を定義する必要があります:row、col = row_col; self.squares [row * 8 + col] = value'です。 – delnan

+0

@delnan:ありがとう、残りはバージョンに依存しないので変更しました。私はこの機能を削除する選択肢が残念だと思います。 –

+0

ありがとうございます@Niklas – Uri

1

のNiklasが指摘するように、 l値を返すことはできません。

ただし、サブスクリプションのオーバーライドに加えて、properties(記述子のアプリケーション:http://docs.python.org/howto/descriptor.html)を使用して、オブジェクト属性を作成することもできます。オブジェクト属性は、コードの読み取りまたは割り当て時にコードを実行します。

+0

ここでは傍受する属性設定がないので、この特定の問題は解決しません。しかし、 'board.square(0,0).value = Piece(...)'のようなものを有効にするために使うことができます。 –

+0

@ NiklasB。だから私はコードを提供していない。 – Marcin

+1

ありがとう@Marcin – Uri

1

(タイトルにあなたの質問に答えていないが、あなたの「どのようにこのデータ構造に近づくでしょうか?」という質問:)あなたのデータ構造のためのより多くのニシキヘビソリューションリストのリストを使用して次のようになります。

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

など。それは実際に何をあなたのものに入れても問題ではありません。ただ何かでなければなりません。引数リストに開梱タプルの特殊なケースは、ノルウェーの青の道を行ってきましたので、定義が3.xの中で少し醜いであることを

(プロキシPerl6のからのアイデアは、これを行うために使用するGOT)

+0

このアイデアを入手した場所からソースを投稿できますか? – Andres

関連する問題