Python类Getter与Setter装饰器应用及代码优化咨询
问题解答
1. 类变量与实例变量的使用优化
你的类变量和实例变量使用逻辑基本通顺,但存在几个可以优化的点:
类变量的问题与调整
auth_bearer和headers不应设为类变量:类变量在类定义阶段就会初始化,后续如果修改BotLine.secret_token,auth_bearer不会自动更新(因为它是一次性计算的)。而且所有实例共享同一个headers对象,若某个实例修改headers会影响所有实例,存在状态污染风险。- 优化方案:将
auth_bearer和headers改为动态计算的实例属性,用@property装饰器实现,确保每次获取时都是最新值:
class BotLine: secret_token = "secret_token_here" endpoint_url = "https://api.line.me/v2/bot/message/push" destination_id_test = "test_group_id" destination_id_real = "real_group_id" @property def auth_bearer(self): return f"Bearer {self.secret_token}" @property def headers(self): return {"Content-Type": "application/json", "Authorization": self.auth_bearer}
实例变量的精简
- 移除冗余的实例变量:
self.chat仅在__init__中设为None,后续未被使用;self.data每次调用set_chat_message都会重新生成,且send_to_chat直接用返回值,没必要存在实例中。优化后的__init__:
def __init__(self, test_mode="Y"): self._test_mode = test_mode # 存储测试模式,方便后续切换
2. 使用GETTER/SETTER装饰器改造方法
Python的@property装饰器可实现getter,配合@<属性名>.setter实现setter,以下是针对性改造:
改造set_destination_id
将test_mode设为可修改的属性,destination_id作为只读属性动态计算,替代原set_destination_id方法:
class BotLine: # ... 其他类变量 ... def __init__(self, test_mode="Y"): self._test_mode = test_mode # 下划线开头表示私有变量,约定外部直接修改 @property def test_mode(self): return self._test_mode @test_mode.setter def test_mode(self, value): # 增加参数验证,确保输入合法 if value not in ("Y", "N"): raise ValueError("test_mode必须为'Y'或'N'") self._test_mode = value @property def destination_id(self): return self.destination_id_real if self._test_mode == 'N' else self.destination_id_test
使用时,直接通过bot.destination_id获取目标ID,通过bot.test_mode = "N"切换环境,destination_id会自动更新。
改造set_chat_message
将消息内容设为可设置的属性,设置时自动生成消息结构,替代原set_chat_message方法:
class BotLine: # ... 其他代码 ... def __init__(self, test_mode="Y"): self._test_mode = test_mode self._chat_content = None @property def chat_content(self): return self._chat_content @chat_content.setter def chat_content(self, content): self._chat_content = content # 设置内容时自动生成消息数据 self._message_data = { "to": self.destination_id, "messages": [ { "type": "text", "text": f"$ {content} $", "emojis": [ {"index": 0, "productId": "5ac2213e040ab15980c9b447", "emojiId": "001"} ] }, {"type": "sticker", "packageId": "6136", "stickerId": "10551377"} ] } @property def message_data(self): if not self._chat_content: raise ValueError("请先设置chat_content") return self._message_data
修改send_to_chat方法适配新逻辑:
def send_to_chat(self, chat=None): if chat: self.chat_content = chat response = requests.post( self.endpoint_url, data=json.dumps(self.message_data), headers=self.headers, verify=False ) return json.loads(response.text)
完整优化后代码
import datetime import json import requests class BotLine: secret_token = "secret_token_here" endpoint_url = "https://api.line.me/v2/bot/message/push" destination_id_test = "test_group_id" destination_id_real = "real_group_id" def __init__(self, test_mode="Y"): self._test_mode = test_mode self._chat_content = None @property def test_mode(self): return self._test_mode @test_mode.setter def test_mode(self, value): if value not in ("Y", "N"): raise ValueError("test_mode必须为'Y'或'N'") self._test_mode = value @property def destination_id(self): return self.destination_id_real if self._test_mode == 'N' else self.destination_id_test @property def auth_bearer(self): return f"Bearer {self.secret_token}" @property def headers(self): return {"Content-Type": "application/json", "Authorization": self.auth_bearer} @property def chat_content(self): return self._chat_content @chat_content.setter def chat_content(self, content): self._chat_content = content self._message_data = { "to": self.destination_id, "messages": [ { "type": "text", "text": f"$ {content} $", "emojis": [ {"index": 0, "productId": "5ac2213e040ab15980c9b447", "emojiId": "001"} ] }, {"type": "sticker", "packageId": "6136", "stickerId": "10551377"} ] } @property def message_data(self): if not self._chat_content: raise ValueError("请先设置chat_content") return self._message_data def send_to_chat(self, chat=None): if chat: self.chat_content = chat response = requests.post( self.endpoint_url, data=json.dumps(self.message_data), headers=self.headers, verify=False ) return json.loads(response.text) if __name__ == "__main__": chat_message = f"\N{Robot Face}: Testing - {datetime.datetime.now().strftime('%Y%m%d%H%M%S')}" bot = BotLine(test_mode="Y") response = bot.send_to_chat(chat=chat_message) print(f"{json.dumps(response, indent=2)}")
内容的提问来源于stack exchange,提问作者insignificant
相关产品推荐
相关产品推荐

