在dateutil.rrule的rrulestr()方法中使用__call__方法的说明

时间:2016-11-25 19:09:47

标签: python

Python的dateutil.rrule模块有一个带有自定义rrule方法的__str__对象,以及一个执行逆操作的方法rrulestr,即重构一个rrule 1}}来自其字符串表示的对象。以下是其使用说明:

In [1]: from dateutil.rrule import *

In [2]: my_rrule = rrule(DAILY, count=2)

In [3]: list(my_rrule)
Out[3]: 
[datetime.datetime(2016, 11, 25, 19, 58, 40),
 datetime.datetime(2016, 11, 26, 19, 58, 40)]

In [4]: list(rrulestr(str(my_rrule)))
Out[4]: 
[datetime.datetime(2016, 11, 25, 19, 58, 40),
 datetime.datetime(2016, 11, 26, 19, 58, 40)]

我想用不同的对象做类似的事情,所以我试图理解这是如何在rrule的source code中实现的。以下是其中包含的内容的“浓缩”摘录:

class _rrulestr(object):

    def _parse_rfc(self, s,
                   dtstart=None,
                   cache=False,
                   unfold=False,
                   forceset=False,
                   compatible=False,
                   ignoretz=False,
                   tzinfos=None):
        global parser

    def __call__(self, s, **kwargs):
        return self._parse_rfc(s, **kwargs)

rrulestr = _rrulestr()

据我了解,为__call__类定义的_rrulestr方法使其基本上像一个函数。这种方法的优点是什么?为什么不直接将rrulestr定义为函数?并且有人可以一步一步地向我解释这是如何工作的吗?

P.S。我也在模仿这种“可调课程”的风格方面遇到了问题。例如,如果我尝试

#!/usr/bin/env python3.5

class CallableClass(object):
    def __call__(self, arg):
        return arg

print(CallableClass("Hello"))

我得到TypeError

Traceback (most recent call last):
  File "/home/kurt/Documents/Scratch/call_test.py", line 7, in <module>
    print(CallableClass("Hello"))
TypeError: object() takes no parameters

但我不知道这个例子与_rrulestr有什么不同?

1 个答案:

答案 0 :(得分:1)

“可调用类”的意思是它是可调用的实例。当然,任何类都是可调用的,因为调用类会给你一个实例;但定义__call__方法意味着生成的实例也可以调用。

所以,你的代码应该是:

print(CallableClass()("Hello"))

如您所见,rrule模块在​​最后定义了它的实例:rrulestr = _rrulestr() - 它就是您调用的对象。