My fight with classes :)

Terry Reedy tjreedy at
Wed Jun 11 22:51:28 CEST 2008

"TheSaint" <fc14301589 at> wrote in message 
news:484fde63_1 at
| Hi,
| I'm very new with classes. I still reading something around ;)
| I got started to try a concatenation of 2 type of string, which have a
| particular property to start with A or D.
| My class here:
|    """ Small class to join some strings according to the leading first
|     letter"""

You left out the class statement.

|    def __init__(self):
|        self.valueA= ''
|        self.valueD= ''
|    def __add__(self, value):

I agree with P. Pearson that 'add' methods should generaly not be used for 
mutation.  Certainly, they are generally used to combine two objects of the 
same or compatible classes, even if the result replaces one of them.  This 
method is equivalent to list.append.

|        if not isinstance(value, str): return

Do you really want to just return None when there is bad input?

|        if value.lower().startswith('a'):
|            self.valueA += value
|        if value.lower().startswith('d'):
|            self.valueD += value
|        return self.valueA ,self.valueD

List mutation methods return None so one cannot forget that they mutate. 
In any case, the alternative is to return self.  You seem to be returning 
this tuple because you did not write an __str__ method.  Doing two 
different things in one method is what got you in trouble.  So return None 
or self and add

def __str__(self): return self.valueA + ', ' + self.valueB

|    __call__= __add__
|    __iadd__= __add__

This requires that __add__ return self.  Better to use .append() and

def __iadd__(self, val):
    return self

| my test on the shell:
[snip good tests]
| >>> k += 'liu'

k is now a tuple!
Hence the below

| >>> k += 'aliu'
| Traceback (most recent call last):
|  File "<stdin>", line 1, in <module>
| TypeError: can only concatenate tuple (not "str") to tuple
| >>> k
| ('aksaboi', 'daksdhksduboi')

| Do I miss something?

That augmented assignment is assigment.  Always.
You are not the first ;-)/

| I'd rather like to avoid class, but a function won't allow me to store so
| easily data between several call.

Classes are the general mechanism for bundling stored data and functions. 
You can easily bundle *one* function and stored data with a nested 

def makeappender():
   data = ['','']
   def appender(val):
      <code that mutates data>
   return appender

For multiple functions, use classes.

| Mostly I'd expect to pass to the built instance in a more elaborated
| function. Then I mean call will be the primer goal.

__call__ can be an alias for append just as well as for __add__.

Terry Jan Reedy

More information about the Python-list mailing list