Python中‘遮蔽外部作用域名称’是否为错误?代码故障求助
解决Firebase实时数据库监听变量时的阴影警告与通知不触发问题
先回答你的第一个问题:绿色下划线提示是不是错误?
那个绿色下划线不是语法错误,是IDE(比如PyCharm)给出的代码质量警告。提示内容"Shadows name 'value' from outer scope"的意思是:你在函数stream_handler内部定义了和全局变量同名的局部变量value,这会把外部的全局变量“遮蔽”——也就是说,你在函数里给value赋值时,修改的是局部变量,而不是你一开始在全局定义的那个value。这正是你现在收不到通知的核心原因之一!
如何解决变量阴影问题?
要在函数内部修改全局变量,你需要用global关键字声明这个变量是全局的。比如在每个stream处理函数的开头,加上对应的全局变量声明,让函数知道你要操作的是外部的全局变量,而不是创建新的局部变量。
你的代码还存在哪些逻辑错误?
- 判断语句执行时机错误:你原来的
if value is 1 & value1 is 1:写在全局作用域里,程序启动时只会执行一次(此时value和value1都是0),之后就算数据库更新了变量,这段代码也不会再执行。你需要把判断逻辑封装成函数,每次变量更新后主动调用它。 - 错误的运算符使用:
- 用
is判断数值相等不合适,is是判断两个对象是否为同一身份,判断值相等应该用==; &是位运算符号,逻辑与应该用and。
- 用
- 缺少变量重置逻辑:如果数据库里的变量从1变回0,你的全局变量不会跟着重置,会一直保持1,导致后续可能误发通知。
修改后的完整代码示例
value = 0 value1 = 0 def check_and_send_notification(): global value, value1 if value == 1 and value1 == 1: response = pn_client.publish( interests=['hello'], publish_body={ 'apns': { 'aps': { 'alert': 'Hello!', }, }, 'fcm': { 'notification': { 'title': 'Notification', 'body': 'Fall Detected !!', }, }, }, ) print(response['publishId']) def stream_handler(message): global value print(message) # 更新全局变量的值,同时处理非1的情况 value = 1 if message['data'] == 1 else 0 check_and_send_notification() def stream_handler1(message1): global value1 print(message1) # 更新全局变量的值,同时处理非1的情况 value1 = 1 if message1['data'] == 1 else 0 check_and_send_notification() # 启动数据库监听 my_stream = db.child("Fall_Detection_Status").stream(stream_handler) my_stream1 = db.child("Fall_Detection_Status1").stream(stream_handler1)
额外提示
如果你觉得全局变量的使用不够优雅,也可以考虑用一个类来封装状态,这样更符合面向对象的编程习惯;另外记得测试数据库中两个变量分别为1、0的各种组合,确保通知只会在两者都为1时触发。
内容的提问来源于stack exchange,提问作者Moustapha Sabbagh




