Python 类中的外部词典阅读行为
我发现这种行为我无法理解。我声明这是对我遇到的问题的简化,因为我脚本中的字典有很多项Python 类中的外部词典阅读行为,python,python-3.7,Python,Python 3.7,我发现这种行为我无法理解。我声明这是对我遇到的问题的简化,因为我脚本中的字典有很多项 configuration = { "video": { "fullscreen": { "user": None, "default": False } } } class test(): fullscreen = configuration["video"]["fullscreen"]["user"]
configuration = {
"video": {
"fullscreen": {
"user": None,
"default": False
}
}
}
class test():
fullscreen = configuration["video"]["fullscreen"]["user"]
def __init__(self):
print(configuration)
print(configuration["video"]["fullscreen"]["user"])
print(self.fullscreen)
if __name__ == "__main__":
configuration["video"]["fullscreen"]["user"] = True
t = test()
结果是:
{'video': {'fullscreen': {'user': True, 'default': False}}}
True
None
为什么在第三次打印中结果为“无”?发生这种行为是因为
self。全屏
指的是在编辑之前定义的类属性,它是全局范围内的属性
一旦创建它,它就会进入类“\uuuuu dict\uuuuu
,因此更改外部作用域中的一个显然与存储在类中的on无关
我觉得如果你写了fullscreen=configuration
,你会得到不同的结果,因为它可能引用同一个dictionary对象。Ciao
事实上,到目前为止对你的问题所作的解释并没有真正向我完全澄清你的问题中的指令执行顺序。我想我完全理解你的意思,这也让我困惑
下面的示例将向您显示,在运行main()
中的configuration[“video”][“fullscreen”][“user”]=“John”
之前,会创建类属性user\u conf
[重命名以避免关注错误的点]。换句话说,在纯类属性级别,它的值是从配置
蓝图中设置的。只有在main
之后调用的类构造函数才能在以后更新该值
configuration = {
"video": {
"fullscreen": {
"user": None,
"default": False
}
}
}
# correcting global variable blueprint
# configuration["video"]["fullscreen"]["user"] = "John"
class test():
print(configuration["video"]["fullscreen"]["user"])
user_conf = configuration["video"]["fullscreen"]["user"]
print(user_conf)
def __init__(self):
# printing modified global variable, all right
print(configuration)
print(configuration["video"]["fullscreen"]["user"])
print(self.user_conf)
self.user_conf = "Jack"
print(self.user_conf)
def main():
# modifying global variable later
# at this point the class attribute user_conf has already been assigned with the old value
configuration["video"]["fullscreen"]["user"] = "John"
test()
if __name__ == '__main__':
main()
请注意,如果您在main中注释了value update并取消注释了我添加的这些行:
# correcting global variable blueprint
# configuration["video"]["fullscreen"]["user"] = "John"
在配置声明之后,您的输出将不包含您期望找到的任何None
,因为class属性将由“更正的”蓝图创建。在这种情况下,您将获得:
约翰约翰
{'video':{'fullscreen':{'user':'John','default': False}}}
约翰
约翰
杰克 另一种在第6点调整示例的方法: 这将使: 初始外部配置:{'video':{'fullscreen':{'user':无, 'default':False}
内部配置:{'video': {'fullscreen':{'user':'John','default':False}}}
已修改 外部配置:{'video':{'fullscreen':{'user':'John', “默认值”:False}
希望这能更好地解决你的疑问
在评论后编辑:正如我公开声明的那样,我花了一些时间才弄清楚到底发生了什么。让我们看看这个代码:
configuration = {
"video": {
"fullscreen": {
"user": None,
"default": False
}
}
}
print("step 1 -> " + str(configuration))
# correcting global variable blueprint
# configuration["video"]["fullscreen"]["user"] = "John"
class test():
print("step 2 -> " + str(configuration))
user_conf = configuration["video"]["fullscreen"]["user"]
def __init__(self):
# printing modified global variable, all right
print("step 5 -> constructor reads the updated value: " + str(configuration))
def main():
# modifying global variable later
# at this point the class attribute user_conf has already been assigned with the old value
print("step 3 -> " + str(configuration))
configuration["video"]["fullscreen"]["user"] = "John"
print("step 4 -> main just updated the global variable: " + str(configuration))
test()
if __name__ == '__main__':
main()
打印此文件将提供以下输出:
步骤1->{'video':{'fullscreen':{'user':无,默认值:False}
步骤2->{'video':{'fullscreen':{'user':无,'default': False}}}
步骤3->{'video':{'fullscreen':{'user':无, 'default':False}}
步骤4->main刚刚更新了全局 变量:{'video':{'fullscreen':{'user':'John','default': False}}
步骤5->构造函数读取更新的值: {'video':{'fullscreen':{'user':'John','default':False} 现在,如果您阅读,您将很容易理解Python是自上而下执行的,并且执行
def
块-在我们的例子中\uuuu init\uuuu(self)
-不会立即执行包含的代码。相反,它在当前作用域中创建一个具有给定名称的函数对象,该函数对象只有在从main()
调用test()
后才实际输入,也就是说,只有在您请求从test()
类实例化一个对象后,才会触发其构造函数
重要:在您的情况下,我意识到您正在调用类test()
,而test()
正是从main()
调用的。您的main实际上正在调用一个方法,test()
:因此,请在前面的代码中将class test()
替换为def test()
,您将得到一个不同的、更易于理解的执行流:
步骤1->{'video':{'fullscreen':{'user':无,默认值:False}
步骤3->{'video':{'fullscreen':{'user':无,'default': False}}
步骤4->main刚刚更新了全局变量: {'video':{'fullscreen':{'user':'John','default':False}}
步骤2->{'video':{'fullscreen':{'user':'John','default': 假}}} 在第一次
打印后
跳过所有def块,然后进入main()
。main()
更新全局变量,然后test()
函数将立即对更新的值起作用。当然,在这种情况下,构造函数不会被触发[这不再是一个类],这就解释了缺少步骤5的原因
->您确定以这种方式定义和使用类是一个很好的选择吗?[可能不是]->将
test()
声明为def
而不是声明为class
不是更好吗?[我真的这么认为]
祝您愉快您为一个类属性分配了一个对象,该属性恰好是dict中的一个值。然后,您在字典中更改了该引用。您再也不会接触该属性,因此它当然保持不变。简而言之,第三次打印将打印
None
,因为您将None
指定给正在打印的属性,并且此后从未更改过该属性,因此它当然仍然是None
。注意,它是一个类属性这一事实与此无关。如果您刚刚分配了一个变量,这将以sam的方式工作。谢谢您完整的回答。在现实中,我仍然是一个疑问。在我发布的示例中,更改发生在调用类之前。所以,一旦我用一个内部变量复制了字典中的值,为什么不复制值更改呢?我不知道我的解释是否正确。@BlackFenix06我修改了内容,请再试一次
configuration = {
"video": {
"fullscreen": {
"user": None,
"default": False
}
}
}
print("step 1 -> " + str(configuration))
# correcting global variable blueprint
# configuration["video"]["fullscreen"]["user"] = "John"
class test():
print("step 2 -> " + str(configuration))
user_conf = configuration["video"]["fullscreen"]["user"]
def __init__(self):
# printing modified global variable, all right
print("step 5 -> constructor reads the updated value: " + str(configuration))
def main():
# modifying global variable later
# at this point the class attribute user_conf has already been assigned with the old value
print("step 3 -> " + str(configuration))
configuration["video"]["fullscreen"]["user"] = "John"
print("step 4 -> main just updated the global variable: " + str(configuration))
test()
if __name__ == '__main__':
main()