简体   繁体   English

导入带有类定义的python模块时发生意外行为

[英]Unexpected behavior while importing python Modules with Class Definitions

Consider the code in the file my_module.py: 考虑文件my_module.py中的代码:

class A(object):
  def __init__(self, x=er()):
    self.x = x

Now, when I import this module 现在,当我导入此模块时

import my_module

I get an error, 我收到一个错误

name 'er is not defined

While I understand that my_module does not have er defined, but I am never creating an instance of class A . 尽管我知道my_module尚未定义er ,但是我从未创建过class A的实例。 Therefore it is puzzling that python tries to execute the __init__ callback when simply importing the module. 因此,令人困惑的是,当简单地导入模块时,python尝试执行__init__回调。 Although, the __init__ call is not fully executed as explained by the example below: 但是, __init__调用并未完全执行,如以下示例所述:

class A(object):
  def __init__(self, x=5):
    self.x = x
    print ('I am here')

Now, when I import the module - nothing is printed and this is expected behavior. 现在,当我导入模块时-没有打印任何内容,这是预期的行为。

I am puzzled why is function er called in the first example when I donot instantiate an object of class A . 我不知道为什么在不实例化class A的对象时在第一个示例中调用函数er Any pointers to the documentation that explains this? 有任何指向说明此问题的文档的指针吗?

Because in Python, default argument values are evaluated at definition time . 因为在Python中,默认参数值是在定义时间评估的。 See, for example this question , or this notorious question . 参见,例如,这个问题这个臭名昭著的问题

This is documented here 在这里记录

The default values are evaluated at the point of function definition in the defining scope, so that 在定义范围内的函数定义点评估默认值,以便

 i = 5 def f(arg=i): print(arg) i = 6 

f() will print 5. f()将打印5。

Important warning : The default value is evaluated only once. 重要警告 :默认值仅计算一次。 This makes a difference when the default is a mutable object such as a list, dictionary, or instances of most classes. 当默认值是可变对象(例如列表,字典或大多数类的实例)时,这会有所不同。 For example, the following function accumulates the arguments passed to it on subsequent calls: 例如,以下函数累积在后续调用中传递给它的参数:

 def f(a, L=[]): L.append(a) return L print(f(1)) print(f(2)) print(f(3)) 

This will print 这将打印

 [1] [1, 2] [1, 2, 3] 

If you don't want the default to be shared between subsequent calls, you can write the function like this instead: 如果您不希望在后续调用之间共享默认值,则可以这样编写函数:

 def f(a, L=None): if L is None: L = [] L.append(a) return L 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM