Python: передать метод в качестве аргумента в функции

#python #methods #arguments

#python #методы #аргументы

Вопрос:

Я видел много сообщений, но ни одно из них не касалось моего вопроса. С помощью Python я пытаюсь передать метод в качестве аргумента в функции, которая требует двух аргументов:

 # 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())
  

Но тогда Python не доволен: ему нужны два аргумента для функции logIn(). Достаточно справедливо. Я думал, проблема заключалась в том, что метод getAccount() вернул кортеж, который является одним объектом. Я попытался тогда:

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

Но это также не имело значения.

Как тогда я могу передать данные из getAccount() в logIn()? Конечно, если я этого не понимаю, я упускаю что-то фундаментальное в логике программирования 🙂

Спасибо за помощь. Бенджамин

Комментарии:

1. Почему вы не можете просто сохранить возвращаемое значение getAccount() в переменной и вызвать logIn() с полученными значениями? Также вы не следуете стандарту кодирования на Python. Вы пишете на twisted?

2. не то ли, что я сделал с моим первым кодом, где переменной была «account»? Я не знаю о стандартах кодирования на Python, я новичок в этом, и это просто хобби. Но если у вас есть советы, пожалуйста, поделитесь.

3. @Benjamin: Вам следует прочитать PEP-8 .

4. @the_drow Какая часть кода, который я привел, по вашему мнению, не соответствует стандартам python?

5. @Benjamin: имя функции и имена переменных. Ничего не должно быть __XXX. Имя метода должно быть method_name. Просто прочитайте PEP.

Ответ №1:

Вы хотите использовать распаковку аргументов python:

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

* перед аргументом функции указывает, что следующий кортеж должен быть разделен на его составляющие и передан в качестве позиционных аргументов функции.

Конечно, вы могли бы сделать это вручную или написать оболочку, которая принимает кортеж, как предлагали другие, но распаковка более эффективна и pythonic для этого случая.

Комментарии:

1. Спасибо за подробное описание использования * 🙂

2. Для записи, он работает с любым итерируемым, он просто будет полностью исчерпан до вызова функции.

Ответ №2:

Это

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

Комментарии:

1. это не C, в python вы просто используете имя метода

2. @correndo: Это верно, если вы хотите передать обратный вызов. Если вы этого не сделаете, он прав.

3. @correndo: Это распаковка . Возвращаемое значение myObject.getAccount() распаковывается так, что оно становится двумя аргументами. Как вы думаете, почему он написал C?

4. Я этого не понимаю, не могли бы вы объяснить использование * , пожалуйста?

5. @Benjamin: * берет кортеж и распаковывает его в myModule.logIn() метод. Таким образом, myObject.getAccount() возвращая имя пользователя, пароль, оператор * преобразует их в параметры myModule.logIn() .

Ответ №3:

Ваш метод запрашивает два параметра, в то время как, если вы хотите скрыть выполнение входа в метод, вы можете легко передать один параметр, выполнить его и получить данные:

 # 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)
  

Обратите внимание, что метод передается без круглых скобок, затем вы выполняете его при входе в систему, извлекая данные.

Комментарии:

1. Я нахожу этот ответ интересным, я даже не представлял, что смогу это сделать. Однако я нахожу его менее читаемым, потому что при чтении функции logIn () неясно, что на самом деле делает account ().

Ответ №4:

Ваш заголовок немного сбивает с толку, поскольку вы действительно можете передать метод. В Python функции являются первоклассными, что означает, что вы можете передавать их как любое значение.

Однако ваш текст показывает, что вы хотите сделать что-то еще.

Python действительно возвращает несколько значений как одно значение, кортеж значений.

 return 1, 2
  

на самом деле это то же самое, что

 return (1, 2)
  

Однако, если вам нужно распаковать эти значения, как в вашем случае, есть несколько способов добиться этого.

Вы можете распаковать их в переменные:

 usn, psw = myObject.getAccount()
  

Или вы можете «развернуть» их прямо в вызов функции:

 myModule.logIn(*myObject.getAccount())
  

Для этого требуется, чтобы количество аргументов совпадало с размером кортежа (для функции с 2 аргументами требуется кортеж (x, y) )

Если вы вместо этого хотите передать метод, вы можете это сделать, но вам нужно быть осторожным, чтобы не вызывать его:

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

logIn(myObject.getAccount)
  

Комментарии:

1. Спасибо за предоставление подробного ответа. Я не знал большей части того, что вы объяснили. Как я прокомментировал выше, я не уверен в том, как использовать * функции, хотя это, кажется, самый элегантный способ достичь того, что я хочу сделать. Также я не совсем уверен, что понимаю, что вы сказали о названии этого вопроса.

2. @Benjamin: Не обращайте внимания на заголовок. Это был просто очень тупой способ сказать, что я вас неправильно понял 🙂 Можно сказать, что * оператор сопоставляет каждое значение итерации с позиционным аргументом в вызове функции (это работает и со списками). Существует также ** оператор, который распаковывает dict в аргументы ключевого слова.