本文的文字及圖片來(lái)源于網(wǎng)絡(luò),僅供學(xué)習(xí)、交流使用,不具有任何商業(yè)用途,,版權(quán)歸原作者所有愕提,如有問(wèn)題請(qǐng)及時(shí)聯(lián)系我們以作處理
作者:測(cè)試游記?? 來(lái)源:推酷
本文鏈接:https://mp.weixin.qq.com/s?__biz=MzU5NTI3NDcxOA==&mid=2247485037&idx=1&sn=c95320355
想要獲取更多Python學(xué)習(xí)資料涕蜂,了解更多關(guān)于Python的知識(shí)华匾,可以加Q群630390733踴躍發(fā)言,大家一起來(lái)學(xué)習(xí)討論吧机隙!
把協(xié)議當(dāng)作正式接口
repr
reprlib.repr用于生成大型結(jié)構(gòu)或遞歸結(jié)構(gòu)的安全表示形式蜘拉。
它會(huì)限制輸出字符串的長(zhǎng)度萨西,用「…」表示截?cái)嗟牟糠帧?/p>
注意:調(diào)用__repr__函數(shù)的目的是調(diào)試,因此絕對(duì)不能拋出異常旭旭,盡量輸出有用的內(nèi)容谎脯,讓用戶(hù)能夠識(shí)別目標(biāo)對(duì)象。
協(xié)議
在面向?qū)ο缶幊讨心瑓f(xié)議是非正式的接口穿肄,只在文檔中定義年局,在代碼中不定義际看。
協(xié)議是非正式的,沒(méi)有強(qiáng)制力矢否,因此如果知道類(lèi)的具體使用場(chǎng)景仲闽,通常只需要實(shí)現(xiàn)一個(gè)協(xié)議的部分。
切片原理
class A:
? ? def __getitem__(self, item):
? ? ? ? return item
if __name__ == '__main__':
? ? a = A()
? ? print(a[1])? # 1
? ? print(a[1:4])? # slice(1, 4, None)
? ? print(a[1:4:2])? # slice(1, 4, 2)
? ? print(a[1:4:2, 9])? # (slice(1, 4, 2), 9)
? ? print(a[1:4:2, 7:9])? # (slice(1, 4, 2), slice(7, 9, None))
slice是內(nèi)置的類(lèi)型僵朗,它的indices方法開(kāi)放了內(nèi)置序列實(shí)現(xiàn)的邏輯赖欣,用于優(yōu)雅的處理缺失索引和負(fù)數(shù)索引,以及長(zhǎng)度超過(guò)目標(biāo)序列的切片验庙。
classslice(start,stop[,step])
返回一個(gè)表示由range(start, stop, step)所指定索引集的 slice 對(duì)象顶吮。其中start和step參數(shù)默認(rèn)為None。切片對(duì)象具有僅會(huì)返回對(duì)應(yīng)參數(shù)值(或其默認(rèn)值)的只讀數(shù)據(jù)屬性start,stop和step粪薛。它們沒(méi)有其他的顯式功能悴了;不過(guò)它們會(huì)被 NumPy 以及其他第三方擴(kuò)展所使用。切片對(duì)象也會(huì)在使用擴(kuò)展索引語(yǔ)法時(shí)被生成违寿。例如:a[start:stop:step]或a[start:stop, i]湃交。
# [:10:2]? [0:5:2]
slice(None, 10, 2).indices(5) # (0, 5, 2)
# [-3::]? [2:5:1]
slice(-3, None, None).indices(5) # (2, 5, 1)
?
indices
獲取實(shí)例所屬類(lèi)
通過(guò)type(self)可以拿到實(shí)例所屬的類(lèi)
動(dòng)態(tài)存取屬性
屬性查找失敗后,解釋器會(huì)調(diào)用__getattr__方法藤巢。
示例代碼
# -*- coding: utf-8 -*-
# @Time? ? : 2020/12/27 下午3:07
# @Author? : zhongxin
# @Email? : 490336534@qq.com
# @File? ? : vector.py
import itertools
import numbers
import functools
import operator
from array import array
import reprlib
import math
class Vector:
? ? typecode = 'd'? # 類(lèi)屬性
? ? shortcut_names = 'xyzt'
? ? def __init__(self, components):
? ? ? ? self._components = array(self.typecode, components)
? ? def __iter__(self):
? ? ? ? return iter(self._components)
? ? def __repr__(self):
? ? ? ? components = reprlib.repr(self._components)
? ? ? ? components = components[components.find('['):-1]
? ? ? ? return f'Vector({components})'
? ? def __str__(self):
? ? ? ? return str(tuple(self))
? ? def __bytes__(self):
? ? ? ? return (bytes([ord(self.typecode)]) + bytes(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
? ? ? ? return len(self) == len(other) and all(a == b for a, b in zip(self, other))
? ? def __hash__(self):
? ? ? ? # hashes = (hash(x) for x in self._components)
? ? ? ? hashes = map(hash, self._components)
? ? ? ? return functools.reduce(operator.xor, hashes, 0)
? ? def __abs__(self):
? ? ? ? return math.sqrt(sum(x * x for x in self))
? ? def __bool__(self):
? ? ? ? return bool(abs(self))
? ? def __len__(self):
? ? ? ? return len(self._components)
? ? def __getitem__(self, item):
? ? ? ? cls = type(self)? # 獲取實(shí)例所屬類(lèi)
? ? ? ? if isinstance(item, slice):
? ? ? ? ? ? return cls(self._components[item])
? ? ? ? elif isinstance(item, numbers.Integral):
? ? ? ? ? ? return self._components[item]
? ? ? ? else:
? ? ? ? ? ? msg = '{cls.__name__} 切片必須是整數(shù)'
? ? ? ? ? ? raise TypeError(msg.format(cls=cls))
? ? def __getattr__(self, name):
? ? ? ? cls = type(self)
? ? ? ? if len(name) == 1:
? ? ? ? ? ? pos = cls.shortcut_names.find(name)
? ? ? ? ? ? if 0 <= pos < len(self._components):
? ? ? ? ? ? ? ? return self._components[pos]
? ? ? ? msg = '{.__name__!r} object has no attribute {!r}'
? ? ? ? raise AttributeError(msg.format(cls, name))
? ? def __setattr__(self, name, value):
? ? ? ? cls = type(self)
? ? ? ? if len(name) == 1:
? ? ? ? ? ? if name in cls.shortcut_names:
? ? ? ? ? ? ? ? error = 'readonly attribute {attr_name!r}'
? ? ? ? ? ? elif name.islower():
? ? ? ? ? ? ? ? error = "can't set attributes 'a' to 'z' in {cls_name!r}"
? ? ? ? ? ? else:
? ? ? ? ? ? ? ? error = ''
? ? ? ? ? ? if error:
? ? ? ? ? ? ? ? msg = error.format(cls_name=cls.__name__, attr_name=name)
? ? ? ? ? ? ? ? raise AttributeError(msg)
? ? ? ? super().__setattr__(name, value)
? ? def angle(self, n):
? ? ? ? r = math.sqrt(sum(x * x for x in self[n:]))
? ? ? ? a = math.atan2(r, self[n - 1])
? ? ? ? if (n == len(self) - 1) and (self[-1] < 0):
? ? ? ? ? ? return math.pi * 2 - a
? ? ? ? else:
? ? ? ? ? ? return a
? ? def angles(self):
? ? ? ? return (self.angle(n) for n in range(1, len(self)))
? ? def __format__(self, format_spec=''):
? ? ? ? if format_spec.endswith('h'):
? ? ? ? ? ? format_spec = format_spec[:-1]
? ? ? ? ? ? coords = itertools.chain([abs(self)], self.angles())
? ? ? ? ? ? outer_fmt = '<{}>'
? ? ? ? else:
? ? ? ? ? ? coords = self
? ? ? ? ? ? outer_fmt = '({})'
? ? ? ? components = (format(c, format_spec) for c in coords)
? ? ? ? return outer_fmt.format(','.join(components))
? ? @classmethod
? ? def frombytes(cls, octets):
? ? ? ? typecode = chr(octets[0])
? ? ? ? memv = memoryview(octets[1:]).cast(typecode)
? ? ? ? return cls(memv)