Değişken fonksiyon jeneratörü olarak
Kimseye bir işlev için yalnızca konumsal bağımsız değişken olarak bir jeneratör geçen özel kurallar var gibi görünüyor neden açıklayabilir mi?
Eğer var ise:
>>> def f(*args):
>>> print "Success!"
>>> print args
Bu beklendiği gibi çalışır.
>>> f(1, *[2]) Success! (1, 2)
Bu beklendiği gibi çalışmaz.
>>> f(*[2], 1) File "<stdin>", line 1 SyntaxError: only named arguments may follow *expression
Bu beklendiği gibi çalışır
>>> f(1 for x in [1], *[2]) Success! (generator object <genexpr> at 0x7effe06bdcd0>, 2)
Bu çalışır, ama neden anlamıyorum. Bunu 2 şekilde başarısız) olmamalı
>>> f(*[2], 1 for x in [1]) Success! (generator object <genexpr> at 0x7effe06bdcd0>, 2)
CEVAP
Hem 3. ve 4.gerekirbütün Python sürümlerinde sözdizimi hataları olabilir.Ancak Python sürümleri etkileyen bir hata buldum sonradan posted to the Python issue tracker olan 2.5 - 3.4. Bu hata nedeniyle, unparenthesized jeneratör ifadesi *args
ve/veya **kwargs
sadece eşlik etti Eğer bir işlev için bağımsız değişken olarak kabul edilmiştir. Python 2.6 iken, her iki durumda izin verilen 3. ve 4., Python 2.5 tek durum 3 izin verdi. - yine de documented grammar karşı olmuştur
call ::= primary "(" [argument_list [","]
| expression genexpr_for] ")"
yani belgelere bir işlev çağrısı primary
oluşur (bir çağrı veren ifade) diyor, parantez içinde izlediyabir bağımsız değişken listesiyaunparenthesized üreteç ifadesi sadece bir;
ve argüman listesi içinde, tüm jeneratör ifadeler parantez içinde olmalıdır.
Bu hata, bilinen hiç bir şeye sahip değilmiş gibi görünse de), Python 3.5 prereleases sabit olmuştu. Python ile 3.5 parantez içinde her zaman işlevi tek bağımsız değişken olduğu sürece jeneratör bir ifade mi gereklidir:
Python 3.5.0a4 (default:a3f2b171b765, May 19 2015, 16:14:41)
[GCC 4.9.2] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> f(1 for i in [42], *a)
File "<stdin>", line 1
SyntaxError: Generator expression must be parenthesized if not sole argument
Bu şimdi What's New in Python 3.5, teşekkürler, bu hatayı tespit DeTeReR belgelenmiştir.
Hata analizi
Bir değişiklik 58**: 2.6 Python için yapılmış
Ayrıca yasal *bir besten sonra anahtar kelime argümanlar sunmak oldu bir işlev çağrısı için bağımsız değişken.
>>> def f(*args, **kw): ... print args, kw ... >>> f(1,2,3, *(4,5,6), keyword=13) (1, 2, 3, 4, 5, 6) {'keyword': 13}
Daha önce bu sözdizimi bir hata olurdu. (Amaury katkıda Forgeot d'Arc; sorun 3473.)
Ancak, 2.6 grammar Python anahtar kelime argümanlar, konumsal bağımsız değişkenler, ya da çıplak jeneratör ifadeler arasında herhangi bir ayrım yapmaz - türü çözümleyici 32**.
Python kuralları gereğince, jeneratör bir ifade işlevi için tek argüman ise programlama dilinde * sembolü olmalı. Bu Python/ast.c
doğrulanır:
for (i = 0; i < NCH(n); i ) {
node *ch = CHILD(n, i);
if (TYPE(ch) == argument) {
if (NCH(ch) == 1)
nargs ;
else if (TYPE(CHILD(ch, 1)) == gen_for)
ngens ;
else
nkeywords ;
}
}
if (ngens > 1 || (ngens && (nargs || nkeywords))) {
ast_error(n, "Generator expression must be parenthesized "
"if not sole argument");
return NULL;
}
Ancak bu işlevdeğil*args
hiç dikkate - özellikle sadece sıradan konumsal bağımsız değişkenleri ve anahtar kelime argümanlar arar.
Aynı işlevi daha aşağı, bir hata iletisi non-keyword arg after keyword arg oluşturulur
if (TYPE(ch) == argument) {
expr_ty e;
if (NCH(ch) == 1) {
if (nkeywords) {
ast_error(CHILD(ch, 0),
"non-keyword arg after keyword arg");
return NULL;
}
...
Ama bu yine değişkenler için geçerlidirdeğilevidenced by the else if
statement jeneratör ifadeler unparenthesized:
else if (TYPE(CHILD(ch, 1)) == gen_for) {
e = ast_for_genexp(c, ch);
if (!e)
return NULL;
asdl_seq_SET(args, nargs , e);
}
Böylece unparenthesized jeneratör bir ifade pass kayma izin verildi.
Şimdi Python 3.5 *args
herhangi bir işlev çağrısı, bu yüzden kullanabilirsiniz
Grammar bunun için barındıracak şekilde değiştirildi:
arglist: argument (',' argument)* [',']
ve
argument: ( test [comp_for] |
test '=' test |
'**' test |
'*' test )
for (i = 0; i < NCH(n); i ) {
node *ch = CHILD(n, i);
if (TYPE(ch) == argument) {
if (NCH(ch) == 1)
nargs ;
else if (TYPE(CHILD(ch, 1)) == comp_for)
ngens ;
else if (TYPE(CHILD(ch, 0)) == STAR)
nargs ;
else
/* TYPE(CHILD(ch, 0)) == DOUBLESTAR or keyword argument */
nkeywords ;
}
}
Böylece hata düzeltme.
Ancak yanlışlıkla değişiklik geçerli görünümlü yapılar olduğunu
func(i for i in [42], *args)
ve
func(i for i in [42], **kwargs)
unparenthesized jeneratör öncelikli olduğu *args
**kwargs
şimdi çalışmayı durdurdu.
Bu hata bulmak için, farklı Python sürümleri denedim. 2.5 SyntaxError
olsun istiyorum:
Python 2.5.5 (r255:77872, Nov 28 2010, 16:43:48)
[GCC 4.4.5] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> f(*[1], 2 for x in [2])
File "<stdin>", line 1
f(*[1], 2 for x in [2])
Ve bu Python 3.5 bazı yayın öncesi önce sabit oldu:
Python 3.5.0a4 (default:a3f2b171b765, May 19 2015, 16:14:41)
[GCC 4.9.2] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> f(*[1], 2 for x in [2])
File "<stdin>", line 1
SyntaxError: Generator expression must be parenthesized if not sole argument
Ancak, programlama dilinde * sembolü jeneratör ifadesi, Python 3.5, ama Python 3.4 değil çalışmaz çalışır:
f(*[1], (2 for x in [2]))
Ve bu ipucu. Python 3.5 *splatting
genel; her yerde bir işlev çağrısı kullanabilirsiniz:
>>> print(*range(5), 42)
0 1 2 3 4 42
Gerçek hata (jeneratör *star
ile çalışmak parantez olmadan)olduPython 3.4 ve 3.5 arasında ne değişti gerçekten Python hata bulunamadı 3.5 ve sabit
Neden anonim fonksiyon tanımlama ve de...
nasıl bir python değişken bir fonksiyo...
Javascript nesne adı olarak değişken k...
'değişken' anahtar kelime he...
Bir şekilde Git submodule olarak Değiş...