4

I'm a programmer coming from Python background which typically uses lexical scoping and I want to understand dynamic scope. I've researched it on-line, still unclear to me. For example, I've read this page which made things a lot easier to me, especially the code snippets:

#In Dynamic scoping:         
    const int b = 5;        
    int foo()               
    {                       
       int a = b + 5;
       return a;
    }

    int bar()
    {
       int b = 2;
       return foo();
    }

    int main()
    {
       foo(); // returns 10
       bar(); // returns 7
       return 0;
    }


#In lexical scoping:         
    const int b = 5;        
    int foo()               
    {                       
       int a = b + 5;
       return a;
    }

    int bar()
    {
       int b = 2;
       return foo();
    }

    int main()
    {
       foo(); // returns 10
       bar(); // returns 10
       return 0;
    }

As I understand and as you can see, in the dynamic scoping, bar function returns 7 not 10, which means foo called the b variable which is defined within bar, in other words, foo did not looked for the b variable that's defined in top of the code (the first b variable) but rather it used the b variables that's defined in bar.

Q1: Hence, In dynamic scoping, the function that's being called within another function in this case foo called in bar first looks for variables in the caller function in this case bar and then it looks for top level variables ?

Q2: Could you explain dynamic scoping in Python code ?

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
GIZ
  • 4,409
  • 1
  • 24
  • 43

1 Answers1

10

There is no dynamic scoping in Python, unless you implement your own stack-based 'namespace'.

And yes, dynamic scoping is that simple; the value of a variable is determined by the closest calling namespace where a value was set. View the calls as a stack, and a value is looked up by searching the current call stack from top to bottom.

So for your dynamic example, the stack is first:

foo
main 
globals -> b = 5

finding b = 5 when searching through the stack, and then the stack changes to

foo
bar -> b = 2
main
globals -> b = 5

so b = 2 is found.

Community
  • 1
  • 1
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • So it's possible to find variables even in `main` function if for example `b` variable was assigned in `main` instead of `bar` ? – GIZ Sep 21 '15 at 17:24
  • Yes, all scopes on the call stack are included in the search. – Martijn Pieters Sep 21 '15 at 17:30
  • And if I called `main` or any other function outside functions, it'll only look for globals only, correct me if I'm wrong. – GIZ Sep 21 '15 at 17:31
  • If there are no other call frames in between then only the globally remain. – Martijn Pieters Sep 21 '15 at 17:32
  • 1
    I see the point now why very limited people still relying on dynamic scoping as it's very complicated to comprehend, guess if you have about 100 functions in your program, it's really, really difficult to trace every single var, that being said, you need to build a tree of variable chain to understand where the problem is coming from in case of a bug – GIZ Sep 21 '15 at 17:39
  • @direprobs: yes, dynamic scoping is generally seen as a Bad Idea, and few languages make it the default model, if they offer it at all. – Martijn Pieters Sep 21 '15 at 18:08
  • @MartijnPieters There is one context in Python where something similar to dynamic scoping applies, and that is with class inheritance. It's not dynamic scoping, but has similarities. If you have a base class that defines class attribute `a`, and a derived class that also defines class attribute `a`, then instances of the derived class will reference `a` from the derived class. But if you then delete `a` from the derived class, those same instances will now reference `a` from the base class. And of course you can reverse this by again defining `a` in the derived class. – Tom Karzes Jul 15 '21 at 02:32
  • @MartijnPieters Of course, this only applies to reading `a`, not writing it. – Tom Karzes Jul 15 '21 at 02:42
  • @TomKarzes: that's not dynamic scoping though; the namespaces are just layered, defined by the class MRO. – Martijn Pieters Jul 16 '21 at 20:17
  • @MartijnPieters Right, which is why I said it wasn't dynamic scoping. I just said it had some similarities, in that the check to determine which instance to use is made dynamically.. – Tom Karzes Jul 16 '21 at 20:19
  • 1
    Aren't Python's [context variables](https://docs.python.org/3/library/contextvars.html) (3.7) just dynamically scoped variables? – Alexey Aug 08 '21 at 17:59