Python类方法与静态方法选型咨询:此函数是否需用类方法?
import json from urllib.request import urlopen class Website: def __init__(self, username, privateID): self.username = username self.privateID = privateID # URL's to query AccountBalance = 'https://website.com/private/AccountBalance?{0}?nonce={1}' # 0 requires private ID num TopComments = 'https://website.com/public/TopComments?nonce={0}' def get_AccountBalance(self): nonce = gen_nonce(8) print(json.load(urlopen(AccountBalance.format(self.privateID, nonce)))) @staticmethod def gen_nonce(length): return ''.join([str(random.randint(0, 9)) for i in range(length)])
我仍在学习Python中不同类型类方法的适用场景,当前项目遇到困惑:项目中会创建多个Website类实例,但所有实例需查询的URL固定,因此计划将URL设为类变量。但实际从URL获取数据时,应使用类方法、静态方法还是抽象方法?我认为获取账户余额的方法因各实例privateID不同,或许该用抽象方法;
gen_nonce()无需类或实例变量,应为静态方法。但获取热门评论的方法,是因使用类变量URL而用类方法,还是因并非所有实例同时调用而用抽象方法?
让我一步步帮你理清Python中类方法、静态方法、实例方法的适用场景,结合你的代码来分析:
1. 类变量URL的设计是正确的
你把AccountBalance和TopComments设为类变量的思路非常合理——所有Website实例共享固定的URL模板,既节省内存,也方便后续统一修改维护,不需要逐个实例去更新。
2. 获取账户余额:应该用实例方法(不是抽象方法)
你提到的抽象方法是用来定义父类的接口,要求子类必须实现对应方法的,你的场景完全不需要这个。get_AccountBalance需要访问每个实例独有的privateID,所以必须是实例方法(也就是默认带self参数的方法),这样才能通过self.privateID获取当前实例的私有ID,拼接成正确的请求URL。
另外你的代码里有几个小问题需要修正:
- 调用类变量
AccountBalance时,要通过self.AccountBalance或者Website.AccountBalance访问,否则会报未定义错误; - URL的参数分隔符应该是
&而不是第二个?,正确的格式应该是:AccountBalance = 'https://website.com/private/AccountBalance?privateID={0}&nonce={1}' - 调用
gen_nonce时,要通过self.gen_nonce(8)或者Website.gen_nonce(8)来调用,因为它是类里的静态方法。
修正后的get_AccountBalance大概是这样:
def get_AccountBalance(self): nonce = self.gen_nonce(8) print(json.load(urlopen(self.AccountBalance.format(self.privateID, nonce))))
3. gen_nonce():你的判断完全正确,用静态方法
这个方法不需要访问任何类属性或实例属性,只是一个独立的工具函数——生成指定长度的随机数字字符串。用@staticmethod非常合适,它不需要self或cls参数,放在类里只是为了把相关功能归类在一起,让代码结构更清晰。
4. 获取热门评论:推荐用类方法
获取热门评论的方法不需要实例的任何属性(因为是公开接口),但需要使用类变量TopComments。这种情况下,类方法比静态方法更合适:
- 类方法的第一个参数是
cls,可以通过cls.TopComments访问当前类的URL模板,如果以后你需要子类化Website类(比如创建一个BlogWebsite子类重写TopComments的URL),类方法会自动使用子类的类变量,灵活性更高; - 如果用静态方法,你需要硬编码
Website.TopComments,子类继承后无法自动复用逻辑,扩展性差。
示例的热门评论方法可以写成这样:
@classmethod def get_TopComments(cls): nonce = cls.gen_nonce(8) print(json.load(urlopen(cls.TopComments.format(nonce))))
这样不管是直接调用Website.get_TopComments(),还是通过实例调用my_website.get_TopComments(),都能正常工作,而且子类重写URL后也能无缝使用这个方法。
内容的提问来源于stack exchange,提问作者user9375283

