2012-04-01 14 views
8

[Niestety, jestem nowy w Pythonie. Chociaż wydaje się to być bardzo podstawowym pytaniem, zrobiłem swój udział w należytej staranności, zanim zapytałem tę publiczność, starając się uniknąć naprawdę głupich pytań].Zwracanie wartości l z funkcji w pytonie

Próbuję znaleźć prawidłowy idiom dla zwracania wartości l z funkcji. Załóżmy, że mam kontener z 64 obiektami i chcę mieć możliwość zwrócenia odwołania do tych obiektów.

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 

Następnie spoza klasy chcę:

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. 

Więc chciałbym funkcję „at”, aby powrócić do lwartość (coś jak odniesienie w C++), ale mogę w tekście znajduje się coś przypominającego odnośnik lub wskaźnik. Jeśli zapisałem listę w każdym kwadracie zawierającym jeden element, możliwe jest, że mógłbym zrobić coś takiego: board.square (0,0) [0] = Piece - ale wydaje się szalone (a może nie - tak jak powiedziałem, Jestem nowy w tym języku).

Jak podchodzisz do tej struktury danych?

Odpowiedz

8

W języku Python, wszystko, co jest odnośnikiem. Jedynym problemem jest to, że None jest niezmienna , więc nie możesz użyć zwróconego odwołania do zmiany wartości.

Nie można również przesłonić operatora przypisania, więc nie uzyskasz tego konkretnego zachowania. Jednakże, dobre i bardzo elastyczne rozwiązanie byłoby zastąpić metody __setitem__ i __getitem__ do realizacji operator odbiorczych ([]) dla klasy:

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] 

Zastosowanie:

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

Należy zauważyć, że definicja jest nieco bardziej brzydkie w 3.x, ponieważ szczególny przypadek krotki rozpakowaniu na listach argumentów poszedł drogą Norweskiego błękitu.Będziesz musiał zdefiniować 'def __setitem __ (self, row_col, value): row, col = row_col; self.squares [wiersz * 8 + col] = wartość'. – delnan

+0

@delnan: Dzięki, zmieniłem to, ponieważ reszta jest niezależna od wersji. Myślę, że wybór usunięcia tej funkcji jest niefortunny, może być bardzo przydatny, jeśli jest używany w sposób rozsądny. –

+0

Dziękuję @Niklas – Uri

1

jako Niklas wskazuje nie możesz zwrócić wartości l.

Jednak oprócz przesłonięcia subskrypcji można również użyć opcji properties (aplikacja deskryptorów: http://docs.python.org/howto/descriptor.html) w celu utworzenia atrybutu obiektu, który podczas odczytu lub przypisania uruchamia kod.

+0

To jednak nie rozwiązuje tego konkretnego problemu, ponieważ nie ma tutaj ustawienia atrybutu. Można go jednak użyć do włączenia czegoś takiego jak: board.square (0,0) .value = Piece (...) '. –

+0

@NiklasB. Dlatego nie oferuję żadnego kodu. – Marcin

+1

Dziękuję @Marcin – Uri

1

(nie odpowiadając na pytanie w tytule, ale twój „Jak można podejść do tego struktury danych?” Pytanie :) Bardziej pythonic rozwiązanie dla struktury danych będzie na podstawie listy zawierającej list:

# 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

można spróbować czegoś takiego, kosztem konieczności wprowadzenia fałszywego [:] indeksujący okolicy:

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

Następnie można zrobić

b=Board() 
b.square(2,3)[:]=Piece('Knight') 
if b.square(x,y)[:] == Piece('King') ... 

I tak dalej. Nie ma znaczenia, co umieścisz w [] s, to po prostu musi być coś.

(wpadł na pomysł z prokurentów Perl6 wykorzystuje to zrobić)

+0

Czy możesz podać źródło, skąd wziąłeś ten pomysł? – Andres

Powiązane problemy