Still thinking and blogging about #python. There are some practices that python encourages that are ... frankly dangerous.

Turns out sometimes writing more lines of #python is better than writing fewer.

Surprised ?

https://medium.com/@LeftSaidTim/the-curious-case-of-more-code-being-better-than-less-code-18d834e72e5?sk=a23543481bf71377ace092e8963414ba

@Leftsaidtim I think you wanted `assert has_stuff.size() == 2` in that first code block?
@llimllib hey youโ€™re absolutely right. Thanks for checking that. I gave you a shout out at the end ๐Ÿ™Œ

@Leftsaidtim I either disagree, or don't fully understand the boggle there.

In the first example, I wonder why you'd have a `__size` or `size()` in the first place, and not just add them into `__len__`. That seems like it'd be the more Pythonic approach.

@diji I think i would understand better if you share a snippet. Pair programming over mastodon is challenging.

@Leftsaidtim

```
class Set:
def __init__(self):
self.__values = []
self.__size = 0

def __len__(self):
return self.__size

def add(self, value):
if value in self.__values:
return
self.__size += 1
self.__values.append(value)
```

```
def test_size():
empty = Set()
has_stuff = Set()
has_stuff.add("waffles")
has_stuff.add("cheese")

assert len(empty) == 0
assert len(has_stuff) == 2
```

@Leftsaidtim This'd be the more Pythonic approach.

@Leftsaidtim

```
class Node:
def __init__(self, val):
self.value = val
self.__next = None

def add(self, next_):
self.__next = Node(next_)
return self.__next

def __next__(self):
if self.__next is None:
raise StopIteration
return self.__next

def __iter__(self):
return self

def __len__(self):
return sum(1 for _ in self)
```

@Leftsaidtim This uses Python's built-in iteration, and len() functionality. A few mods I made, and you might adjust for your use case:

- Assumed next_ in add was a value, and we want to wrap it in a Node. Note that this replaces the next node, so it is more like an Insert than an add. You might want to crawl to the last node and add the next there.
- The len works from the instance node you are looking at. That makes sense sicne this is a one-way linked list.

@diji Ah that's a good point. I should have pointed out that I was considering this as an exercise of defining our own interface, separate from knowing anything about len(), or other python built-ins.

It's a bit of a strawman argument as a result, but there's certainly other cases where you're building your own interface and it's tempting to expose a variable directly, rather than a method.

@Leftsaidtim That's fair. The problem with exposing the field directly, is that you have no control over someone mucking with it. If a field expects a string, and methods in the class hinge on it being a string, then someone replacing that value with an int or None could be bad.

That said, the ethos of Python is "we're all consenting adults here".

You can do getters and setters with the property decorator, which does allow you a measure of control. This is a bit anti-pattern though.

@Leftsaidtim This link covers that:

https://realpython.com/python-getter-setter/

You're not wrong though. We're giving the kids access to matches and hoping they don't burn down the house! :)

Getters and Setters: Manage Attributes in Python โ€“ Real Python

In this tutorial, you'll learn what getter and setter methods are, how Python properties are preferred over getters and setters when dealing with attribute access and mutation, and when to use getter and setter methods instead of properties in Python.

@Leftsaidtim The second example... I am not sure I see the dilemma in exposing the value directly. Seems like the `next()` could be replaced with `__next__()` to hook into existing Pythonic systems?