pythonic code_Pythonic Code (Part II)

Iterable Objects

实现可迭代对象的方法有三种:第一种是类内实现 __iter__ 和 __next__ 方法, 第二种是使用 generator, 第三种是封装一个序列。__iter__ 和 __next__

from datetime import timedelta

class DateRangeIterable:

def __init__(self, start_date, end_date):

self.start_date = start_date

self.end_date = end_date

self._present_day = start_date

def __iter__(self):

return self

def __next__(self):

if self._present_day >= self.end_date:

raise StopIteration

today = self._present_day

self._present_day += timedelta(days=1)

return today使用 generator

from datetime import timedelta

class DateRangeContainerIterable:

def __init__(self, start_date, end_date):

self.start_date = start_date

self.end_date = end_date

def __iter__(self):

current_day = self.start_date

while current_day < self.end_date:

yield current_day

current_day += timedelta(days=1)封装一个序列

from datetime import timedelta

class DateRangeSequence:

"""An range created by wrapping a sequence."""

def __init__(self, start_date, end_date):

self.start_date = start_date

self.end_date = end_date

self._range = self._create_range()

def _create_range(self):

days = []

current_day = self.start_date

while current_day < self.end_date:

days.append(current_day)

current_day += timedelta(days=1)

return days

def __getitem__(self, day_no):

return self._range[day_no]

def __len__(self):

return len(self._range)

Container Objects

在 Python 中,实现了 __contains__ 方法的类就是容器类。当对该类使用 in 关键字的时候这个方法就会被调用。

element in container == container.__contains__(element)

示例代码:

class Criteria:

def __init__(self, height, weight):

self.height = height

self.weight = weight

def __contains__(self, person):

h, w = person

return 0 < h < self.height and 0 < w < self.weight

class Scope:

def __init__(self, height, weight):

self.criteria = Criteria(height, weight)

def __contains__(self, person):

return person in self.criteria

def mark_person(scope, person):

if person in scope:

scope[person] = 1

Dynamic attributes for objects

当我们做 . 调用的时候, Python 首先会对 object 的内部字典调用 __getattribute__ 方法,如果没有找到对应的 attribute,就会以 attribute 作为参数调用 __getattr__ 方法。

class DemoAttribute:

"""docstring for DemoAttribute"""

def __init__(self, attr):

self.attr = attr

def __getattr__(self, attr):

if attr.startswith("test"):

name = attr.replace("test", "")

return f"[test replaced]{name}"

raise AttributeError(f"{self.__class__.__name__}has no attribute{attr}")

下面是执行结果

>>> da = DemoAttribute("value")

>>> da.attr

'value'

>>> da.test_value

'[test replaced] _value'

>>> da.value

Traceback (most recent call last):

File "", line 1, in

File "testattr.py", line 19, in __getattr__

raise AttributeError(f"{self.__class__.__name__} has no attribute {attr}")

AttributeError: DemoAttribute has no attribute value

Callable objects

每当我们调用一个 Object 的时候,像这样 object(*args,**kwargs),其实 Python 是执行 object.__call__(*args, **kwargs).

from collections import defaultdict

class Count:

"""docstring for Count"""

def __init__(self):

self._count = defaultdict(int)

def __call__(self, value):

self._count[value] += 1

return self._count[value]

下面是执行结果

>>> c = Count()

>>> c(1)

1

>>> c(1)

2

>>> c(2)

1

>>> c(2)

2

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值