1

I am wondering how a function is processed in a certain language due to the two errors caused by the following two functions in Python.

def fun(a=[0], b: int):
    pass

The error reads that SyntaxError: non-default argument follows default argument.

# to show that this function is not trivial    
def fun(a:list=[0], b=len(a)):
    pass

Araises the error: NameError: name 'a' is not defined

The first example shows obviously that a is processed before b, that is the compiler should know a when it encounters b, but it seems that the compiler doesn't as shown in the second example.

When(or how) is a parameter defined in a function? Or how can I know what's going on under the hood? I mean the related part of the compiler code, may be implemented in context-free grammar.

Lerner Zhang
  • 6,184
  • 2
  • 49
  • 66
  • Please refer https://stackoverflow.com/questions/24719368/syntaxerror-non-default-argument-follows-default-argument – shyamzzp Sep 25 '20 at 13:40

4 Answers4

3

The parameter a is a local variable that doesn't actually get defined until the function is run; it's not available as a default argument value for b. Such a value needs to exist when the function is defined.

chepner
  • 497,756
  • 71
  • 530
  • 681
2

The first example shows obviously that a is processed before b

Not really, at least not in the full meaning of "processed".

The "compiler"/"pre-processor" (non of these terms really apply to Python, but let's let them) can easily check if you use = with an argument before another argument which does not have it by just building the AST tree, without "executing" the actual code.

So, fun(a=0, b) is wrong on the language syntax level (hence the SyntaxError). It is detected before the code is even executed, and its presence stops the parsing and the "compilation" of the code.

fun(a=0, b=a) is logically wrong. The syntax checking mechanism can't/won't detect it. It is only detected by the interpreter when it is trying to execute the code.

DeepSpace
  • 78,697
  • 11
  • 109
  • 154
2
def fun(a=0, b):

Here you have a default value for a, but none for b. That means you must provide a value for b when calling the function, but not for a. However, when you call it like so:

fun(42)

Which argument will receive the value? b, since a already has one?

That syntax just raises all sorts of questions, hence you must list all parameters with a default value last. That is the reason for that error.

def fun(a=0, b=a):

Here you're trying to assign the value of a variable a as the default value for b. That is fine in general:

bar = 'baz'

def fun(foo=bar): ...

The default value is evaluated once at function declaration time. The a in b=a does in no way refer to the a in a=0 from the same function declaration. It's looking for a variable a in scope, which it doesn't find.

deceze
  • 510,633
  • 85
  • 743
  • 889
  • Thanks for your answer. `It's looking for a variable a in scope, which it doesn't find.` but why? – Lerner Zhang Sep 25 '20 at 14:04
  • In the first part of your answer about `def fun(a=0, b)` you do explain why we cannot do like that but that is not my question. I know we cannot write that way. – Lerner Zhang Sep 25 '20 at 14:08
  • Perhaps this will help you: https://stackoverflow.com/a/1133013/476 – deceze Sep 25 '20 at 14:09
0

Arguments are processed in the order they appear, but if you are going to set a default parameter for any argument then they need to come at the end. Proper syntax would be def (b, a=0). In this case b is a required argument, and a is optional which defaults to 0 if nothing is passed.

whege
  • 1,391
  • 1
  • 5
  • 13