【问题标题】:Calling variables from other files in Python在 Python 中从其他文件调用变量
【发布时间】:2012-02-12 21:31:53
【问题描述】:

我正在尝试导入文件,情况如下。

file1.py 包含:

from file2 import *
username = "steven"

action()

file2.py 包含:

def action():
    print username 

但我无法打印用户名,因为变量“用户名”是在 file1 中声明的,而不是在 file2 中声明的(因为函数使用该变量)

这不是实际代码,但我不能在 file2 的函数中使用 file1 的变量吗?

【问题讨论】:

    标签: python


    【解决方案1】:

    更好的方法是不依赖其他模块的全局变量,只需将名称传递给file2.action() 函数:

    file1.py

    ​​>
    import file2
    
    username = "steven"
    
    file2.action(username)
    

    file2.py

    ​​>
    def action(name):
        print name 
    

    【讨论】:

    • 太棒了,谢谢!所以我不必输入“import *”?我可以只导入文件吗?
    • 没错。如果您只是import file2,那么您需要使用file2.限定 file2 中的所有名称,例如file2.action 示例。但这是一件好事,因为您知道action 的去向。
    • 在这种情况下,任何来自file2.py 的函数使用来自file1.py 的变量都应该有一个参数来获取它?
    【解决方案2】:

    按照您想要的方式,您的意图将需要 file1 import file2 ,反之亦然 - 在纯代码中,这将导致循环导入,这显然不起作用。

    但除此之外,如果文件上的函数、类或方法需要了解导入它们的文件上下文中的数据,正确的做法是将这些数据作为函数参数传入。

    在你的情况下,你的“行动”功能应该是:

    def action(username):
        print username 
    

    在文件 1 上:

    from file2 import action
    username = "steven"
    
    action(username)
    

    (你也应该避免使用“import *”,因为它在阅读代码时隐藏了名称的来源,使其难以维护)

    当然,Python 是 Python,有一些变通方法可以完全按照您的意愿行事 - 您可以创建一个特殊的装饰器以在您导入的函数上使用,该装饰器将从另一个文件重新创建您的函数,将其指向来自当前模块 - 但这太傻了。

    “OOP”范式允许一种愚蠢的情况,它或多或少类似于您打算做的事情 - 方法使用类属性 - 如果该属性在子类中被覆盖,则该方法 - 甚至是原始的超类方法,将使用新的属性值 - 如:

    class A(object):
        username = ""
        def action(self):
             print self.__class__.username
    

    B 类可以在其他文件中定义,如您所愿:

    from file2 import A
    class B(A):
        username = "Mike"
    
    b = B()
    b.action()
    

    现在,只是为了给你一个完整的答案——这里有一些代码可以做你想做的事——但_不要这样做——修改 yoru 函数以取而代之。

    可以做的是有一个函数来读取它被调用的地方的全局变量。这不仅是“不是一个好的做法”——它只是错误的,除了一些非常有据可查的框架,其中“神奇的变量名”用于配置。即使我发现一个有这个坏习惯的框架,我也倾向于修补它的功能,以便我可以通过函数调用显式地传递配置。

    from inspect import currentframe
    
    def action():
        caller_frame = current_frame(1)
        caller_globals = caller_frame.f_globals
        print caller_globals["username"]
    

    【讨论】:

      【解决方案3】:

      但是file2.py 没有导入file1.py;它怎么知道username 甚至存在?


      顺便说一句,我尽量避免在我的代码中出现循环依赖(即模块 x 导入模块 y,模块 y 导入模块 x),所以简单地将 file1 导入 file2 可能不是最好的解决方案。

      【讨论】:

      • 循环依赖甚至在 Python 中都不起作用——模块主代码中的几个“if”在导入时就知道了。
      【解决方案4】:

      不,file2 无法访问 file1 中的全局变量,除非显式导入它们。这其实是件好事,否则,一个导入一堆模块的项目很容易意外覆盖彼此的数据。

      为什么不将用户名作为方法的参数?

      file1.py:

      from file2 import action
      username = "steven"
      action(username)
      

      file2.py:

      def action(username):
         print username
      

      【讨论】:

        【解决方案5】:

        最好使用类,因为它们很容易扩展:

        file1.py

        from file2 import ExtendedClass
        
        class MyClass(object, ExtendedClass):
          def __init__(self):
            Object.__init__(self)
            self.username = 'steven'
        

        file2.py

        class ExtendedClass:
          def action(self):
            print self.username
        

        尽管存在一些 hacky-method 并解决了您的问题,但一旦您使用它们,您就会喜欢它们。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-10-24
          • 2018-10-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-08-01
          • 1970-01-01
          • 2017-09-15
          相关资源
          最近更新 更多