0

I'm still wrestling with classes. Instead of using the classic employees in a company or car example, I've decided to create a simple game character. So far so good, only I'm having trouble adding to an item to a list which is a class.

class Player():
  def __init__(self, name, items):
    self.name   = name
    self.items  = items

# initialize character
player = Player("Joey", 
  ["movie stub", "keys", "army man"])


print(player.items)
# >> ['movie stub', 'keys', 'army man'] # this is fine

Now I'd like to add an item to the player character.

player.items.push("a rock")
# AttributeError: 'list' object has no attribute 'push'

I was trying using push - only that results in an attribute error. So I added a simple helper class:

# helper class
class List(list):
  def push(self, x):
    self.append(x)

player.items = List(["a rock"])

Yay! no errors...

print(player.items)
>> ['a rock']

Only instead of appending, it's replaced the list, which is not what I'm after.

Any ideas where I'm going wrong?

3
  • 1
    insert(index) – inserts a single element anywhere in the list. append() – always adds items (strings, numbers, lists) at the end of the list. extend() – adds iterable items (lists, tuples, strings) to the end of the list. Commented Aug 25, 2022 at 17:12
  • Can you explain why it is so important to be able to call append by the name push instead of just using append directly? I know it's called push in other languages, but you're not writing those languages; trying to write code from language X in language Y leads to terrible code (all the people who come from C and only write for loops over ranges, the people who come from Perl and never use str methods, just the re module, etc.). Your original problem would not be an issue if you were willing to just type player.items.append("a rock"). Commented Aug 25, 2022 at 17:40
  • @ShadowRanger in this instance (pun intended) it wasn't a python/javascript append/push name transposition but simply using a synonym and unable to comprehend that I was doing anything wrong. A problem with English and not code; happens all the time. Commented Aug 25, 2022 at 19:14

4 Answers 4

1

You should add push function inside the class itself

class Player():
  def __init__(self, name, items):
    self.name   = name
    self.items  = items

  def push(self, x):
    self.items.append(x)

  def print(self):
    print(self.name,": ",self.items)


# initialize character
player = Player("Joey", 
  ["movie stub", "keys", "army man"])

adding item to the list

player.push("a rock")

printing

player.print()

output

Joey : ['movie stub', 'keys', 'army man', 'a rock']

Sign up to request clarification or add additional context in comments.

Comments

1

To be fair you're complicating things. Just made method in class, which add things to your list and you're good to go

class Player():
  def __init__(self, name, items):
    self.name   = name
    self.items  = items
  def add_item(item):
    self.items.append(item)

With this

# helper class
class List(list):
  def push(self, x):
    self.append(x)

player.items = List(["a rock"])

you weren't even passing list you wanted to attach item. So to make your helper work(you do not need it, method in Player is good enough, but I want to show it anyway, because you asked for it)

class List():
  def push(self, list, x):
    list.append(x)

my advise is to put method in class player to append there items

Comments

1

If you don't want to replace it, don't replace it? There is nothing special about the name push, and you never called it, so append never occurred, you just replaced the original list with your unnecessary List subclass.

If you must be able to call push instead of append, convert to your List subclass on construction, so it stores a push friendly list from the get-go:

class List(list):
  def push(self, x):
    self.append(x)

class Player():
  def __init__(self, name, items):
    self.name   = name
    self.items  = List(items)

Now you can just do:

player = Player("Joey", 
                ["movie stub", "keys", "army man"])

player.items.push("a rock")

and it just works. As a side-benefit, it is now shallow-copying the list provided by the caller, so change's made to the caller's list don't retroactively change the instance's attribute's contents, nor vice-versa.

Comments

0

You need to take a more complete OOP approach by encapsulating data and functionality within your class. Something like this:

class Player():
    def __init__(self, name, items):
        self._name = name
        self._items = items
    def push(self, item):
        self._items.append(item)
    def __repr__(self):
        return f'{self._name=}, {self._items=}'
    def __str__(self):
        return f'Name={self._name}, Items={", ".join(self._items)}'

player = Player("Joey", ["movie stub", "keys", "army man"])
print(player)
player.push('a rock')
print(player)

Output:

Name=Joey, Items=movie stub, keys, army man
Name=Joey, Items=movie stub, keys, army man, a rock

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.