【问题标题】:What is the effect of 'from x import variable' in python3python3中'from x import variable'的作用是什么
【发布时间】:2020-01-09 16:37:10
【问题描述】:

我今天感觉特别厚。考虑

mod1.py

count = 0

def foo ():
    global count
    count = count + 1

mod2.py

import mod1

from mod1 import foo, count

print("mod1.count = ", mod1.count)
print("count = ", count)

foo()

print("mod1.count = ", mod1.count)
print("count = ", count)

我假设将 count 导入 mod2 可以有效地将其全球化。

> python3 mod2.py
mod1.count =  0
count      =  0
mod1.count =  1
count      =  0

我显然有一些基本的误解。我假设导入本质上会生成 mod1.count 和 count 别名,但事实并非如此。我猜这与同时使用“import”和“from-import”有关。

【问题讨论】:

标签: python variables scope


【解决方案1】:

它们之间的区别可能是可用性。

import module

允许您使用. 运算符从模块访问方法。而

from module import something

允许您使用 something 而不使用 . 运算符引用模块。 您也可以说它允许您在全局范围内使用something

使用from 方法,您将全局导入something。这并不意味着来自modulesomething 消失了。它只是制作方法的新实例。 因此,当您同时导入modulesomething 的实例时,您可以通过任何一种方式直接访问something(使用或不使用. 运算符)。

【讨论】:

  • 但在他的示例中,他使用. 运算符获取模块中的变量,尽管他使用了from module import variable
【解决方案2】:

我认为您已经回答了自己的问题。它们不是别名,而是两个不同的对象,大概是因为它们存在于不同的命名空间中。您可以通过导入然后print(mod1.count is count) 来更简单地验证这一点。如果它们是别名,这将返回 True

【讨论】:

    【解决方案3】:

    这是由于 Python 处理变量名称的方式。为了有一些解释的基础,我用一个列表作为第二个导入变量扩展了你的示例:

    mod1.py

    count = 0
    lst = [1, 2, 3]
    
    def update_count():
        global count
        count = count + 1
    
    def update_lst():
        lst.append(4)
    

    test.py

    import mod1
    
    from mod1 import count, lst, update_count, update_lst
    
    print("mod1.count = ", mod1.count)
    print("count = ", count)
    print("mod1.lst = ", mod1.lst)
    print("lst = ", lst)
    
    update_count()
    update_lst()
    print('\nAfter updates: \n')
    
    print("mod1.count = ", mod1.count)
    print("count = ", count)
    print("mod1.lst = ", mod1.lst)
    print("lst = ", lst)    
    

    输出:

    mod1.count =  0
    count =  0
    mod1.lst =  [1, 2, 3]
    lst =  [1, 2, 3]
    
    After updates: 
    
    mod1.count =  1
    count =  0
    mod1.lst =  [1, 2, 3, 4]
    lst =  [1, 2, 3, 4]
    

    那么,发生了什么?

    当您导入 countlst 时,这些新名称会在脚本的命名空间中创建。名称countmod1.count 已引用的整数对象0 的另一个名称,名称lstmod1.lst 已引用的列表的另一个名称。

    当我们执行更新时,模块中的列表得到更新,但它仍然是同一个对象:mod1.lstlst 仍然引用同一个对象。

    mod1.count 的情况有所不同,因为我们让这个名称指向一个新对象,即count = count + 1 中的整数1。 现在,mod1.count 指的是整数对象1,而主脚本中的count 仍然指的是原始的0 对象。

    所以,这只是正常的 Python 名称行为。

    如果您还没有阅读,我推荐 Ned Batchelder 的经典著作 Facts and myths about Python names and values,它很好地解释了名称在 Python 中的工作原理。

    【讨论】:

      猜你喜欢
      • 2020-07-23
      • 2017-09-18
      • 1970-01-01
      • 2022-10-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-09
      相关资源
      最近更新 更多