简体   繁体   中英

Python: Appending to an instance attribute from inside a function

I am trying to write a basic card game for fun, but trying to make as much of it as possible applicable to future card games.Here is my code.

decks = [  ]
players = [  ]

class Player:
global players
def __init__( self, name ):
    self.hand = [  ]
    self.name = ''
    self.score = 0
    self.name = 'playerX'
    self.score = 0
    players.append( name )


class Deck:
    global decks
    global players

def __init__( self, name ):
    self.SUITS = [ 'C', 'D', 'H', 'S' ]
    self.RANKS = [ '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A' ]
    self.deck = [  ]
    for r in self.RANKS:
        for s in self.SUITS:
            self.deck.append( ( r, s ) )
    decks.append( name )

def shuffle( self ):
    shuffle( self.deck )

def display( self ):
    for e in range(0, len( self.deck ), 4):
        for i in self.deck[e:e+4]:
            print i,
        print

def dealXtoOne( number, deck, player ):
    ''' number of cards from a deck to named player'''
    if len( deck.deck ) >= number:
        for n in range( 0, number ):
            player.hand.append( deck.deck.pop(  ) )
            print 'Player1 hand: ', p1.hand
    else:
        return 'Insufficient cards in the deck.'

def dealXtoEach( number, deck ):
    ''' number of cards from a deck to each player'''
    global players
    print 'debug 0'
    if len( deck.deck ) >= number*len( players ):
        print 'debug 1'
        for cards in range( 0, number*len( players ) ):
            print 'debug 2'
            for player in players:
                print 'debug 3'
                print player
                print player.hand
                player.hand.append( deck.deck.pop(  ) )
                print player.hand
    else:
        return 'Insufficient cards in the deck.'



def value( card ):
    if card[ 0 ] == 'J': return 11
        elif card[ 0 ] == 'Q': return 12
        elif card[ 0 ] == 'K': return 13
        elif card[ 0 ] == 'A': return 14
        else: return card[ 0 ]

def topCard( deck ):
    return deck.deck[ -1 ]

def color( card ):
    if card[ 1 ] in [ 'Diamonds', 'Hearts' ]:
        return 'Red'
    else:
        return 'Black'


p1 = Player( 'p1' )
p2 = Player( 'p2' )
d = Deck( 'd' )

d.display(  )
print p1.hand
dealXtoOne( 3, d, p1 )
d.display(  )
print p1.hand
dealXtoEach( 3, d )
d.display(  )

I'm sure it's garbage, and it's clearly a work in progress, but I am teaching myself to program. Sorry if your eyes bleed!

So dealing X cards to one player works fine, but dealing X cards to N players each is not working. Here is my output:

('2', 'C') ('2', 'D') ('2', 'H') ('2', 'S')
('3', 'C') ('3', 'D') ('3', 'H') ('3', 'S')
...
('K', 'C') ('K', 'D') ('K', 'H') ('K', 'S')
('A', 'C') ('A', 'D') ('A', 'H') ('A', 'S')
[]
Player1 hand:  [('A', 'S')]
Player1 hand:  [('A', 'S'), ('A', 'H')]
Player1 hand:  [('A', 'S'), ('A', 'H'), ('A', 'D')]
('2', 'C') ('2', 'D') ('2', 'H') ('2', 'S')
...
('K', 'C') ('K', 'D') ('K', 'H') ('K', 'S')
('A', 'C')
[('A', 'S'), ('A', 'H'), ('A', 'D')]
debug 0
debug 1
debug 2
debug 3
p1

Traceback (most recent call last):
    File "C:\Users\11583\Desktop\Personal\cardgame.py", line 94, in <module>
        dealXtoEach( 3, d )
    File "C:\Users\11583\Desktop\Personal\cardgame.py", line 60, in dealXtoEach
        print player.hand
AttributeError: 'str' object has no attribute 'hand'

I can tell that it doesn't like that I am trying to append a tuple to the reference inside the dealXtoEach function of the instance of Player represented by the string in the players global variable. Sheesh, I am confused just explaining it.

So how can I get around this?

Thanks

That error has nothing to do with appending to a tuple (and by the way, players is a list not a tuple- it's impossible to append to a tuple).

Instead, try replacing the line:

players.append( name )

with

players.append( self )

This way, the global players list won't contain a list of strings (which you can't use for much), it will contain a list of Player objects (which have, among other things, a hand attribute).


An extra note: a global players list isn't really necessary (and global variables are usually recommended against)- you could just pass around the players list. Secondly, dealXToOne and dealOneToEach should really be methods of the Deck class. Together, that would make the last few lines look something like:

players = [p1, p2]
d.dealXToOne(3, p1)
d.dealXToEach(e, players)

Each player in your players list is a string, not a Player object, because of this line:

players.append( name )

replace with:

players.append( self )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM