Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit025e9eb

Browse files
committed
PEP 448: additional unpacking generalizations (closes#2292)
Patch by Neil Girdhar.
1 parent4ccc151 commit025e9eb

26 files changed

+2662
-2116
lines changed

‎Grammar/Grammar

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -111,17 +111,29 @@ subscript: test | [test] ':' [test] [sliceop]
111111
sliceop: ':' [test]
112112
exprlist: (expr|star_expr) (',' (expr|star_expr))* [',']
113113
testlist: test (',' test)* [',']
114-
dictorsetmaker: ( (test ':' test (comp_for | (',' test ':' test)* [','])) |
115-
(test (comp_for | (',' test)* [','])) )
114+
dictorsetmaker: ( ((test ':' test | '**' expr)
115+
(comp_for | (',' (test ':' test | '**' expr))* [','])) |
116+
((test | star_expr)
117+
(comp_for | (',' (test | star_expr))* [','])) )
116118

117119
classdef: 'class' NAME ['(' [arglist] ')'] ':' suite
118120

119-
arglist: (argument ',')* (argument [',']
120-
|'*' test (',' argument)* [',' '**' test]
121-
|'**' test)
121+
arglist: argument (',' argument)* [',']
122+
122123
# The reason that keywords are test nodes instead of NAME is that using NAME
123124
# results in an ambiguity. ast.c makes sure it's a NAME.
124-
argument: test [comp_for] | test '=' test # Really [keyword '='] test
125+
# "test '=' test" is really "keyword '=' test", but we have no such token.
126+
# These need to be in a single rule to avoid grammar that is ambiguous
127+
# to our LL(1) parser. Even though 'test' includes '*expr' in star_expr,
128+
# we explicitly match '*' here, too, to give it proper precedence.
129+
# Illegal combinations and orderings are blocked in ast.c:
130+
# multiple (test comp_for) arguements are blocked; keyword unpackings
131+
# that precede iterable unpackings are blocked; etc.
132+
argument: ( test [comp_for] |
133+
test '=' test |
134+
'**' expr |
135+
star_expr )
136+
125137
comp_iter: comp_for | comp_if
126138
comp_for: 'for' exprlist 'in' or_test [comp_iter]
127139
comp_if: 'if' test_nocond [comp_iter]

‎Include/Python-ast.h

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,6 @@ struct _stmt {
8484
identifiername;
8585
asdl_seq*bases;
8686
asdl_seq*keywords;
87-
expr_tystarargs;
88-
expr_tykwargs;
8987
asdl_seq*body;
9088
asdl_seq*decorator_list;
9189
}ClassDef;
@@ -263,8 +261,6 @@ struct _expr {
263261
expr_tyfunc;
264262
asdl_seq*args;
265263
asdl_seq*keywords;
266-
expr_tystarargs;
267-
expr_tykwargs;
268264
}Call;
269265

270266
struct {
@@ -406,11 +402,10 @@ mod_ty _Py_Suite(asdl_seq * body, PyArena *arena);
406402
stmt_ty_Py_FunctionDef(identifiername,arguments_tyargs,asdl_seq*body,
407403
asdl_seq*decorator_list,expr_tyreturns,intlineno,
408404
intcol_offset,PyArena*arena);
409-
#defineClassDef(a0,a1,a2,a3,a4,a5,a6,a7,a8,a9) _Py_ClassDef(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)
405+
#defineClassDef(a0,a1,a2,a3,a4,a5,a6,a7) _Py_ClassDef(a0, a1, a2, a3, a4, a5, a6, a7)
410406
stmt_ty_Py_ClassDef(identifiername,asdl_seq*bases,asdl_seq*keywords,
411-
expr_tystarargs,expr_tykwargs,asdl_seq*body,
412-
asdl_seq*decorator_list,intlineno,intcol_offset,
413-
PyArena*arena);
407+
asdl_seq*body,asdl_seq*decorator_list,intlineno,
408+
intcol_offset,PyArena*arena);
414409
#defineReturn(a0,a1,a2,a3) _Py_Return(a0, a1, a2, a3)
415410
stmt_ty_Py_Return(expr_tyvalue,intlineno,intcol_offset,PyArena*arena);
416411
#defineDelete(a0,a1,a2,a3) _Py_Delete(a0, a1, a2, a3)
@@ -504,10 +499,9 @@ expr_ty _Py_YieldFrom(expr_ty value, int lineno, int col_offset, PyArena
504499
#defineCompare(a0,a1,a2,a3,a4,a5) _Py_Compare(a0, a1, a2, a3, a4, a5)
505500
expr_ty_Py_Compare(expr_tyleft,asdl_int_seq*ops,asdl_seq*comparators,
506501
intlineno,intcol_offset,PyArena*arena);
507-
#defineCall(a0,a1,a2,a3,a4,a5,a6,a7) _Py_Call(a0, a1, a2, a3, a4, a5, a6, a7)
508-
expr_ty_Py_Call(expr_tyfunc,asdl_seq*args,asdl_seq*keywords,expr_ty
509-
starargs,expr_tykwargs,intlineno,intcol_offset,PyArena
510-
*arena);
502+
#defineCall(a0,a1,a2,a3,a4,a5) _Py_Call(a0, a1, a2, a3, a4, a5)
503+
expr_ty_Py_Call(expr_tyfunc,asdl_seq*args,asdl_seq*keywords,int
504+
lineno,intcol_offset,PyArena*arena);
511505
#defineNum(a0,a1,a2,a3) _Py_Num(a0, a1, a2, a3)
512506
expr_ty_Py_Num(objectn,intlineno,intcol_offset,PyArena*arena);
513507
#defineStr(a0,a1,a2,a3) _Py_Str(a0, a1, a2, a3)

‎Include/dictobject.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,10 @@ PyAPI_FUNC(int) PyDict_Merge(PyObject *mp,
105105
PyObject*other,
106106
intoverride);
107107

108+
#ifndefPy_LIMITED_API
109+
PyAPI_FUNC(PyObject*)_PyDictView_Intersect(PyObject*self,PyObject*other);
110+
#endif
111+
108112
/* PyDict_MergeFromSeq2 updates/merges from an iterable object producing
109113
iterable objects of length 2. If override is true, the last occurrence
110114
of a key wins, else the first. The Python dict constructor dict(seq2)

‎Include/opcode.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,11 @@ extern "C" {
111111
#defineSET_ADD 146
112112
#defineMAP_ADD 147
113113
#defineLOAD_CLASSDEREF 148
114+
#defineBUILD_LIST_UNPACK 149
115+
#defineBUILD_MAP_UNPACK 150
116+
#defineBUILD_MAP_UNPACK_WITH_CALL151
117+
#defineBUILD_TUPLE_UNPACK 152
118+
#defineBUILD_SET_UNPACK 153
114119

115120
/* EXCEPT_HANDLER is a special, implicit block type which is created when
116121
entering an except handler. It is not an opcode but we define it here

‎Lib/importlib/_bootstrap_external.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,12 +220,13 @@ def _write_atomic(path, data, mode=0o666):
220220
# Python 3.4a4 3300 (more changes to __qualname__ computation)
221221
# Python 3.4rc2 3310 (alter __qualname__ computation)
222222
# Python 3.5a0 3320 (matrix multiplication operator)
223+
# Python 3.5b1 3330 (PEP 448: Additional Unpacking Generalizations)
223224
#
224225
# MAGIC must change whenever the bytecode emitted by the compiler may no
225226
# longer be understood by older implementations of the eval loop (usually
226227
# due to the addition of new opcodes).
227228

228-
MAGIC_NUMBER= (3320).to_bytes(2,'little')+b'\r\n'
229+
MAGIC_NUMBER= (3330).to_bytes(2,'little')+b'\r\n'
229230
_RAW_MAGIC_NUMBER=int.from_bytes(MAGIC_NUMBER,'little')# For import.c
230231

231232
_PYCACHE='__pycache__'

‎Lib/opcode.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,4 +200,10 @@ def jabs_op(name, op):
200200
def_op('EXTENDED_ARG',144)
201201
EXTENDED_ARG=144
202202

203+
def_op('BUILD_LIST_UNPACK',149)
204+
def_op('BUILD_MAP_UNPACK',150)
205+
def_op('BUILD_MAP_UNPACK_WITH_CALL',151)
206+
def_op('BUILD_TUPLE_UNPACK',152)
207+
def_op('BUILD_SET_UNPACK',153)
208+
203209
deldef_op,name_op,jrel_op,jabs_op

‎Lib/test/test_ast.py

Lines changed: 21 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -427,17 +427,17 @@ def test_dump(self):
427427
self.assertEqual(ast.dump(node),
428428
"Module(body=[Expr(value=Call(func=Name(id='spam', ctx=Load()), "
429429
"args=[Name(id='eggs', ctx=Load()), Str(s='and cheese')], "
430-
"keywords=[], starargs=None, kwargs=None))])"
430+
"keywords=[]))])"
431431
)
432432
self.assertEqual(ast.dump(node,annotate_fields=False),
433433
"Module([Expr(Call(Name('spam', Load()), [Name('eggs', Load()), "
434-
"Str('and cheese')], [], None, None))])"
434+
"Str('and cheese')], []))])"
435435
)
436436
self.assertEqual(ast.dump(node,include_attributes=True),
437437
"Module(body=[Expr(value=Call(func=Name(id='spam', ctx=Load(), "
438438
"lineno=1, col_offset=0), args=[Name(id='eggs', ctx=Load(), "
439439
"lineno=1, col_offset=5), Str(s='and cheese', lineno=1, "
440-
"col_offset=11)], keywords=[],starargs=None, kwargs=None,"
440+
"col_offset=11)], keywords=[], "
441441
"lineno=1, col_offset=0), lineno=1, col_offset=0)])"
442442
)
443443

@@ -453,16 +453,16 @@ def test_copy_location(self):
453453
deftest_fix_missing_locations(self):
454454
src=ast.parse('write("spam")')
455455
src.body.append(ast.Expr(ast.Call(ast.Name('spam',ast.Load()),
456-
[ast.Str('eggs')], [],None,None)))
456+
[ast.Str('eggs')], [])))
457457
self.assertEqual(src,ast.fix_missing_locations(src))
458458
self.assertEqual(ast.dump(src,include_attributes=True),
459459
"Module(body=[Expr(value=Call(func=Name(id='write', ctx=Load(), "
460460
"lineno=1, col_offset=0), args=[Str(s='spam', lineno=1, "
461-
"col_offset=6)], keywords=[],starargs=None, kwargs=None,"
461+
"col_offset=6)], keywords=[], "
462462
"lineno=1, col_offset=0), lineno=1, col_offset=0), "
463463
"Expr(value=Call(func=Name(id='spam', ctx=Load(), lineno=1, "
464464
"col_offset=0), args=[Str(s='eggs', lineno=1, col_offset=0)], "
465-
"keywords=[],starargs=None, kwargs=None,lineno=1, "
465+
"keywords=[], lineno=1, "
466466
"col_offset=0), lineno=1, col_offset=0)])"
467467
)
468468

@@ -487,8 +487,7 @@ def test_iter_fields(self):
487487
node=ast.parse('foo()',mode='eval')
488488
d=dict(ast.iter_fields(node.body))
489489
self.assertEqual(d.pop('func').id,'foo')
490-
self.assertEqual(d, {'keywords': [],'kwargs':None,
491-
'args': [],'starargs':None})
490+
self.assertEqual(d, {'keywords': [],'args': []})
492491

493492
deftest_iter_child_nodes(self):
494493
node=ast.parse("spam(23, 42, eggs='leek')",mode='eval')
@@ -604,8 +603,7 @@ def fac(args):
604603
self._check_arguments(fac,self.stmt)
605604

606605
deftest_classdef(self):
607-
defcls(bases=None,keywords=None,starargs=None,kwargs=None,
608-
body=None,decorator_list=None):
606+
defcls(bases=None,keywords=None,body=None,decorator_list=None):
609607
ifbasesisNone:
610608
bases= []
611609
ifkeywordsisNone:
@@ -614,16 +612,12 @@ def cls(bases=None, keywords=None, starargs=None, kwargs=None,
614612
body= [ast.Pass()]
615613
ifdecorator_listisNone:
616614
decorator_list= []
617-
returnast.ClassDef("myclass",bases,keywords,starargs,
618-
kwargs,body,decorator_list)
615+
returnast.ClassDef("myclass",bases,keywords,
616+
body,decorator_list)
619617
self.stmt(cls(bases=[ast.Name("x",ast.Store())]),
620618
"must have Load context")
621619
self.stmt(cls(keywords=[ast.keyword("x",ast.Name("x",ast.Store()))]),
622620
"must have Load context")
623-
self.stmt(cls(starargs=ast.Name("x",ast.Store())),
624-
"must have Load context")
625-
self.stmt(cls(kwargs=ast.Name("x",ast.Store())),
626-
"must have Load context")
627621
self.stmt(cls(body=[]),"empty body on ClassDef")
628622
self.stmt(cls(body=[None]),"None disallowed")
629623
self.stmt(cls(decorator_list=[ast.Name("x",ast.Store())]),
@@ -854,20 +848,12 @@ def test_call(self):
854848
func=ast.Name("x",ast.Load())
855849
args= [ast.Name("y",ast.Load())]
856850
keywords= [ast.keyword("w",ast.Name("z",ast.Load()))]
857-
stararg=ast.Name("p",ast.Load())
858-
kwarg=ast.Name("q",ast.Load())
859-
call=ast.Call(ast.Name("x",ast.Store()),args,keywords,stararg,
860-
kwarg)
851+
call=ast.Call(ast.Name("x",ast.Store()),args,keywords)
861852
self.expr(call,"must have Load context")
862-
call=ast.Call(func, [None],keywords,stararg,kwarg)
853+
call=ast.Call(func, [None],keywords)
863854
self.expr(call,"None disallowed")
864855
bad_keywords= [ast.keyword("w",ast.Name("z",ast.Store()))]
865-
call=ast.Call(func,args,bad_keywords,stararg,kwarg)
866-
self.expr(call,"must have Load context")
867-
call=ast.Call(func,args,keywords,ast.Name("z",ast.Store()),kwarg)
868-
self.expr(call,"must have Load context")
869-
call=ast.Call(func,args,keywords,stararg,
870-
ast.Name("w",ast.Store()))
856+
call=ast.Call(func,args,bad_keywords)
871857
self.expr(call,"must have Load context")
872858

873859
deftest_num(self):
@@ -957,8 +943,8 @@ def main():
957943
('Module', [('FunctionDef', (1,0),'f', ('arguments', [], ('arg', (1,7),'args',None), [], [],None, []), [('Pass', (1,14))], [],None)]),
958944
('Module', [('FunctionDef', (1,0),'f', ('arguments', [],None, [], [], ('arg', (1,8),'kwargs',None), []), [('Pass', (1,17))], [],None)]),
959945
('Module', [('FunctionDef', (1,0),'f', ('arguments', [('arg', (1,6),'a',None), ('arg', (1,9),'b',None), ('arg', (1,14),'c',None), ('arg', (1,22),'d',None), ('arg', (1,28),'e',None)], ('arg', (1,35),'args',None), [('arg', (1,41),'f',None)], [('Num', (1,43),42)], ('arg', (1,49),'kwargs',None), [('Num', (1,11),1), ('NameConstant', (1,16),None), ('List', (1,24), [], ('Load',)), ('Dict', (1,30), [], [])]), [('Pass', (1,58))], [],None)]),
960-
('Module', [('ClassDef', (1,0),'C', [], [],None,None,[('Pass', (1,8))], [])]),
961-
('Module', [('ClassDef', (1,0),'C', [('Name', (1,8),'object', ('Load',))], [],None,None,[('Pass', (1,17))], [])]),
946+
('Module', [('ClassDef', (1,0),'C', [], [], [('Pass', (1,8))], [])]),
947+
('Module', [('ClassDef', (1,0),'C', [('Name', (1,8),'object', ('Load',))], [], [('Pass', (1,17))], [])]),
962948
('Module', [('FunctionDef', (1,0),'f', ('arguments', [],None, [], [],None, []), [('Return', (1,8), ('Num', (1,15),1))], [],None)]),
963949
('Module', [('Delete', (1,0), [('Name', (1,4),'v', ('Del',))])]),
964950
('Module', [('Assign', (1,0), [('Name', (1,0),'v', ('Store',))], ('Num', (1,4),1))]),
@@ -968,7 +954,7 @@ def main():
968954
('Module', [('If', (1,0), ('Name', (1,3),'v', ('Load',)), [('Pass', (1,5))], [])]),
969955
('Module', [('With', (1,0), [('withitem', ('Name', (1,5),'x', ('Load',)), ('Name', (1,10),'y', ('Store',)))], [('Pass', (1,13))])]),
970956
('Module', [('With', (1,0), [('withitem', ('Name', (1,5),'x', ('Load',)), ('Name', (1,10),'y', ('Store',))), ('withitem', ('Name', (1,13),'z', ('Load',)), ('Name', (1,18),'q', ('Store',)))], [('Pass', (1,21))])]),
971-
('Module', [('Raise', (1,0), ('Call', (1,6), ('Name', (1,6),'Exception', ('Load',)), [('Str', (1,16),'string')], [],None,None),None)]),
957+
('Module', [('Raise', (1,0), ('Call', (1,6), ('Name', (1,6),'Exception', ('Load',)), [('Str', (1,16),'string')], []),None)]),
972958
('Module', [('Try', (1,0), [('Pass', (2,2))], [('ExceptHandler', (3,0), ('Name', (3,7),'Exception', ('Load',)),None, [('Pass', (4,2))])], [], [])]),
973959
('Module', [('Try', (1,0), [('Pass', (2,2))], [], [], [('Pass', (4,2))])]),
974960
('Module', [('Assert', (1,0), ('Name', (1,7),'v', ('Load',)),None)]),
@@ -998,14 +984,14 @@ def main():
998984
('Expression', ('BinOp', (1,0), ('Name', (1,0),'a', ('Load',)), ('Add',), ('Name', (1,4),'b', ('Load',)))),
999985
('Expression', ('UnaryOp', (1,0), ('Not',), ('Name', (1,4),'v', ('Load',)))),
1000986
('Expression', ('Lambda', (1,0), ('arguments', [],None, [], [],None, []), ('NameConstant', (1,7),None))),
1001-
('Expression', ('Dict', (1,0), [('Num', (1,2),1)], [('Num', (1,4),2)])),
987+
('Expression', ('Dict', (1,2), [('Num', (1,2),1)], [('Num', (1,4),2)])),
1002988
('Expression', ('Dict', (1,0), [], [])),
1003-
('Expression', ('Set', (1,0), [('NameConstant', (1,1),None)])),
1004-
('Expression', ('Dict', (1,0), [('Num', (2,6),1)], [('Num', (4,10),2)])),
989+
('Expression', ('Set', (1,1), [('NameConstant', (1,1),None)])),
990+
('Expression', ('Dict', (2,6), [('Num', (2,6),1)], [('Num', (4,10),2)])),
1005991
('Expression', ('ListComp', (1,1), ('Name', (1,1),'a', ('Load',)), [('comprehension', ('Name', (1,7),'b', ('Store',)), ('Name', (1,12),'c', ('Load',)), [('Name', (1,17),'d', ('Load',))])])),
1006992
('Expression', ('GeneratorExp', (1,1), ('Name', (1,1),'a', ('Load',)), [('comprehension', ('Name', (1,7),'b', ('Store',)), ('Name', (1,12),'c', ('Load',)), [('Name', (1,17),'d', ('Load',))])])),
1007993
('Expression', ('Compare', (1,0), ('Num', (1,0),1), [('Lt',), ('Lt',)], [('Num', (1,4),2), ('Num', (1,8),3)])),
1008-
('Expression', ('Call', (1,0), ('Name', (1,0),'f', ('Load',)), [('Num', (1,2),1), ('Num', (1,4),2)], [('keyword','c', ('Num', (1,8),3))],('Name',(1,11),'d', ('Load',)), ('Name', (1,15),'e', ('Load',)))),
994+
('Expression', ('Call', (1,0), ('Name', (1,0),'f', ('Load',)), [('Num', (1,2),1), ('Num', (1,4),2), ('Starred',(1,10), ('Name', (1,11),'d', ('Load',)), ('Load',))],[('keyword','c', ('Num', (1,8),3)), ('keyword',None, ('Name', (1,15),'e', ('Load',)))])),
1009995
('Expression', ('Num', (1,0),10)),
1010996
('Expression', ('Str', (1,0),'string')),
1011997
('Expression', ('Attribute', (1,0), ('Name', (1,0),'a', ('Load',)),'b', ('Load',))),
@@ -1016,6 +1002,6 @@ def main():
10161002
('Expression', ('Tuple', (1,0), [('Num', (1,0),1), ('Num', (1,2),2), ('Num', (1,4),3)], ('Load',))),
10171003
('Expression', ('Tuple', (1,1), [('Num', (1,1),1), ('Num', (1,3),2), ('Num', (1,5),3)], ('Load',))),
10181004
('Expression', ('Tuple', (1,0), [], ('Load',))),
1019-
('Expression', ('Call', (1,0), ('Attribute', (1,0), ('Attribute', (1,0), ('Attribute', (1,0), ('Name', (1,0),'a', ('Load',)),'b', ('Load',)),'c', ('Load',)),'d', ('Load',)), [('Subscript', (1,8), ('Attribute', (1,8), ('Name', (1,8),'a', ('Load',)),'b', ('Load',)), ('Slice', ('Num', (1,12),1), ('Num', (1,14),2),None), ('Load',))], [],None,None)),
1005+
('Expression', ('Call', (1,0), ('Attribute', (1,0), ('Attribute', (1,0), ('Attribute', (1,0), ('Name', (1,0),'a', ('Load',)),'b', ('Load',)),'c', ('Load',)),'d', ('Load',)), [('Subscript', (1,8), ('Attribute', (1,8), ('Name', (1,8),'a', ('Load',)),'b', ('Load',)), ('Slice', ('Num', (1,12),1), ('Num', (1,14),2),None), ('Load',))], [])),
10201006
]
10211007
main()

‎Lib/test/test_extcall.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,24 +34,46 @@
3434
(1, 2, 3, 4, 5) {}
3535
>>> f(1, 2, 3, *[4, 5])
3636
(1, 2, 3, 4, 5) {}
37+
>>> f(*[1, 2, 3], 4, 5)
38+
(1, 2, 3, 4, 5) {}
3739
>>> f(1, 2, 3, *UserList([4, 5]))
3840
(1, 2, 3, 4, 5) {}
41+
>>> f(1, 2, 3, *[4, 5], *[6, 7])
42+
(1, 2, 3, 4, 5, 6, 7) {}
43+
>>> f(1, *[2, 3], 4, *[5, 6], 7)
44+
(1, 2, 3, 4, 5, 6, 7) {}
45+
>>> f(*UserList([1, 2]), *UserList([3, 4]), 5, *UserList([6, 7]))
46+
(1, 2, 3, 4, 5, 6, 7) {}
3947
4048
Here we add keyword arguments
4149
4250
>>> f(1, 2, 3, **{'a':4, 'b':5})
4351
(1, 2, 3) {'a': 4, 'b': 5}
52+
>>> f(1, 2, **{'a': -1, 'b': 5}, **{'a': 4, 'c': 6})
53+
Traceback (most recent call last):
54+
...
55+
TypeError: f() got multiple values for keyword argument 'a'
56+
>>> f(1, 2, **{'a': -1, 'b': 5}, a=4, c=6)
57+
Traceback (most recent call last):
58+
...
59+
TypeError: f() got multiple values for keyword argument 'a'
4460
>>> f(1, 2, 3, *[4, 5], **{'a':6, 'b':7})
4561
(1, 2, 3, 4, 5) {'a': 6, 'b': 7}
4662
>>> f(1, 2, 3, x=4, y=5, *(6, 7), **{'a':8, 'b': 9})
4763
(1, 2, 3, 6, 7) {'a': 8, 'b': 9, 'x': 4, 'y': 5}
64+
>>> f(1, 2, 3, *[4, 5], **{'c': 8}, **{'a':6, 'b':7})
65+
(1, 2, 3, 4, 5) {'a': 6, 'b': 7, 'c': 8}
66+
>>> f(1, 2, 3, *(4, 5), x=6, y=7, **{'a':8, 'b': 9})
67+
(1, 2, 3, 4, 5) {'a': 8, 'b': 9, 'x': 6, 'y': 7}
4868
4969
>>> f(1, 2, 3, **UserDict(a=4, b=5))
5070
(1, 2, 3) {'a': 4, 'b': 5}
5171
>>> f(1, 2, 3, *(4, 5), **UserDict(a=6, b=7))
5272
(1, 2, 3, 4, 5) {'a': 6, 'b': 7}
5373
>>> f(1, 2, 3, x=4, y=5, *(6, 7), **UserDict(a=8, b=9))
5474
(1, 2, 3, 6, 7) {'a': 8, 'b': 9, 'x': 4, 'y': 5}
75+
>>> f(1, 2, 3, *(4, 5), x=6, y=7, **UserDict(a=8, b=9))
76+
(1, 2, 3, 4, 5) {'a': 8, 'b': 9, 'x': 6, 'y': 7}
5577
5678
Examples with invalid arguments (TypeErrors). We're also testing the function
5779
names in the exception messages.

‎Lib/test/test_grammar.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,8 +296,12 @@ def f(*args, **kwargs):
296296
returnargs,kwargs
297297
self.assertEqual(f(1,x=2,*[3,4],y=5), ((1,3,4),
298298
{'x':2,'y':5}))
299-
self.assertRaises(SyntaxError,eval,"f(1, *(2,3), 4)")
299+
self.assertEqual(f(1,*(2,3),4), ((1,2,3,4), {}))
300300
self.assertRaises(SyntaxError,eval,"f(1, x=2, *(3,4), x=5)")
301+
self.assertEqual(f(**{'eggs':'scrambled','spam':'fried'}),
302+
((), {'eggs':'scrambled','spam':'fried'}))
303+
self.assertEqual(f(spam='fried',**{'eggs':'scrambled'}),
304+
((), {'eggs':'scrambled','spam':'fried'}))
301305

302306
# argument annotation tests
303307
deff(x)->list:pass

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp