Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I've been learning Python for about 2 months now (Started with Learn Python The Hard Way, now reading Dive Into Python), and within both books, I still seem to be confused over this one bit of code.

Lets just take the default code that Dive Into Python uses as an example:

def buildConnectionString(params):
    """Build a connection string from a dictionary of parameters.


    Returns string."""
    return ";".join(["%s=%s" % (k, v) for k, v in params.items()])

if __name__ == "__main__":
    myParams = {"server":"mpilgrim",
                "database":"master",
                "uid":"sa",
                "pwd":"secret"
               }

print buildConnectionString(myParams)

How does the function buildConnectionString with the argument (params) know to get its data from the variable myParams? Or params.items(), too within the return line? Wouldn't the argument in buildConnectionString need to be set as buildConnectionString(myParams) in order for it to read properly? How can you set the variable of your data to myParams, but have the argument of your function be params and have it read? How does it know to read myParams as params?

And is there a reason behind not naming your variable params, or vice versa naming your argument in your function myParams? It's just been extremely confusing seeing the argument set as one word, and then having the variable named something completely different, but having the function still be able to read your code, even when the argument name is different from your variable with the data you're printing from.

share|improve this question
    
Thank you for the edit. I didn't realize I had a notification requesting that I edit something. –  Kevin Jul 25 '12 at 11:29
    
Shouldn't this go to SO? –  H2CO3 Jul 28 '12 at 22:30

5 Answers 5

It's not about Python.

But nevertheless, to answer you straightly. Lets say you have a function:

def doSomethingWithParmas(params):
    params.doSomething()

Now you can call it later on with:

print doSomethingWithParams(myParams)

or/and

print doSomethingWithParams(yourParams)

It's how functions work, you can call it with whatever params you like, all that function cares, is that they are some kind of params that it can handle.

EDIT: A remark: I have never coded a line of Python in my life.

share|improve this answer
    
so let's say we do something like this <br> def doSomethingWithParams(params): params.doSomething() x = "whatever" y = "whatever" –  Kevin Jul 25 '12 at 11:54
    
I was trying to type code in the comment, and it wasn't allowing me..than it wouldn't allow me to edit because of the 5 minute rule..what I wanted to say was thank you for your response. –  Kevin Jul 25 '12 at 12:00
    
@kevin and the reason this is necessary is that the function migth be put in a library and used by someone else - so it's important that the name of the params is just a token fro whatever is passed in –  Martin Beckett Jul 28 '12 at 21:21
    
That edit is wrong. You have now coded 4 lines of Python in your life. –  Jordan Jul 29 '12 at 1:22

Maybe it would be clearer if the arguments were differently named?

def buildConnectionString(placeholder_for_whatever_is_passed_in):
    return ";".join(["%s=%s" % (k, v) for k, v in placeholder_for_whatever_is_passed_in.items()])

if __name__ == "__main__":
    what_I_actually_pass in = { "server":"mpilgrim",
                                "database":"master",
                                "uid":"sa",
                                "pwd":"secret"   } 

print buildConnectionString(what_I_actually_pass_in)
share|improve this answer

If we take a look at

def buildConnectionString(params):
    return ";".join(["%s=%s" % (k, v) for k, v in params.items()])

params is a locally-scoped variable. It's not referring to any other variables in your code, it is the name for the variable you pass into your function. What this means is that you can pass any variable into buildConnectionString() without having to know in advance what you are passing in.

Regarding naming myParams vs params there is no real reason. You could just as easily name it params if it helps you keep track of things. But what happens when you need to keep two sets of params variables? This is why you pass variables into your function rather than referencing global (defined outside of a function) variables. You could have written that function as

myParams = {"server":"mpilgrim",
            "database":"master",
            "uid":"sa",
            "pwd":"secret"
           }

def buildConnectionString():
    return ";".join(["%s=%s" % (k, v) for k, v in myParams.items()])

print buildConnectionString(myParams)

Doing it that way means you can only print myParams. But if you define myOtherParams you couldn't print it at all. You just have to keep in mind that any variables defined inside of the parentheses is only a copy of the variable you pass into it, not the original variable itself.

