求 Python 大佬看看哪个版本的代码比较好,类化争议

2018-02-11 10:53:12 +08:00
 cz5424

近期一个项目要写一个类,跟同学争执不下,特来请教各位大佬

import time

class SchoolDate(object):

    def __init__(self, school_time):
        self.weeks = 1
        self.what_day = 1
        self.school_time = time.strptime(school_time, "%Y-%m-%d")

    def get_term(self):
        timestamp = time.mktime(self.school_time)
        #计算开学前周日的时间戳
        first_week_timestamp=timestamp- 86400* int(time.strftime("%w",self.school_time))
        now_timestamp = time.time()
        self.what_day = time.strftime("%w",time.localtime(now_timestamp))
        #周数 = (当前时间戳 - 开学周日的时间戳) / 7 天 +1
        self.weeks = int((time.time() -first_week_timestamp)/ (86400*7)) + 1
        if self.weeks < 1:
            self.what_day = 1
            self.weeks = 1
        return self

    def weeks(self):
        return self.weeks

    def day(self):
        return self.what_day


版本 2


import time
from datetime import datetime


class SchoolDate(object):
    __get = False

    def __init__(self, starting_date):
        """
        :param starting_date: 开学日期
        """
        self.now_weeks = 1
        self.what_day = 1
        self.starting_date = time.strptime(starting_date, "%Y-%m-%d")

    def _get_term(self):
        self.__get = True
        timestamp = time.mktime(self.starting_date)
        # 计算开学前周日的时间戳
        first_week_timestamp = timestamp - 86400 * int(time.strftime("%w", self.starting_date))
        now_timestamp = time.time()
        self.what_day = time.strftime("%w", time.localtime(now_timestamp))
        # 周数 = (当前时间戳 - 开学周日的时间戳) / 7 天 +1
        self.now_weeks = int((time.time() - first_week_timestamp) / (86400*7)) + 1
        if self.weeks < 1:
            self.what_day = 1
            self.now_weeks = 1

    @property
    def weeks(self):
        """开学第几周"""
        if not self.__get:
            self._get_term()
        return self.now_weeks

    @property
    def week_day(self):
        """周几"""
        if not self.__get:
            self._get_term()
        return self.what_day

    @property
    def school_year(self):
        """获取当前学年"""
        now = datetime.now()
        if 2 <= now.month <= 7:
            return "%d-%d" % ((now.year - 1), now.year)
        else:
            return "%d-%d" % (now.year, (now.year + 1))

初级写法,敬请吐槽!!

2350 次点击
所在节点    问与答
17 条回复
msg7086
2018-02-11 10:59:33 +08:00
school_year 这个方法只有版本 2 里有。
__get 这个只是数据缓存标志位吧。
最理想的做法大概是用非侵入式元编程来智能缓存,但是说白了,没有数据量要求,怎么写都行。更重要的是可读性可维护性,缓存什么的无所谓啦。就说版本 1,如果有一天客户说,我们流量大了要提速,让你改成版本 2,你觉得会花多久?
cz5424
2018-02-11 11:06:39 +08:00
这个类不只是做周数计算,而且我想吐槽版本 1 的一点是,必须调用 get_term 才能获取下面两个参数
@msg7086
bigzhu
2018-02-11 11:08:29 +08:00
用 python 当然是别用类啊
msg7086
2018-02-11 11:08:52 +08:00
sd.get_term().weeks()?链式调用我觉得也还行。

这个类到底是做什么的你也没说啊。
cz5424
2018-02-11 11:10:12 +08:00
调用版本一
school = shooldate().get_term()
school.weeks()
cz5424
2018-02-11 11:11:09 +08:00
@msg7086 做各种校园时间计算,计算学期,学年,第几周,周几
msg7086
2018-02-11 11:13:39 +08:00
@cz5424 schooldate().get_term().weeks()
leavic
2018-02-11 11:17:40 +08:00
simple is better
cz5424
2018-02-11 11:30:12 +08:00
@msg7086 如果用链式,这样的缺点是每次获取都要计算一次吧,他要获取的往往并不止一个参数,也就是得到周几的时候还要知道这一周是第几周
msg7086
2018-02-11 11:31:46 +08:00
@cz5424 参考#1 最后一段内容。
没有性能要求的时候,随便你怎么写。甚至越简单越好,因为越简单的代码,越容易读懂和针对性优化。
ipwx
2018-02-11 11:51:19 +08:00
永远不要让外部调用者接触类内部的缓存策略。

第一个版版直接枪毙。

第二个版本,_get_term 命名不合理。get_XXX 一般默认不引起副作用,哪怕是私有(保护)函数。

p.s. 为啥第二个版本不初始化 now_weeks = what_day = None,通过 is None 决定是否调用 _get_term,而要一个单独的 __get 标志位?
ipwx
2018-02-11 11:58:35 +08:00
我觉得楼主和你的小伙伴最好注意一下“副作用”有关的各种约定。

面向对象设计中,为了让调用更安全,函数语义上最好隔离“读取”和“写入”。换句话说,叫做 get_xxx 的,语义上应该只返回状态而不更改状态,叫做 set_xxx 的则只更改状态而不返回状态(返回 self 例外,这是链式调用)。

缓存策略是另一回事。它应该对调用者透明。换句话说,你要是不高兴现在的缓存策略,可以随时更换,而不影响接口语义。所以你第一个版本是不对的,因为调用者需要明确知道 get_term 引起一次缓存,这个接口设计是不合理的。
fxxkgw
2018-02-11 12:16:12 +08:00
第一个版本属性 weeks 和方法 weeks 难道不冲突么? SchoolDate object 加入叫 t,那 t.weeks t.weeks() 都能 OK 么?
cz5424
2018-02-11 12:26:23 +08:00
@fxxkgw 不会的,第二个版本会冲突所以我改了,第一个版本是函数,第二个版本是参数
cz5424
2018-02-11 12:28:20 +08:00
@ipwx 感谢,😂😂我就觉得一定要知道有 get_term 才能用其他函数问题很大
paicha
2018-02-11 14:54:32 +08:00
ipwx 说的已经挺多的,结构上第二种会比较好,还有命名写法的细节可以改进。

其实没什么好争论的,Python 已经是有相当多最佳实践的例子了,可以阅读学习一些优秀开源项目代码。
hsuan
2018-02-11 15:13:28 +08:00
两个都不咋地,好的代码要做到自解释,看到就应该明白是做什么的,该怎么用。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/430141

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX