2015-08-20 3 views
1

может кто-нибудь помочь мне выяснить, почему первый код работает и второй Dont ?:Python * арг AttributeError

Рабочий код

alias = [] 
alias.append(cx_Oracle.connect('%s/%[email protected]%s' % (username, password, base))) 
solve(*alias, **binds) 

def solve(*alias, **binds): 
    cur = alias[0].cursor() 

Не работает код

alias = [] 
alias.append(cx_Oracle.connect('%s/%[email protected]%s' % (username, password, base))) 
solve(alias, binds) 

def solve(*alias, **binds): 
    cur = alias[0].cursor() 

Ошибка

AttributeError: 'list' object has no attribute 'cursor'

*** Tha nks все! Это было очень полезно!

ответ

0

Это описано в Keyword Arguments**binds, Arbitrary Argument Lists*alias и Unpacking Argument Listssolve(alias, binds) против solve(*alias, **binds).

При вызове solve(alias, binds) оба аргумента alias и binds присваиваются формальному параметру *alias.

Это результат alias[0], являющийся списком [ cx_Oracle.connect('%s/%[email protected]%s' % (username, password, base)) ], а не только первым элементом cx_Oracle.connect('%s/%[email protected]%s' % (username, password, base)). И список [...] не имеет атрибута «курсор», так как Python метко жалуется.

1

alias - это tuple всех аргументов, которые были переданы. Если вы пройдете мимо, то list, alias будет tuple, который содержит один элемент, list. Вместо этого вы хотите распаковать этот list на отдельные элементы. Тогда alias будет tuple, который содержит каждый из этих элементов.

>>> def a(*arg): 
...  print(arg) 
... 
>>> a([1,2]) 
([1, 2],) 
>>> a(*[1,2]) 
(1, 2) 

То же самое относится и к **binds (если вы используете его) - это не ожидая словаря, он ожидает в элементы из словаря, так что если у вас уже готовый словарь, вы бы должны передать его в своей распакованной форме с **.

3

Проблема возникает из-за того, что во втором случае, поскольку вы не распаковываете список или словарь при передаче в качестве аргумента функции, они передаются в alias как таковые (то есть внутри функции решения alias) это список alias, а второй элемент alias - это словарь binds).

Пример показать это -

>>> def a(*nargs, **kwargs): 
...  print('nargs : ',nargs) 
...  print('kwargs : ',kwargs) 
... 
>>> x = [1,2,3] 
>>> d = {'a':2,'b':4} 
>>> a(*x,**d) 
nargs : (1, 2, 3) 
kwargs : {'a': 2, 'b': 4} 
>>> a(x,d) 
nargs : ([1, 2, 3], {'a': 2, 'b': 4}) 
kwargs : {} 
1

solve принимает любое количество аргументов и именованных аргументов. аргумент *alias - это список данных нормальных аргументов, а **binds - это список заданных аргументов ключевого слова.

*aliasраспаковываетalias к аргументам, например:

array = [1, 2, 3] 
solve(*array) # same as solve(1, 2, 3) 

Аналогично, **binds распаковывает binds в качестве ключевого слова аргументы.

map = {"a": 1, "b": 2, "c": 3} 
solve(**map) # same as solve(a = 1, b = 2, c = 3) 

Это рабочий код.

solve(*alias, **binds) 

Если alias был [1, 2, 3] и binds был {"a": 1, "b": 2, "c": 3}, то этот вызов эквивалентен

solve(1, 2, 3, a = 1, b = 2, c = 3) 

Это приводит к следующему:

def solve(*alias, **binds): 
    # alias is now the argument list 
    # [1, 2, 3] 
    # bind is now the keyword argument map 
    # {"a": 1, "b": 2, "c": 3} 
    cur = alias[0].cursor() 

Это другая.

solve(alias, binds) 

Опять же, давайте посмотрим, что произойдет, если alias был [1, 2, 3] и binds был {"a": 1, "b": 2, "c": 3}. Тогда этот вызов эквивалентен

solve([1, 2, 3], {"a": 1, "b": 2, "c": 3}) 

def solve(*alias, **binds): 
    # alias is now the argument list 
    # [[1, 2, 3], {"a": 1, "b": 2, "c": 3}] 
    # bind is now keyword argument map 
    # {} 
    cur = alias[0].cursor() 
+0

Общепринятый термин «распаковывается», а не «распространяется», между прочим. – TigerhawkT3

+0

@ TigerhawkT3 Спасибо, слишком привык к терминам ES6 в последнее время. – Pietu1998

Смежные вопросы