[Tutor] Re: Defining a function (Joseph Q.)

Jeffrey Maitland maitj at vianet.ca
Tue Apr 12 18:54:57 CEST 2005


Brian van den Broek writes: 

> Joseph Quigley said unto the world upon 2005-04-11 20:23:
>> Well, now I've learned what def is good for. But what could I put in the 
>> parenthesis of  def foo():?
>> Of course self is always available, but what would maybe def 
>> foo(number1): do? An error right? So I now repeat my self, what else 
>> besides self could I put in there? 
>> 
>> Thanks,
>>         Joseph
> 
> Hi Joseph, 
> 
> as Liam explained, you put the arguments (if any) to the function in
> the parenthesis. 
> 
> But, I want to address the bit where you said "Of course self is
> always available". *Any* valid Python identifier (or name) can be used
> ("is always available"): 
> 
>>>> def silly(a_name_I_picked_at_random):   # well, not quite
> ... 	print a_name_I_picked_at_random     # at random ;-)
> ... 	
>>>> silly(42)
> 42 
> 
> The name a_name_I_picked_at_random is like a "placeholder" inside the
> function for whatever input we gave to the function. And *that* can be
> any object: 
> 
>>>> silly(silly)
> <function silly at 0x01298070>
>>>> 
> 
> Some functions require certain sorts of inputs in virtue of what they
> try to do with them, but we can still pass any sort of object in.  For
> instance, Liam had: 
> 
>>>> def foo(a, b):
> ... 	return a + b
> ... 
> 
> Now, try this: 
> 
>>>> foo(42, '42')
> Traceback (most recent call last):
>   File "<interactive input>", line 1, in ?
>   File "<interactive input>", line 2, in foo
> TypeError: unsupported operand type(s) for +: 'int' and 'str'
>>>> 
> 
> That's not a problem with Liam's function; it's a problem that I
> caused by sending it inappropriate inputs. 
> 
> 
> At any rate, you are correct that you can always name an argument
> "self". But "self" is, by *very* strong convention, used only within
> classes.  Simplifying[*] a bit, a method is a function defined
> internal to a class. If you define a method in a class, you call the
> first argument of the method definition "self", and it is
> automatically interpreted as a reference to the `active' instance of
> the class on which the method is called. 
> 
> So, don't use "self" outside of method definitions. You can ("we are
> all adults here"), but doing so will only confuse things given the
> strength of the convention. 
> 
> [*] The simplification comes in that not all methods in a class need
> to be bound to an instance, so not all methods employ "self". But, my
> guess is that is something you shouldn't be worrying about just yet. 
> 
> Best, 
> 
> Brian vdB 
> 
> 
> _______________________________________________
> Tutor maillist  -  Tutor at python.org
> http://mail.python.org/mailman/listinfo/tutor

Brian is correct. 

Also I would like to point out that
def foo(*args): #this allows for any number of arguments to be passed.

The *args is powerful when used correctly. *args is a list of any length of 
arguments being passed to the function and/or class, and the arguments 
passed can be any type/object you want to pass . 

So you might do something like.
def foo(*args):
  print len(args)
# this prints the length of the list of the arguements passed 

# so using that function you would see something like. in the example I only 
used basic types but you can pass objects as well.
>>foo(1, 2, 3, "cat", "mouse", ['bee', 'honey', 'stinger'])
6 

Notice that the length that is returned is only 6 but there are 8 items so 
it appears to have been passed to the function.   In actuallity it is only 6 
items.  There is 3 integers, then 2 strings, then 1 list that is 3 items 
long. Thus the length of the list args is 6 items long. I wouldn't recomend 
passing mixed types like this to a function using args because it can get 
very confusing. I hope this helps you out and doesn't confuse you. I know 
from first hand experience the first time I saw the *args in some code I was 
lost. 

If you know the type of variables that are to be passed to the function and 
the number of them then it is easier to specify them, and use names. such 
as. 

def bar(num1, num2): #this is not catching invalid data types and such.
  return num1 + num2 #returns the sum of num1 + num2 

>> bar(1, 2)
3 

Also if you want to have default values passed incase the call is issued 
without any arguments passed.
#This will take 2 arguments and add them together and return the sum
# but the default values will fill in the remaining (missing) arguments.
def my_foo(num1 = 0.0, num2 = 1.0):
  return num1 + num2 

>> my_foo()
1.0
>> my_foo(6.7)
7.7
>> my_foo(2, 2)
4 

The reason that my_foo() returns 1.0 is that no arguments were given so the 
default values were used and the 2nd argument default value is 1.0 and was 
added to the 1st argument's default value of 0.0. Thus 0.0 + 1.0 

The reason that in the my_foo(6.7) example 7.7 is returned is that the 
default value of the 2nd argument is used since no 2nd argument was given 
was given. so it was 6.7 + 1.0 

And Finally both arguments were specified my_foo(2, 2) the function takes 
both values and adds them giving you 4. 

I hope this helps, and does not make any more confusing. I try to be consise 
when giving information however I like to be thorough in my explanations. 

Jeff


More information about the Tutor mailing list