如何不使用exec()重写Python日期按钮的创建与删除代码?
不用
exec()重写你的日期按钮代码 当然可以完全抛弃exec()来实现这两个功能,而且这样做会让代码更安全、易读,也更符合Python的最佳实践——exec()这类动态执行字符串代码的方式不仅调试麻烦,还存在安全风险(比如如果传入的date是恶意构造的字符串,可能会执行意料之外的代码)。
重写make_button函数
原来的代码用exec()动态创建按钮属性并设置布局,我们可以用Python内置的setattr()函数来动态给实例设置属性,再通过临时变量简化重复代码:
def make_button(self, date, row, column): """ 描述:创建日期按钮。 :param date: 日期。 :type date: str :param row: 行号。 :type row: int # 注意:grid的row/column参数需要整数,建议把参数类型改成int :param column: 列号。 :type column: int """ # 先创建按钮实例 btn = ttk.Button(self.frame_days, text=date, width=5) # 动态把按钮绑定为self的属性,属性名是btn_xxx(xxx为传入的date) setattr(self, f"btn_{date}", btn) # 设置按钮布局,若row/column是字符串类型,记得转成int btn.grid(row=int(row), column=int(column)) # 绑定点击事件 btn.bind("<Button-1>", self.get_date)
小提示:
如果你的row和column参数本来就是整数(大概率应该是),可以直接去掉int()转换,同时把参数类型注释改成int,这样代码更严谨。
重写delete_buttons函数
删除按钮时,我们用getattr()来动态获取对应的按钮属性,然后调用destroy()方法即可:
def delete_buttons(self, date): """ 描述:删除日期按钮。 :param date: 日期。 :type date: str """ # 获取按钮实例,第二个参数是默认值:如果找不到对应属性就返回None btn = getattr(self, f"btn_{date}", None) # 确保按钮存在再销毁,避免触发AttributeError if btn: btn.destroy() # 可选:销毁后删除实例属性,清理内存 delattr(self, f"btn_{date}")
为什么这样更好?
- 安全:不会执行任意字符串代码,避免注入风险
- 易读:逻辑清晰,其他开发者(包括未来的你)一眼就能看懂代码在做什么
- 易调试:如果出问题,能直接定位到具体代码行,而不是
exec()里的字符串
内容的提问来源于stack exchange,提问作者protej
相关产品推荐
相关产品推荐

