## Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community!

### Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.  # A big confusion in a challange

Why am I getting an output like this? It seems like cls() is removing all of the values inside list_sum. Why?

```>>> from hands import Hand
>>> from dice import D20
>>> Hand.roll(2)
[12, 17]
[12, 17]
[]
[12, 17]
[12, 17]
[]
```
dice.py
```import random

class Die:
def __init__(self, sides=2):
if sides < 2:
raise ValueError("Can't have fewer than two sides")
self.sides = sides
self.value = random.randint(1, sides)

def __int__(self):
return self.value

return int(self) + other

return self + other

class D20(Die):
def __init__(self):
super().__init__(sides=20)
```
hands.py
```from dice import D20

class Hand(list):
def __init__(self, list_sum=None):
self.list_sum = list_sum
print(self.list_sum)
print(list_sum)

@classmethod
def roll(cls, times):
list_sum = []
for _ in range(times):
list_sum.append(D20().value)
print(cls(list_sum))
return cls(list_sum)

@property
def total(self):
return sum(self)
``` MOD

By adding numbers to the print statements, you can follow the flow:

```class Hand(list):
def __init__(self, list_sum=None):
self.list_sum = list_sum
print(1, self.list_sum)
print(2, list_sum)

@classmethod
def roll(cls, times):
list_sum = []
for _ in range(times):
list_sum.append(D20().value)
print(3, cls(list_sum))
return cls(list_sum)

@property
def total(self):
return sum(self)

a= Hand.roll(2)
print(4, a)
```

Produces:

```1 [5, 8]
2 [5, 8]
3 []
1 [5, 8]
2 [5, 8]
4 []
```

The print before the `return` and the `return` both create instances of `Hand` The instance from the print is thrown away. Thanks Chris, I still don't understand, why `cls()` makes `list_sum` to loose it's content. Could you please explain it to me?(sorry if it's already in your answer and I can't see it) ```class Hand(list):
def __init__(self, list_sum=None):
self.list_sum = list_sum
print(1, self.list_sum)
print(2, list_sum)

@classmethod
def roll(cls, times):
list_sum = []
for _ in range(times):
list_sum.append(D20().value)
a= cls(list_sum)
print('3a', a)
print('3b', a.list_sum)
print(3, cls(list_sum))
return cls(list_sum)

@property
def total(self):
return sum(self)

a= Hand.roll(2)
print(4, a)
```

Produces:

```1 [13, 8]
2 [13, 8]
3a []
3b [13, 8]
1 [13, 8]
2 [13, 8]
3 []
1 [13, 8]
2 [13, 8]
4 []
```

Printing the instance which is an extension of `list` produces the empty list since nothing was append to `self`. The custom added attribute `list_sum` does display as printed. Thanks Chris! I've played a bit with that code and I came to a conclusion that I completely don't need `self` in my code. I was struggling with understanding your answer above becasue I didn't get how is `self` neccessary in this code. Did you mean by saying `self` the `cls()`? Because then it would make sense. I finally undertand the point of having `@classmethod` - they don't need an instance to work on. Am I getting that right? Here's my code:

```from dice import D20

class Hand(list):
@classmethod
def roll(cls, times):
print(2)
list_sum = cls()
for _ in range(times):
list_sum.append(D20())
print(3, list_sum)
print(4, sum(list_sum))
return list_sum

@property
def total(self):
return sum(self)

a= Hand.roll(2)
print(1, a)
print(2, a.total)
```

...and the output:

```2
3 [<dice.D20 object at 0x7f20008d5080>, <dice.D20 object at 0x7f20008d50b8>]
4 9
1 [<dice.D20 object at 0x7f20008d5080>, <dice.D20 object at 0x7f20008d50b8>]
2 9
```

EDIT After a minute I realised that in

``` @property
def total(self):
return sum(self)
```

there's `self`! How is it possible that it still works even tho I removed everything with conection to the instance from the code? Is `self` and `cls()` basically the same thing? I came to that conclusion after changing `self` to `cls` in

```@property
def total(cls):
return sum(cls)
```

Also I don't understand what's the difference between just `cls` and `cls()` Good point! `self` and `cls` are similar in that they are both placeholders used to bind the method to an object. "Binding" means to attach the method to an instance or a class that the method will use as a context to operate within.

Both of the terms `self` and `cls` are always used as the first positional parameter. For class methods, the `cls` is assigned when the class is parsed. for instance methods, the `self` is assigned during the instance creation.

The names of the parameters `self` and `cls` are a Python convention. Changing the name of the first positional argument to something else does not change the functionality, rather it only affects the readability of the code. So changing `self` to `cls` in the `total` method does not affect it's functionality. In the method with `self` changed to `cls`, the parameter `cls` will still be assigned to point to the instance of the class.

By adding `print` inside the `total` method, you can see whether it is `self` or `cls`, the value of the parameter is the same. In fact, you could you "`smith`" and "`agent`" instead of `self` and `cls` as the name of the positional arguments.

```class Hand(list):
@classmethod
def roll(cls, times):
print(2, "class:", cls)
list_sum = cls()
for _ in range(times):
list_sum.append(D20())
print(3, "instance:", list_sum)
print(4, "instance:", sum(list_sum))
return list_sum

@property
def total_self(self):
print(5, "instance:", self)
return sum(self)

@property
def total_cls(cls):
print(6, "instance:", cls)
return sum(cls)

a = Hand.roll(2)
print(1, "instance:", a)
print(2, "instance:", a.total_self)
print(6, "instance:", a.total_cls)
```
```\$ python rpg_roller.py
2 class: <class '__main__.Hand'>
3 instance: [<__main__.D20 object at 0x7fdb1d7f1c18>, <__main__.D20 object at 0x7fdb1d7f1cc0>]
4 instance: 15
1 instance: [<__main__.D20 object at 0x7fdb1d7f1c18>, <__main__.D20 object at 0x7fdb1d7f1cc0>]
5 instance: [<__main__.D20 object at 0x7fdb1d7f1c18>, <__main__.D20 object at 0x7fdb1d7f1cc0>]
2 instance: 15
6 instance: [<__main__.D20 object at 0x7fdb1d7f1c18>, <__main__.D20 object at 0x7fdb1d7f1cc0>]
6 instance: 15
``` Oh alright, so as long as I'm consistent in naming these parameters, functionality isn't affected. Only readabilty is... So which way is proper? Should I in the `@classmethod`use `cls` and in the `total` method use `self`? But then constintacy rule is enroached and to me it doesn't make sense to in one part of a code name it in a different way than in an another part...

Also while testing the code one thing suprised me: how does python know that when calling `return sum(cls)` we want python to return the summed value of `D20()` attribute `.value`? I mean I didn't provide an information that I want `.value` attribute to be summed. Should I in the @classmethoduse cls and in the total method use self? Yes! Though it may look inconsistent, the point of using `cls` in a classmethod is to provide a visual reminder that you are operating on the class and not on an instance of the class.

How does python know that when calling `return sum(self)` we want python to return the summed value of D20() attribute .value? The sum() function expects an iterable. Since the `self` instance is derived from `list`, `sum()` will be able iterated over each item in the `Hand` instance and calling the item's `__add__` method. In this case, it calls the `D20` instance `__add__` method, which returns an `int`.