5

I've seen a lot of posts but none really addressing my question. With Python, I am trying to pass a method as an argument in a function which requires two arguments:

# this is a method within myObject
def getAccount(self):
    account = (self.__username, self.__password)
    return account
# this is a function from a self-made, imported myModule
def logIn(username,password):
    # log into account
    return someData
# run the function from within the myObject instance
myData = myModule.logIn(myObject.getAccount())

But then Python's not happy: it wants two arguments for the logIn() function. Fair enough. If thought the problem was that the getAccount() method returned a tuple, which is one object. I tried then:

def getAccount(self):
    return self.__username, self.__password

But that either did not make a difference.

How then can i pass the data from getAccount() to logIn()? Surely if i don't understand that, i am missing something fundamental in the logic of programming :)

Thanks for helping. Benjamin

6
  • Why can't you just store the return value of getAccount() in a variable and call logIn() with the received values? Also you are not following the python coding standard. Are you coding in twisted? Commented May 4, 2011 at 10:01
  • isn't what i did with my first code where "account" was the variable? I don't know about the python coding standards, i'm new to it, and it's just a hobby. But if you have tips, please share. Commented May 4, 2011 at 10:26
  • 1
    @Benjamin: You should read PEP-8. Commented May 4, 2011 at 10:45
  • @the_drow What part of the code i gave did you think was not according to the python standards? Commented May 5, 2011 at 12:04
  • @Benjamin: the function name and the variable names. Nothing should be __XXX. The method name should be method_name. Just read the PEP. Commented May 5, 2011 at 13:43

4 Answers 4

8

You want to use python argument unpacking:

myData = myModule.logIn( * myObject.getAccount() )

The * before an argument to a function signals that the following tuple should be split into its constituents and passed as positional arguments to the function.

Of course, you could do this by hand, or write a wrapper that takes a tuple as suggested by others, but unpacking is more efficient and pythonic for this case.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for detailing the use of * :)
For the record, it works with any iterable, it will just be exhausted completely before the function is called.
6

This

myData = myModule.logIn( * myObject.getAccount() )

6 Comments

it is not C, in python you just use the method name
@correndo: That's true if you want to pass a callback. If you don't, He is correct.
@correndo: This is unpacking. The return value of myObject.getAccount() is unpacked so that it becomes two arguments. Why do you think he wrote C?
I don't understand this, could you explain the use of * please?
@Benjamin: * takes the tuple and unpacks it into the myModule.logIn() method. So while myObject.getAccount() returns username, password the * operator transforms them into the parameters of myModule.logIn().
|
4

Your method asks for two parameters while if you want to hide the login execution in a method you can easily pass one parameter, execute it and retrieve the data:

# this is a method within myObject
def getAccount(self):
    account = (self.__username, self.__password)
    return account

# this is a function from a self-made, imported myModule
def logIn(account):
    user , passwd = account()
   # log into account
   return someData

# run the function from within the myObject instance
myData = myModule.logIn(myObject.getAccount)

Note that the method is passed without the parenthesis, then you execute it within the login retrieving the data.

1 Comment

I find this answer interesting, i didn't even realise i could do that. However i find it less readable, because it's not clear when reading the logIn() function what the account() really does.
3

Your title is a bit confusing, since you actually can pass a method. In Python functions are first class, which means you can pass them around as any value.

Your text however shows that you want to do something else.

Python really returns multiple values as one value, a tuple of the values.

return 1, 2

is really the same as

return (1, 2)

However, if you need to unpack these values, as in your case, there are several ways to achieve this.

You can unpack them into variables:

usn, psw = myObject.getAccount()

Or you can "expand" them right into the function call:

myModule.logIn(*myObject.getAccount())

This requires that the amount of arguments is the same as the dimension of the tuple (2 argument function requires a tuple (x, y))

If you instead want to pass the method you can do that, but you need to be careful not to call it:

def logIn(self, a):
   usn, psw = a()
   # do stuff

logIn(myObject.getAccount)

2 Comments

Thanks for providing a detailed answer. I didn't know most of what you explained. As i commented above, i am not sure as to how the use of * functions, although it seems to be the most elegant way to achieve what i want to do. Also i am not really sure i understand what you said about the title of this question.
@Benjamin: Never mind that about the title. It was just a very obtuse way to say I misunderstood you :) You could say the * operator maps each value of an iterable to a positional argument in a function call (it works with lists as well.) There is also the ** operator, which unpacks a dict into keyword arguments.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.