洛阳市涧西区建设局网站,平台商业模式有哪些,沈阳做网站有名公司,广州安全教育平台注册Python 类对象
经典迭代器 可迭代对象的定义#xff1a; 使用内置的iter可以获取迭代器的对象。如果对象实现了能返回迭代器的__iter__方法#xff0c;那么对象就是可迭代的。序列都可以迭代。实现了__getitem__方法#xff0c;而且接受从0开始的索引#xff0c;这种对象也…Python 类对象
经典迭代器 可迭代对象的定义 使用内置的iter可以获取迭代器的对象。如果对象实现了能返回迭代器的__iter__方法那么对象就是可迭代的。序列都可以迭代。实现了__getitem__方法而且接受从0开始的索引这种对象也是可以迭代的。 可迭代对象与迭代器之间的关系Python从可迭代对象中获取迭代器。
import re
import reprlibRE_WORD re.compile(r\w)class SentenceV2:def __init__(self, text):self.text textself.words RE_WORD.findall(text)def __repr__(self):return fSentence({reprlib.repr(self.text)})def __iter__(self):# 返回一个迭代器return SentenceIterator(self.words)class SentenceIterator:def __init__(self, words):self.words words # 初始化索引self.index 0def __next__(self):try:word self.words[self.index]except IndexError:raise StopIteration()self.index 1return worddef __iter__(self): return self可迭代对象有一个__iter__方法每次都实例化一个新迭代器。迭代器要实现__next__方法返回单个元素此外还要实现__iter__方法返回迭代器本身。迭代器也是可迭代对象但是可迭代对象不是迭代器。
生成器函数
import re
import reprlibRE_WORD re.compile(r\w)class SentenceV3:def __init__(self, text):self.text textself.words RE_WORD.findall(text)def __repr__(self):return Sentence(%s) % reprlib.repr(self.text)def __iter__(self):for word in self.words:# 产生当前的wordyield wordclass ArithmeticProgression:def __init__(self, begin, step, endNone):self.begin beginself.step stepself.end end # None - infinite seriesdef __iter__(self):result_type type(self.begin self.step)result result_type(self.begin)forever self.end is Nonewhile forever or result self.end:yield resultresult self.step只要Python函数的主体中有yield关键字该函数就是生成器函数。调用生成器函数返回一个生成器对象。
生成器工作原理
生成器函数创建一个生成器对象包装生成器函数的主体。把生成器对象传给next()函数时生成器函数提前执行函数主体中的下一个yield语句返回产出的值并在函数主体的当前位置暂停。函数的主体返回时Python创建的外层生成器对象抛出StopIteration异常。
上下文管理器
import sysclass LookingGlass:def __enter__(self):self.original_write sys.stdout.write# 打上猴子补丁sys.stdout.write self.reverse_writereturn JABBERWOCKYdef reverse_write(self, text):# 反转参数的内容self.original_write(text[::-1])def __exit__(self, exc_type, exc_value, traceback):# 将原来的方法还原sys.stdout.write self.original_writeif exc_type is ZeroDivisionError:print(Please DO NOT divide by zero!)return TrueVector2d
from array import array
import math class Vector2d: typecode d def __init__(self, x, y): self.x float(x) self.y float(y) # 可以解包 v Vector2d(2,2)# x,y vdef __iter__(self): return (i for i in (self.x, self.y)) # print返回def __repr__(self): class_name type(self).__name__ return {}({!r}, {!r}).format(class_name, *self) def __str__(self): # 调用__iter__return str(tuple(self)) def __bytes__(self): return (bytes([ord(self.typecode)]) bytes(array(self.typecode, self))) # 判断Vector2d是否相等def __eq__(self, other): return tuple(self) tuple(other) def __abs__(self): return math.hypot(self.x, self.y)def __bool__(self): return bool(abs(self)) 格式化显示 format(42, b)
101010 format(2 / 3, .1%)
66.7%
# datetime类重构了__format__方法from datetime import datetime now datetime.now() format(now, %H:%M:%S)
18:49:05 Its now {:%I:%M %p}.format(now)
Its now 06:49 PMdef __format__(self, fmt_spec): components (format(c, fmt_spec) for c in self) return ({}, {}).format(*components) v1 Vector2d(3, 4) format(v1)
(3.0, 4.0) format(v1, .2f)
(3.00, 4.00) format(v1, .3e)
(3.000e00, 4.000e00)可哈希的
为了把 Vector2d 实例变成可哈希的必须实现 hash 方法 还需要 eq 方法前面已经实现了。此外还要让向量实例 不可变
class Vector2d: typecode d def __init__(self, x, y): self.__x float(x) self.__y float(y) property def x(self): return self.__x property def y(self): return self.__y def __hash__(self): return hash((self.x, self.y))使用 slots 节省空间
默认情况下Python 把各个实例的属性存储在一个名为 dict 的字典中字典消耗的内存很多。但是如果定义一个名为 slots 的类属性以序列的形式 存储属性名称那么 Python 将使用其他模型存储实例属性 slots 中的属性名称存储在一个隐藏的引用数组中消耗的内 存比字典少。 class Pixel:
... __slots__ (x, y)
... p Pixel() p.__dict__
Traceback (most recent call last): ...
AttributeError: Pixel object has no attribute __dict__ p.x 10 p.y 20
# 不允许添加其他属性p.color red
Traceback (most recent call last): ...
AttributeError: Pixel object has no attribute colorVector
多维向量 Vector([3.1, 4.2])
Vector([3.1, 4.2]) Vector((3, 4, 5))
Vector([3.0, 4.0, 5.0]) Vector(range(10))
Vector([0.0, 1.0, 2.0, 3.0, 4.0, ...])from array import array
import reprlib
import math class Vector: typecode d def __init__(self, components): self._components array(self.typecode, components) def __iter__(self): return iter(self._components) def __repr__(self): # 替换为省略号# 返回array(d, [0.0, 1.0, 2.0, 3.0, 4.0, ...])components reprlib.repr(self._components) components components[components.find([):-1] return fVector({components}) def __str__(self): return str(tuple(self)) def __bytes__(self): return (bytes([ord(self.typecode)]) bytes(self._components)) # 调用len()返回def __len__(self): return len(self._components) def __eq__(self, other): if len(self) ! len(other): return False for a, b in zip(self, other): if a ! b: return False return True def __abs__(self): return math.hypot(*self) def __bool__(self): return bool(abs(self))切片 def __getitem__(self, index): return self._components[index]v1 Vector([3, 4, 5]) len(v1)
3 v1[0], v1[-1]
(3.0, 5.0) v7 Vector(range(7))
# 返回的是arrayv7[1:4]
array(d, [1.0, 2.0, 3.0])def __getitem__(self, key): # 调用Vector[a:b:c] 传入的是slice(a,b,c)if isinstance(key, slice): cls type(self) return cls(self._components[key]) # 调用Vector[a]index operator.index(key) return self._components[index] 动态存取属性
# 希望xyzt能获取前4个元素v Vector(range(10)) v.x
0.0 v.y, v.z, v.t
(1.0, 2.0, 3.0)__match_args__ (x, y, z, t) def __getattr__(self, name): cls type(self) try: pos cls.__match_args__.index(name) except ValueError: pos -1 if 0 pos len(self._components): return self._components[pos] msg f{cls.__name__!r} object has no attribute {name!r} raise AttributeError(msg)a Vector(range(9))a
Vector([0.0, 1.0, 2.0, 3.0, 4.0, ...])a.x
0.0a.y
1.0
# x不应该可以直接复制这样会创建一个x变量a.x 10a
Vector([0.0, 1.0, 2.0, 3.0, 4.0, ...])a.x
10# 赋值操作def __setattr__(self, name, value): cls type(self) if len(name) 1: if name in cls.__match_args__: error readonly attribute {attr_name!r} elif name.islower(): error cant set attributes a to z in
{cls_name!r} else: error if error: msg error.format(cls_namecls.__name__,
attr_namename) raise AttributeError(msg) # 没问题就调用父类方法super().__setattr__(name, value) 哈希 def __hash__(self): hashes (hash(x) for x in self._components) # reduce类似于递归函数sum、any 和 all的本质都是调用reducereturn functools.reduce(operator.xor, hashes, 0) msg error.format(cls_namecls.__name__, attr_namename) raise AttributeError(msg) # 没问题就调用父类方法 super().setattr(name, value) ### 哈希pythondef __hash__(self): hashes (hash(x) for x in self._components) # reduce类似于递归函数sum、any 和 all的本质都是调用reducereturn functools.reduce(operator.xor, hashes, 0)