#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
в аргументы ключевого слова.