How to make a variable's late binding crosses the module boundary?

Jach Feng jfong at ms4.hinet.net
Mon Aug 29 21:02:53 EDT 2022


Mark Bourne 在 2022年8月29日 星期一下午6:40:59 [UTC+8] 的信中寫道:
> Jach Feng wrote: 
> > Chris Angelico 在 2022年8月29日 星期一下午1:58:58 [UTC+8] 的信中寫道: 
> >> On Mon, 29 Aug 2022 at 15:54, Jach Feng <jf... at ms4.hinet.net> wrote: 
> >>> 
> >>> Richard Damon 在 2022年8月29日 星期一上午10:47:08 [UTC+8] 的信中寫道: 
> >>>> On 8/27/22 7:42 AM, Mark Bourne wrote: 
> >>>>> Jach Feng wrote: 
> >>>>>> I have two files: test.py and test2.py 
> >>>>>> --test.py-- 
> >>>>>> x = 2 
> >>>>>> def foo(): 
> >>>>>> print(x) 
> >>>>>> foo() 
> >>>>>> 
> >>>>>> x = 3 
> >>>>>> foo() 
> >>>>>> 
> >>>>>> --test2.py-- 
> >>>>>> from test import * 
> >>>>>> x = 4 
> >>>>>> foo() 
> >>>>>> 
> >>>>>> ----- 
> >>>>>> Run test.py under Winows8.1, I get the expected result: 
> >>>>>> e:\MyDocument>py test.py 
> >>>>>> 2 
> >>>>>> 3 
> >>>>>> 
> >>>>>> But when run test2.py, the result is not my expected 2,3,4:-( 
> >>>>>> e:\MyDocument>py test2.py 
> >>>>>> 2 
> >>>>>> 3 
> >>>>>> 3 
> >>>>>> 
> >>>>>> What to do? 
> >>>>> 
> >>>>> `from test import *` does not link the names in `test2` to those in 
> >>>>> `test`. It just binds objects bound to names in `test` to the same 
> >>>>> names in `test2`. A bit like doing: 
> >>>>> 
> >>>>> import test 
> >>>>> x = test.x 
> >>>>> foo = test.foo 
> >>>>> del test 
> >>>>> 
> >>>>> Subsequently assigning a different object to `x` in one module does 
> >>>>> not affect the object assigned to `x` in the other module. So `x = 4` 
> >>>>> in `test2.py` does not affect the object assigned to `x` in `test.py` 
> >>>>> - that's still `3`. If you want to do that, you need to import `test` 
> >>>>> and assign to `test.x`, for example: 
> >>>>> 
> >>>>> import test 
> >>>>> test.x = 4 
> >>>>> test.foo() 
> >>>>> 
> >>>> Yes, fundamental issue is that the statement 
> >>>> 
> >>>> from x import y 
> >>>> 
> >>>> makes a binding in this module to the object CURRECTLY bound to x.y to 
> >>>> the name y, but if x.y gets rebound, this module does not track the changes. 
> >>>> 
> >>>> You can mutate the object x.y and see the changes, but not rebind it. 
> >>>> 
> >>>> If you need to see rebindings, you can't use the "from x import y" form, 
> >>>> or at a minimum do it as: 
> >>>> 
> >>>> 
> >>>> import x 
> >>>> 
> >>>> from x import y 
> >>>> 
> >>>> then later to get rebindings to x.y do a 
> >>>> 
> >>>> y = x.y 
> >>>> 
> >>>> to rebind to the current x.y object. 
> >>>> 
> >>>> -- 
> >>>> Richard Damon 
> >>> Yes, an extra "import x" will solve my problem too! Sometimes I am wondering why "from x import y" hides x? hum...can't figure out the reason:-) 
> >>> 
> >> "from x import y" doesn't hide x - it just grabs y. Python does what 
> >> you tell it to. :) 
> >> 
> >> ChrisA 
> > But I had heard people say that "from x import y" did import the whole x module into memory, just as "import x" did, not "grabs y" only. Is this correct?
> `from x import y` does import the whole module x into memory, and adds 
> it to `sys.modules`. But it only binds the name `y` in the namespace of 
> module doing the import (and it binds it to the value of `x.y` at the 
> time the import is done - it doesn't magically keep them in sync if one 
> or the other is later reassigned). 
> 
> The point about the whole module being imported is that you don't save 
> any memory by using `from x import y` to avoid importing some very large 
> object `z` from `x`. Those other large objects might be needed by 
> functions which have been imported (e.g. your `foo` function still needs 
> `x` even if you haven't imported `x` - so it still needs to be loaded 
> into memory) or might be imported and used by other modules importing 
> `x`, so they still have to be loaded when any part of `x` is imported - 
> they just don't have to be bound to names in the importing module's 
> namespace. 
> 
> As Richard mentioned, if `x.y` is a mutable object (such as a list) you 
> can still mutate that object (e.g. add/remove items) and those changes 
> will be seen in both modules. That's because both are still bound to 
> the same object and you're mutating that existing object. If you assign 
> a new list to either, that won't be seen by the other. 
> 
> -- 
> Mark.
When using dot notation to change variable, no matter if 'x.y' is a mutable or immutable object, the change
will be seen in both modules except those early bindings.

--Jach


More information about the Python-list mailing list