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

    From Jach Feng@21:1/5 to All on Sat Aug 20 23:24:43 2022
    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?

    --Jach

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Mark Bourne@21:1/5 to Jach Feng on Sat Aug 27 12:42:13 2022
    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()

    --
    Mark.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Jach Feng@21:1/5 to All on Sat Aug 27 18:40:18 2022
    Mark Bourne 在 2022年8月27日 星期六晚上7:42:37 [UTC+8] 的信中寫道:
    import test
    test.x = 4
    test.foo()

    --
    Mark.
    Yes, you are right. But because of I am using "from test import *" which makes the name "test" disappear in the test2 scope, so this is not work.

    I solved this problem by moving "x" to a separate config.py file, import it in both test.py and test2.py, and access it using config.x

    --Jach

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Richard Damon@21:1/5 to Mark Bourne on Sun Aug 28 22:46:41 2022
    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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Jach Feng@21:1/5 to All on Sun Aug 28 20:51:43 2022
    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:-)

    --Jach

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Chris Angelico@21:1/5 to Jach Feng on Mon Aug 29 15:58:22 2022
    On Mon, 29 Aug 2022 at 15:54, Jach Feng <jfong@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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Jach Feng@21:1/5 to All on Mon Aug 29 01:00:10 2022
    Chris Angelico 在 2022年8月29日 星期一下午1:58:58 [UTC+8] 的信中寫道:
    On Mon, 29 Aug 2022 at 15:54, Jach Feng <jf...@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?

    --Jach

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Mark Bourne@21:1/5 to Jach Feng on Mon Aug 29 11:40:33 2022
    Jach Feng wrote:
    Chris Angelico 在 2022年8月29日 星期一下午1:58:58 [UTC+8] 的信中寫道:
    On Mon, 29 Aug 2022 at 15:54, Jach Feng <jf...@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.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Chris Angelico@21:1/5 to Jach Feng on Tue Aug 30 02:45:39 2022
    On Tue, 30 Aug 2022 at 02:38, Jach Feng <jfong@ms4.hinet.net> wrote:

    Chris Angelico 在 2022年8月29日 星期一下午1:58:58 [UTC+8] 的信中寫道:
    On Mon, 29 Aug 2022 at 15:54, Jach Feng <jf...@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?


    In order to do any sort of import, Python has to run the whole module.
    But after that, something gets set in your module so that you can get
    access to it.

    import x
    # is kinda like
    go_and_run("x")
    x = fetch_module("x")

    from x import y
    # is kinda like
    go_and_run("x")
    y = fetch_module("x").y

    Either way, the whole module gets run, but then there's an assignment
    into your module that depends on what you're importing.

    ChrisA

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Peter J. Holzer@21:1/5 to Mark Bourne on Mon Aug 29 20:45:12 2022
    On 2022-08-29 11:40:33 +0100, Mark Bourne wrote:
    Jach Feng wrote:
    Chris Angelico 在 2022年8月29日 星期一下午1:58:58 [UTC+8] 的信中寫道:
    On Mon, 29 Aug 2022 at 15:54, Jach Feng <jf...@ms4.hinet.net> wrote:
    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. :)

    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

    I think this should be rephrased. "`x.y` at the time the import is done" implies that at this time the name `x` does exist in the current
    namespace. Which then leads to the conclusion that this name must be
    hidden later. But I don't think this is the case.

    The module is imported but it isn't bound to any name in the current
    (global) namespace (obviously there must be some variable bound to it, but that's probably a local variable in the importer and it isn't called
    `x`). Then the object bound to the name `y` in the loaed module is bound
    to the name `y` in the current namespace.

    hp

    --
    _ | Peter J. Holzer | Story must make more sense than reality.
    |_|_) | |
    | | | hjp@hjp.at | -- Charles Stross, "Creative writing
    __/ | http://www.hjp.at/ | challenge!"

    -----BEGIN PGP SIGNATURE-----

    iQIzBAABCgAdFiEETtJbRjyPwVTYGJ5k8g5IURL+KF0FAmMNCTMACgkQ8g5IURL+ KF0SSxAAkE6BxGlLUS50WKLH0UyyJO42UGsmmY4RJaHIUB/adekUbTBr1nIgXDQr w+EkL85+zxzeabWtz972eobM+AgmRYjZU0eIw1tJzNJQMJa0IqaRox/mlDD69Ib2 3CY4sNibsYPKO8+3fwQ+pVw8qAZV2WM/Eq1HP64C5Z3I8J1v+g2Srap3hyapwTdv Sg9zH9oVDC38XKR271Gshdm2WD0QLuPz9FWQ7ELBKgD4LMP6ANp2KHyIytN5qX2q 24MEoxttQ75bfVQdiGymk0L3XELXPRwnXXPbajBDoWiYvMD2iitaiuvZEjVpQMjs EkiJfW6hzMSayqoa7n402CyijVEUZyPulmfcoWEgDz7r/qr6wSEhjy1na+anjBIE wgUVFAuMHqo7D3CLTkNYcKH8gtK5vd4nbS8eeEIbWw7laixXikcW4mZgYOOVU8iM ktUlAHgVy3YWOo9/YvSIBpLMf1aA6GeYEgdO1KM9C5AGYwiftYIc/9xNRmNDlJmL +Ewq2dGvdkgmI7louZuu8aRGPi2A1T/1LcsG/3kcjRuO0eiH9TcfdPul2ObHJrhV PZwCrvzemyDGEIL6cScS4pqjjYzdJLwearoKssUKBbLs/Fyy7mvDFV98dAoiTPgg Px7+BORdrSqb5c6yw0j1gn6U5IOkOX7J0UYblBv
  • From Jach Feng@21:1/5 to All on Mon Aug 29 18:02:53 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...@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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dn@21:1/5 to Peter J. Holzer on Tue Aug 30 16:05:43 2022
    On 30/08/2022 06.45, Peter J. Holzer wrote:

    The module is imported but it isn't bound to any name in the current
    (global) namespace (obviously there must be some variable bound to it, but that's probably a local variable in the importer and it isn't called
    `x`). Then the object bound to the name `y` in the loaed module is bound
    to the name `y` in the current namespace.


    Correct!

    Build module.py as:
    ***
    CONSTANT = 1

    def func():
    pass
    ***

    then in the terminal:
    ***
    Python 3.9.13 (main, May 18 2022, 00:00:00)
    [GCC 11.3.1 20220421 (Red Hat 11.3.1-2)] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    from module import func as f
    locals()
    {'__name__': '__main__', '__doc__': None, '__package__': None,
    '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__':
    None, '__annotations__': {}, '__builtins__': <module 'builtins'
    (built-in)>, 'f': <function func at 0x7f6faa8269d0>}
    f
    <function func at 0x7f6faa8269d0>
    f.CONSTANT
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    AttributeError: 'function' object has no attribute 'CONSTANT'
    module.CONSTANT
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    NameError: name 'module' is not defined

    # no mention of module and no access to CONSTANT

    import module as m
    locals()
    {'__name__': '__main__', '__doc__': None, '__package__': None,
    '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__':
    None, '__annotations__': {}, '__builtins__': <module 'builtins'
    (built-in)>, 'f': <function func at 0x7f6faa8269d0>, 'm': <module
    'module' from '/home/dn/Projects/ListQuestions/module.py'>}
    m
    <module 'module' from '/home/dn/Projects/ListQuestions/module.py'>
    m.func
    <function func at 0x7f6faa8269d0>
    m.CONSTANT
    1
    module
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    NameError: name 'module' is not defined

    # name module is bound as m, and not available as module

    import module
    locals()
    {'__name__': '__main__', '__doc__': None, '__package__': None,
    '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__':
    None, '__annotations__': {}, '__builtins__': <module 'builtins'
    (built-in)>, 'f': <function func at 0x7f6faa8269d0>, 'm': <module
    'module' from '/home/dn/Projects/ListQuestions/module.py'>, 'module':
    <module 'module' from '/home/dn/Projects/ListQuestions/module.py'>}
    module.func
    <function func at 0x7f6faa8269d0>
    module.CONSTANT
    1
    module
    <module 'module' from '/home/dn/Projects/ListQuestions/module.py'>

    # now it is available
    # also notice how the function (func) now has three
    'names'/access-methods but all lead to the same location
    ***

    --
    Regards,
    =dn

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Stefan Ram@21:1/5 to PythonList@DancesWithMice.info on Tue Aug 30 05:08:51 2022
    dn <PythonList@DancesWithMice.info> writes:
    Build module.py as:
    ***
    CONSTANT = 1

    def func():
    pass
    ***

    then in the terminal:
    ***
    Python 3.9.13 (main, May 18 2022, 00:00:00)
    [GCC 11.3.1 20220421 (Red Hat 11.3.1-2)] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    from module import func as f

    In CPython one then can also:

    print( f.__globals__[ "CONSTANT" ])
    import sys
    module = sys.modules[ f.__globals__[ "__name__" ]]
    print( module.CONSTANT )
    CONSTANT = module.CONSTANT
    print( CONSTANT )

    .

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Schachner, Joseph (US)@21:1/5 to All on Tue Aug 30 17:26:24 2022
    VGhlIHdheSB3ZSBkbyB0aGlzLCBpcyBpbiBtYWluLnB5LCBjYWxsIGEgImdsb2JhbGl6ZXIiIGZ1 bmN0aW9uIGluIGVhY2ggb3RoZXIgZmlsZToNCg0KICAgICMgY2FsbCBnbG9iYWxpemVycyB0byBn ZXQgc2hvcnRjdXRzIGFzIGdsb2JhbCB2YXJpYWJsZXMNCiAgICBmdW5jcy5nbG9iYWxpemVyKGlu dGVyZmFjZSwgdmFyaWFibGVfZGljdCkNCiAgICB1dGlsLmdsb2JhbGl6ZXIoaW50ZXJmYWNlLCB2 YXJpYWJsZV9kaWN0KQ0KICAgIHNkLmdsb2JhbGl6ZXIoaW50ZXJmYWNlLCB2YXJpYWJsZV9kaWN0 KQ0KICAgIHRlc3RzLmdsb2JhbGl6ZXIoaW50ZXJmYWNlLCB2YXJpYWJsZV9kaWN0KQ0KICAgIHV0 Lmdsb2JhbGl6ZXIoaW50ZXJmYWNlLCB2YXJpYWJsZV9kaWN0KQ0KDQpPYnZpb3VzbHksIHlvdSBt YXkgbm90IG5lZWQgYSBzaGFyZWQgaW50ZXJmYWNlIGluIHdoaWNoIGNhc2UgeW91IGNhbiBqdXN0 IHBhc3MgdGhlIHZhcmlhYmxlIGRpY3Rpb25hcnkuDQoNCkluIGVhY2ggZmlsZSwgeW91IGhhdmUg YSBmdW5jdGlvbjoNCmRlZiBnbG9iYWxpemVyKGludGVyZmFjZSwgdmFyaWFibGVzX2RpY3QpOg0K ICAgICMgY3JlYXRlIGdsb2JhbCB2YXJpYWJsZXMgZm9yIHRoaXMgLnB5IGZpbGUgZm9yIHNoYXJl ZCBpbnRlcmZhY2UgYW5kIHRoZSB2YXJpYWJsZXMNCiAgICAuLi4uDQoNClRoaXMgd29ya3Mgd2Vs bCwgbWFraW5nIHN1cmUgc2VwYXJhdGUgcHl0aG9uIGZpbGVzIHNoYXJlZCBleGFjdGx5IHRoZSBz YW1lIHRoaW5ncyB3ZSB3YW50IHRvIGJlIGdsb2JhbC4NCg0KLS0tLSBKb3NlcGggUy4NCg0KVGVs ZWR5bmUgQ29uZmlkZW50aWFsOyBDb21tZXJjaWFsbHkgU2Vuc2l0aXZlIEJ1c2luZXNzIERhdGEN Cg0KLS0tLS1PcmlnaW5hbCBNZXNzYWdlLS0tLS0NCkZyb206IFN0ZWZhbiBSYW0gPHJhbUB6ZWRh dC5mdS1iZXJsaW4uZGU+IA0KU2VudDogVHVlc2RheSwgQXVndXN0IDMwLCAyMDIyIDE6MDkgQU0N ClRvOiBweXRob24tbGlzdEBweXRob24ub3JnDQpTdWJqZWN0OiBSZTogSG93IHRvIG1ha2UgYSB2 YXJpYWJsZSdzIGxhdGUgYmluZGluZyBjcm9zc2VzIHRoZSBtb2R1bGUgYm91bmRhcnk/DQoNCmRu IDxQeXRob25MaXN0QERhbmNlc1dpdGhNaWNlLmluZm8+IHdyaXRlczoNCj5CdWlsZCBtb2R1bGUu cHkgYXM6DQo+KioqDQo+Q09OU1RBTlQgPSAxDQoNCj5kZWYgZnVuYygpOg0KPiAgICBwYXNzDQo+ KioqDQoNCj50aGVuIGluIHRoZSB0ZXJtaW5hbDoNCj4qKioNCj5QeXRob24gMy45LjEzIChtYWlu LCBNYXkgMTggMjAyMiwgMDA6MDA6MDApIFtHQ0MgMTEuMy4xIDIwMjIwNDIxIChSZWQgDQo+SGF0 IDExLjMuMS0yKV0gb24gbGludXggVHlwZSAiaGVscCIsICJjb3B5cmlnaHQiLCAiY3JlZGl0cyIg b3IgDQo+ImxpY2Vuc2UiIGZvciBtb3JlIGluZm9ybWF0aW9uLg0KPj4+PiBmcm9tIG1vZHVsZSBp bXBvcnQgZnVuYyBhcyBmDQoNCiAgSW4gQ1B5dGhvbiBvbmUgdGhlbiBjYW4gYWxzbzoNCg0KcHJp bnQoIGYuX19nbG9iYWxzX19bICJDT05TVEFOVCIgXSkNCmltcG9ydCBzeXMNCm1vZHVsZSA9IHN5 cy5tb2R1bGVzWyBmLl9fZ2xvYmFsc19fWyAiX19uYW1lX18iIF1dIHByaW50KCBtb2R1bGUuQ09O U1RBTlQgKSBDT05TVEFOVCA9IG1vZHVsZS5DT05TVEFOVCBwcmludCggQ09OU1RBTlQgKQ0KDQog IC4NCg0KDQo=

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dn@21:1/5 to All on Wed Aug 31 09:52:03 2022
    On 31/08/2022 05.26, Schachner, Joseph (US) wrote:
    The way we do this, is in main.py, call a "globalizer" function in each other file:

    # call globalizers to get shortcuts as global variables
    funcs.globalizer(interface, variable_dict)
    util.globalizer(interface, variable_dict)
    sd.globalizer(interface, variable_dict)
    tests.globalizer(interface, variable_dict)
    ut.globalizer(interface, variable_dict)

    Obviously, you may not need a shared interface in which case you can just pass the variable dictionary.

    In each file, you have a function:
    def globalizer(interface, variables_dict):
    # create global variables for this .py file for shared interface and the variables
    ....

    This works well, making sure separate python files shared exactly the same things we want to be global.

    ---- Joseph S.

    Teledyne Confidential; Commercially Sensitive Business Data

    -----Original Message-----
    From: Stefan Ram <ram@zedat.fu-berlin.de>
    Sent: Tuesday, August 30, 2022 1:09 AM
    To: python-list@python.org
    Subject: Re: How to make a variable's late binding crosses the module boundary?

    dn <PythonList@DancesWithMice.info> writes:
    Build module.py as:
    ***
    CONSTANT = 1

    def func():
    pass
    ***

    then in the terminal:
    ***
    Python 3.9.13 (main, May 18 2022, 00:00:00) [GCC 11.3.1 20220421 (Red
    Hat 11.3.1-2)] on linux Type "help", "copyright", "credits" or
    "license" for more information.
    from module import func as f

    In CPython one then can also:

    print( f.__globals__[ "CONSTANT" ])
    import sys
    module = sys.modules[ f.__globals__[ "__name__" ]] print( module.CONSTANT ) CONSTANT = module.CONSTANT print( CONSTANT )


    The conversation seems to be wandering some way from the OP. Whereas
    both of these answers are clever (and I assume work), the question
    becomes: why would you want to do this? (especially as it looks ugly and 'smells' a bit convoluted). An example use-case from your experience?


    Delving into the list-archive, to get back to the OP: the first message
    in the thread quotes another message that's (apparently) not present.

    However, in there somewhere is:

    from test import *

    So, the elephant-in-the-room has always been a very stinky 'code-smell'
    - which pretty much every text or web-tutorial will say is a bad idea.

    Why is a bad idea?
    Why is it there then?
    When to use it?
    [Socratic questioning]

    Same question, but the other way around: why has Python been equipped
    with modules, classes, functions, etc? To quote The Zen of Python:
    "Namespaces are one honking great idea -- let's do more of those!".
    Programming paradigms and architectural principles all contain reference
    and recommendation to independent code-units, coupling and cohesion,
    boundary crossing and interfaces (etc). Python doesn't enact a formal
    interface construct (thank you great, high, Python, gods!), but that
    doesn't remove the issues behind them (as the OP-code demonstrates).
    Instead it requires a Python-idiomatic approach.

    Should the question be: "how to I smash two namespaces into one and have
    it work 'my way'?", or should the question become "how does Python
    enable passing/retention of values between namespaces?".

    NB The OP likely reduced the 'problem' to 'minimum-code' for the benefit
    of the list, but what is the motivation behind it? Why would one want to
    be able to do this? Rationale? Use-case?

    Enquiring minds and all that...
    --
    Regards,
    =dn

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Stefan Ram@21:1/5 to PythonList@DancesWithMice.info on Tue Aug 30 23:08:11 2022
    dn <PythonList@DancesWithMice.info> writes:
    On 31/08/2022 05.26, Schachner, Joseph (US) wrote:
    From: Stefan Ram <ram@zedat.fu-berlin.de>
    ...
    In CPython one then can also:
    print( f.__globals__[ "CONSTANT" ])
    import sys
    module = sys.modules[ f.__globals__[ "__name__" ]]
    print( module.CONSTANT )
    CONSTANT = module.CONSTANT print( CONSTANT )
    The conversation seems to be wandering some way from the OP. Whereas
    both of these answers are clever (and I assume work), the question
    becomes: why would you want to do this? (especially as it looks ugly and >'smells' a bit convoluted). An example use-case from your experience?

    The OP asked whether the module was loaded, and my code
    showed that after "only f was imported", one can indeed
    access the whole module, which make it plausible that
    the whole module was loaded indeed.

    NB The OP likely reduced the 'problem' to 'minimum-code' for the benefit
    of the list, but what is the motivation behind it? Why would one want to
    be able to do this? Rationale? Use-case?

    For code that does not have to be production grade, but is
    just written ad hoc, "from X import *" can be convenient.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Antoon Pardon@21:1/5 to All on Wed Aug 31 09:38:19 2022
    Op 30/08/2022 om 23:52 schreef dn:
    The conversation seems to be wandering some way from the OP. Whereas
    both of these answers are clever (and I assume work), the question
    becomes: why would you want to do this? (especially as it looks ugly and 'smells' a bit convoluted). An example use-case from your experience?


    Delving into the list-archive, to get back to the OP: the first message
    in the thread quotes another message that's (apparently) not present.

    However, in there somewhere is:

    from test import *
    So, the elephant-in-the-room has always been a very stinky 'code-smell'
    - which pretty much every text or web-tutorial will say is a bad idea.

    No that is a red herring. If for some reason a variable in a module has
    to be (re)set after import time, it doesn't matter whether someone uses

    from module import *

    or

    from module import resetable_variable

    in both cases the module that did the import will not notice the change
    in the original module.

    focussing on the code smell, is leading the attention away from the problem.

    --
    Antoon Pardon

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dn@21:1/5 to Antoon Pardon on Wed Aug 31 19:53:49 2022
    On 31/08/2022 19.38, Antoon Pardon wrote:


    Op 30/08/2022 om 23:52 schreef dn:
    The conversation seems to be wandering some way from the OP. Whereas
    both of these answers are clever (and I assume work), the question
    becomes: why would you want to do this? (especially as it looks ugly and
    'smells' a bit convoluted). An example use-case from your experience?


    Delving into the list-archive, to get back to the OP: the first message
    in the thread quotes another message that's (apparently) not present.

    However, in there somewhere is:

    from test import *
    So, the elephant-in-the-room has always been a very stinky 'code-smell'
    - which pretty much every text or web-tutorial will say is a bad idea.

    No that is a red herring. If for some reason a variable in a module has
    to be (re)set after import time, it doesn't matter whether someone uses

        from module import *

    or

        from module import resetable_variable

    in both cases the module that did the import will not notice the change
    in the original module.

    focussing on the code smell, is leading the attention away from the
    problem.


    Are you the OP?

    The behavior has been shown to be exactly that which is (should be)
    expected.

    --
    Regards,
    =dn

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Antoon Pardon@21:1/5 to All on Wed Aug 31 10:06:56 2022
    Op 31/08/2022 om 09:53 schreef dn:
    On 31/08/2022 19.38, Antoon Pardon wrote:

    Op 30/08/2022 om 23:52 schreef dn:
    The conversation seems to be wandering some way from the OP. Whereas
    both of these answers are clever (and I assume work), the question
    becomes: why would you want to do this? (especially as it looks ugly and >>> 'smells' a bit convoluted). An example use-case from your experience?


    Delving into the list-archive, to get back to the OP: the first message
    in the thread quotes another message that's (apparently) not present.

    However, in there somewhere is:

    from test import *
    So, the elephant-in-the-room has always been a very stinky 'code-smell'
    - which pretty much every text or web-tutorial will say is a bad idea.
    No that is a red herring. If for some reason a variable in a module has
    to be (re)set after import time, it doesn't matter whether someone uses

        from module import *

    or

        from module import resetable_variable

    in both cases the module that did the import will not notice the change
    in the original module.

    focussing on the code smell, is leading the attention away from the
    problem.
    Are you the OP?

    The behavior has been shown to be exactly that which is (should be)
    expected.

    That doesn't contradict that the behaviour is a problem. What is expected (viewed as a language specification) and what is desired (viewed from what would solve the problem easily) can be at odds.

    --
    Antoon Pardon.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Mark Bourne@21:1/5 to Jach Feng on Wed Aug 31 19:43:09 2022
    Jach Feng wrote:
    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...@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

    Yes, sorry, I'd used `x.y` as a way of referring to the variable `y` in
    module `x` as opposed to `y` in the current module. It doesn't help
    that I added the second paragraph and didn't notice that the third was
    then out of context.

    If you use `import x` and assign to `x.y`, that will as you say be seen
    in both modules. On the other hand, if you use `from x import y`, then
    (as has been discussed) assigning to `y` in the module which has the
    import won't affect the value seen in module `x`. However, if `y` is
    mutable (e.g. a list), and no new object is assigned to it, then `y`
    still points to the same object in both modules, so mutating that
    existing object (e.g. `y.append(123)`) *will* affect what's seen in both modules - they're both referencing the same object, and you've modified
    that object, as opposed to assigning a new object to `y` in one of the
    modules.

    --
    Mark.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Jach Feng@21:1/5 to All on Wed Aug 31 18:53:55 2022
    Mark Bourne 在 2022年9月1日 星期四凌晨2:43:40 [UTC+8] 的信中寫道:
    Jach Feng wrote:
    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...@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
    Yes, sorry, I'd used `x.y` as a way of referring to the variable `y` in module `x` as opposed to `y` in the current module. It doesn't help
    that I added the second paragraph and didn't notice that the third was
    then out of context.

    If you use `import x` and assign to `x.y`, that will as you say be seen
    in both modules. On the other hand, if you use `from x import y`, then
    (as has been discussed) assigning to `y` in the module which has the
    import won't affect the value seen in module `x`. However, if `y` is
    mutable (e.g. a list), and no new object is assigned to it, then `y`
    still points to the same object in both modules, so mutating that
    existing object (e.g. `y.append(123)`) *will* affect what's seen in both modules - they're both referencing the same object, and you've modified
    that object, as opposed to assigning a new object to `y` in one of the modules.

    --
    Mark.
    Good Point! I learn from it:-)

    I found that using "from test import *" in test2.py makes test2's relation to "test" almost like the function's relation to the module where it is defined. You can refer to all the variables of the module, even modify the mutable objects, but just can't
    change them. The only way to change it is to declare it a "global." The same situation is in Test 2, but unfortunately there is no "super-global" to declare. The only way to make changes is to "import test" (again? it looks like a redundant statement to
    me:-) and use dot notation to do it.

    --Jach

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Eryk Sun@21:1/5 to Jach Feng on Thu Sep 1 11:41:21 2022
    On 8/31/22, Jach Feng <jfong@ms4.hinet.net> wrote:

    I found that using "from test import *" in test2.py makes test2's relation
    to "test" almost like the function's relation to the module where it is defined. You can refer to all the variables of the module

    Note that in general, if __all__ doesn't exist to explicitly define
    the contents of a star import, then it imports everything except names
    that begin with an underscore.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Jach Feng@21:1/5 to All on Thu Sep 1 17:44:46 2022
    ery...@gmail.com 在 2022年9月2日 星期五凌晨12:41:46 [UTC+8] 的信中寫道:
    On 8/31/22, Jach Feng <jf...@ms4.hinet.net> wrote:

    I found that using "from test import *" in test2.py makes test2's relation to "test" almost like the function's relation to the module where it is defined. You can refer to all the variables of the module
    Note that in general, if __all__ doesn't exist to explicitly define
    the contents of a star import, then it imports everything except names
    that begin with an underscore.
    Thank you for pointing out these important difference:-)

    --Jach

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)