share|improve this answer

First, you need to understand what functions are used for. You might say, that a function provides a service: It does something for you.

Functions

  • Provide a service
  • don't know you exist

A printer for example is some kind of a service: It prints documents for you, you don't have to do it yourself. If you provide the printer with the necessary information (the parameters), the printer will happily do its job.

The printer does not know what data it will receive, otherwise, it wouldn't need a parameter. The parameter is the "unknown" that is needed to perform the service.

def my_function(a, b):
    pass

This provides a service (or function) that wants two pieces of information from you. Once it has this information, it needs to be able to refer to it somehow. The notation (a, b) simply means that whatever you give it as first "information", will accessible from the name a and what you pass second will be accessible from the name b.

When you actually call the function (i.e. tell the printer to actually print something), you need to fill in these gaps of knowledge like so:

my_function(data_that_i_know, other_data_that_i_know)

Your questions

How does the function buildConnectionString with the argument (params) know to get it's data from the variable myParams?

It doesn't. Does my printer know I am going to print a document relating to programming tomorrow? No. Tomorrow, I will send the information to my printer, which it will then happily print. The printer does not even know I exist.

Similarly, you "send" (pass) the data (myParams) to your function with the following expression:

buildConnectionString(myParams)

At some other point in your program, you may wish to execute your function with different data. Similar to the printer, the function doesn't know who will call it, or when it will be called, or with what data it will be called.

Or params.items(), too within the return line?

The function, once executed, has received some data so it can do its job. This will execute a function called items() on whatever has been given the function to work with.


An example function

I want to create my own service, that can calculate the square of a number. This implies, that it needs to be given a number in order to work. After all, you can't square nothing, can you?

The function does not know, which number it will be given. However, in order to be able to multiply this number, we need to be able to refer to it somehow, hence, we give it a name: x.

def square(x):
    return x * x

This defines a function called square that needs to be given one piece of data (the x).

I can now use this function to square a number:

>>> print square(2) # "Please square this number 2 for me"
4

Within the function, x now refers to the value 2.

But I could also have called the function with the number 3:

>>> print square(3) # "Please square this number 2 for me"
9

I could have chosen the name two instead of x for my function. But that would be misleading: The value does not have to be 2, it can be whatever I wish it to be.


And is there a reason behind not naming your variable params, or vice versa naming your argument in your function myParams?

Names in programming can be chosen arbitrarily, as long as they are not reserved by the language (these are called keywords).

Usually, you will name your variables whatever makes sense in that context. For instance, in code about geometric objects, my local variable may be named area which I will then square using the square() function. In code about a car I may have a variable named weight on the otherhand. I am sure you will agree that I being able to call square with square(weight) and square(area) conveys a lot of information.

Would you now change the parameter of square from x to weight_or_area? I hope you wouldn't. What if I was to use the function in connection with lengths? You will have to get used to the fact that parameters and arguments of functions are usually named differently, that is a Good Thing®.

It's just been extremely confusing seeing the argument set as one word, and then having the variable named something completely different, but having the function still be able to read your code, even when the argument name is different from your variable with the data you're printing from.

It is important to understand, that the function does not read your code. It has no idea it even exists. This brings us back to the printer analogy: Does it know you or I exist? Not, it's there to perform a job, no questions asked. The same thing applies to functions: They are there to do our bidding. They do not act on their own and "read code" to see where they are referenced.

share|improve this answer

You need to read this for a complete understanding of how functions and their parameters work in python: http://docs.python.org/tutorial/controlflow.html#defining-functions

A simple explanation is that the python interpreter matches the first parameter in your function call to the first value in the function definition, the second to the second and so on if the parameters in the function call are not named.

In your example, when you do print buildConnectionString(myParams) as you have done, python assumes you meant print buildConnectionString(params=myParams) which is a fair assumption to make. The value of params can be anything you like but if you mess up the parameter name itself, you will get an error.

This will not give you an error: print buildConnectionString(params=whateveryouwant)

But this will give you an error: print buildConnectionString(wrongparametername=myParams)

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.