Gazoo Gazoo - 6 months ago 11
Python Question

Function inside of Object generating different print output than stand-alone function in Python 3.5

I have the following stand-alone function for printing arguments:

def multiArgsPrinter2(*args):
testString = '';
for count, thing in enumerate(args):
testString += str(thing) + ","

return testString


Which when run like this:

retval = multiArgsPrinter2(20, 30, 40)
print(retval)


prints 20,30,40, - as expected. I then make a class with this functionality inside:

class TestHelper2:
"""The TestHelper Class"""

def multiArgsPrinter3(*args):
testString = '';
for count, thing in enumerate(args):
testString += str(thing) + ","

print(testString)
return testString


No matter where I print this result, either as a returned value or inside the class the output I get looks like this:

<TestHelper2.TestHelper2 object at 0x00F6ABB0>,20,30,40,


which puzzles me. Any clues to what I'm not grasping?

Bonus points if you can tell me why calling yet another function inside an object has a habit of causing parentheses () to be attached around the return value?

Answer

Functions defined in a class are by default instance methods. This means that they are implicitly passed an instance of the class and the function signature should reflect that. For example:

class Example:
    def print_stuff(self, *args):
        print 'My *self* is {}'.format(self)
        print 'My *args* is {}'.format(args)

Example().print_stuff(1, 2, 3)
# My *self* is <__main__.Example instance at 0x012D4210>
# My *args* is (1, 2, 3)

Python provides two decorators in order to change the signature of a function defined inside a class, staticmethod and classmethod. They are most often used with the decorator syntax (beyond the scope of this response) and are functions that accept a function as an argument and return a new, altered function.

staticmethod removes the implicit self argument from a function inside a class.

class Example:
    @staticmethod
    def print_stuff(*args):
        # No more self...
        print 'My *args* is {}'.format(args)

Example().print_stuff(1, 2, 3)
# My *args* is (1, 2, 3)

A hypothetical implementation of staticmethod might look something like this:

def staticmethod_example(func):
    def wrapper(self, *args, **kwargs):
        return func(*args, **kwargs) # Notice how *self* is thrown away
    return wrapper

classmethod removes the implicit self argument from a function, but adds the instance class as an argument instead.

class Example:
    @classmethod
    def print_stuff(cls, *args):
        print 'My *cls* is {}'.format(cls)
        print 'My *args* is {}'.format(args)

Example().print_stuff(1, 2, 3)
# My *cls* is __main__.Example
# My *args* is (1, 2, 3)

A hypothetical implementation of classmethod might look something like this:

def classmethod_example(func):
    def wrapper(self, *args, **kwargs):
        return func(self.__class__, *args, **kwargs) # Substitute *cls* for *self*
    return wrapper

To answer your question, your function call is printing the instance of the class because it is being passed self implicitly. If you add the staticmethod decorator above the function declaration, it will work as intended.