欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Python中序列的修改、散列與切片詳解

 更新時間:2017年08月27日 14:47:07   作者:demon_gdy  
在Python中,最基本的數(shù)據(jù)結(jié)構(gòu)是序列(sequence)。下面這篇文章主要給大家介紹了關(guān)于Python中序列的修改、散列與切片的相關(guān)資料文中通過示例代碼介紹的非常詳細,需要的朋友可以參考,下面來一起看看吧。

前言

本文主要給大家介紹了關(guān)于Python中序列的修改、散列與切片的相關(guān)內(nèi)容,分享出來供大家參考學習,下面話不多說了,來一起看看詳細的介紹吧。

Vector類:用戶定義的序列類型

  我們將使用組合模式實現(xiàn) Vector 類,而不使用繼承。向量的分量存儲在浮點數(shù)數(shù)組中,而且還將實現(xiàn)不可變扁平序列所需的方法。

Vector 類的第 1 版要盡量與前一章定義的 Vector2d 類兼容。

Vector類第1版:與Vector2d類兼容

Vector 類的第 1 版要盡量與前一章定義的 Vector2d 類兼容。然而我們會故意不讓 Vector 的構(gòu)造方法與 Vector2d 的構(gòu)造方法兼容。為了編寫 Vector(3, 4) 和 Vector(3, 4, 5) 這樣的代碼,我們可以讓 __init__ 方法接受任意個參數(shù)(通過 *args);但是,序列類型的構(gòu)造方法最好接受可迭代的對象為參數(shù),因為所有內(nèi)置的序列類型都是這樣做的。

測試 Vector.__init__ 和 Vector.__repr__ 方法

>>> 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, ...])

vector_v1.py:從 vector2d_v1.py 衍生而來

from array import array
import reprlib
import math


class Vector:
 typecode = 'd'

 def __init__(self, components):
 self._components = array(self.typecode, components)  #self._components是“受保護的”實例屬性,把Vector的分量保存在一個數(shù)組中

 def __iter__(self):
 return iter(self._components)    #為了迭代,我們使用self._components構(gòu)建一個迭代器

 def __repr__(self):
 components = reprlib.repr(self._components)   #使用reprlib.repr()函數(shù)獲取self._components 的有限長度表示形式(如 array('d', [0.0, 1.0, 2.0, 3.0, 4.0, ...]))
 components = components[components.find('['):-1]  #把字符串插入 Vector 的構(gòu)造方法調(diào)用之前,去掉前面的array('d' 和后面的 )
 return 'Vecotr({})'.format(components)   #直接使用 self._components 構(gòu)建 bytes 對象

 def __str__(self):
 return str(tuple(self))

 def __bytes__(self):
 return (bytes([ord(self.typecode)]) +
  bytes(self._components))

 def __eq__(self, other):
 return tuple(self) == tuple(other)

 def __abs__(self):
 return math.hypot(sum(x * x for x in self))   #不能使用hypot方法了,因此我們先計算各分量的平方之和,然后再使用sqrt方法開平方

 def __bool__(self):
 return bool(abs(self))

 @classmethod
 def frombytes(cls, octets):
 typedcode = chr(octets[0])
 memv = memoryview(octets[1:]).cast(typedcode)
 return cls(memv)      #我們只需在 Vector2d.frombytes 方法的基礎(chǔ)上改動最后一行:直接把memoryview傳給構(gòu)造方法,不用像前面那樣使用*拆包

協(xié)議和鴨子類型

在 Python 中創(chuàng)建功能完善的序列類型無需使用繼承,只需實現(xiàn)符合序列協(xié)議的方法。不過,這里說的協(xié)議是什么呢?

在面向?qū)ο缶幊讨?,協(xié)議是非正式的接口,只在文檔中定義,在代碼中不定義。例如,Python 的序列協(xié)議只需要 __len__ 和 __getitem__ 兩個方法。任何類(如 Spam),只要使用標準的簽名和語義實現(xiàn)了這兩個方法,就能用在任何期待序列的地方。Spam 是不是哪個類的子類無關(guān)緊要,只要提供了所需的方法即可。

class FrenchDeck:
 ranks = [str(n) for n in range(2, 11)] + list('JQKA')
 suits = 'spades diamonds clubs hearts'.split()

 def __init__(self):
 self._cards = [Card(rank, suit) for suit in self.suits for rank in self.ranks]

 def __len__(self):
 return len(self._cards)

 def __getitem__(self, position):
 return self._cards[position]

協(xié)議是非正式的,沒有強制力,因此如果你知道類的具體使用場景,通常只需要實現(xiàn)一個協(xié)議的部分。例如,為了支持迭代,只需實現(xiàn)__getitem__ 方法,沒必要提供 __len__ 方法。

Vector類第2版:可切片的序列

如 FrenchDeck 類所示,如果能委托給對象中的序列屬性(如self._components 數(shù)組),支持序列協(xié)議特別簡單。下述只有一行代碼的 __len__ 和 __getitem__ 方法是個好的開始:

class Vector:
 # 省略了很多行
 # ...

 def __len__(self):
 return len(self._components)

 def __getitem__(self, index):
 return self._components[index]

添加這兩個方法之后,就能執(zhí)行下述操作了:

>>> v1 = Vector([3, 4, 5])
>>> len(v1)
>>> v1[0], v1[-1]
(3.0, 5.0)
>>> v7 = Vector(range(7))
>>> v7[1:4]
array('d', [1.0, 2.0, 3.0])

可以看到,現(xiàn)在連切片都支持了,不過尚不完美。如果 Vector 實例的切片也是 Vector 實例,而不是數(shù)組,那就更好了。前面那個FrenchDeck 類也有類似的問題:切片得到的是列表。對 Vector 來說,如果切片生成普通的數(shù)組,將會缺失大量功能。

為了把 Vector 實例的切片也變成 Vector 實例,我們不能簡單地委托給數(shù)組切片。我們要分析傳給 __getitem__ 方法的參數(shù),做適當?shù)奶幚怼?/p>

切片原理

了解 __getitem__ 和切片的行為

>>> class MySeq:
... def __getitem__(self, index):
...  return index
... 
>>> s = MySeq()              
>>> s[1]                      #__getitem__直接返回傳給它的值
>>> s[1:4]                     #[1:4]表示變成了slice(1, 4, None)
slice(1, 4, None)
>>> s[1:4:2]                    #[1:4:2]的意思為從第1個索引開始,到第4個索引結(jié)束,步長為2
slice(1, 4, 2)          
>>> s[1:4:2, 9]                  
(slice(1, 4, 2), 9)                #神奇的事情發(fā)生了..wtf...如果[]中有逗號,那么__getitem__接收的是元祖
>>> s[1:4:2, 7:9]                 #元祖中還可以包含多個切片對象
(slice(1, 4, 2), slice(7, 9, None))

🌰 查看slice類的屬性

>>> slice
<class 'slice'>
>>> dir(slice)
['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', 

'__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', 

'__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', 

'__sizeof__', '__str__', '__subclasshook__', 'indices', 'start', 'step', 'stop']

調(diào)用 dir(slice) 得到的結(jié)果中有個 indices 屬性,這個方法有很大的作用,但是鮮為人知。help(slice.indices) 給出的信息如下。

indices(...)

S.indices(len) -> (start, stop, stride)

給定長度為 len 的序列,計算 S 表示的擴展切片的起始(start)和結(jié)尾(stop)索引,以及步幅(stride)。超出邊界的索引會被截掉,這與常規(guī)切片的處理方式一樣。

 舉個 🌰 假設(shè)有個長度為5的序列,例如'ABCDE':

>>> slice(None, 10, 2).indices(5)    #'ABCDE'[:10:2]等同于[:]
(0, 5, 2)
>>> slice(-3, None, None).indices(5)  #'ABCDE'[-3:]等同于[2:5:1]
(2, 5, 1)

能處理切片的__getitem__方法

vector_v2.py 的部分代碼:為 vector_v1.py 中的 Vector類添加 __len__ 和__getitem__ 方法

def __len__(self):
 return len(self._components)

 def __getitem__(self, index):
 cls = type(self)      #獲取實例的類(Vector)
 if isinstance(index, slice):    #判斷傳遞進來的index是否為slice對象
  return cls(self._components[index])   #調(diào)用類的構(gòu)造方法,創(chuàng)建一個新的Vector實例
 elif isinstance(index, numbers.Integral):   #如果傳遞進來的是個整數(shù)
  return self._components[index]    #返回 _components 中相應(yīng)的元素
 else:       #拋出異常
  msg = '{cls.__name__} indices must be integers'
  raise TypeError(msg.format(cls=cls))

測試 🌰 改進的 Vector.__getitem__ 方法

>>> v7 = Vector(range(7))
>>> v7[-1]                     #獲取單個整數(shù)索引,返回一個浮點數(shù)
6.0
>>> v7[1:4]                     #切片索引創(chuàng)建一個新的Vector實例
Vector([1.0, 2.0, 3.0])
>>> v7[-1:]                     #長度為1的切片也會創(chuàng)建一個新的Vector實例
Vector([6.0])
>>> v7[1,2]                     #我們在上面的slice已經(jīng)知道,如果slice中包含了,則是一個包含slice的元祖,所以報錯了
Traceback (most recent call last):
...
TypeError: Vector indices must be integers

Vector類第3版:動態(tài)存取屬性

  Vector2d 變成 Vector 之后,就沒辦法通過名稱訪問向量的分量了(如 v.x 和 v.y)?,F(xiàn)在我們處理的向量可能有大量分量。不過,若能通過單個字母訪問前幾個分量的話會比較方便。比如,用 x、y 和 z 代替 v[0]、v[1] 和 v[2]

  在 Vector2d 中,我們使用 @property 裝飾器把 x 和 y 標記為只讀特性。我們可以在 Vector 中編寫四個特性,但這樣太麻煩。特殊方法 __getattr__ 提供了更好的方式。

  屬性查找失敗后,解釋器會調(diào)用 __getattr__ 方法。簡單來說,對my_obj.x 表達式,Python 會檢查 my_obj 實例有沒有名為 x 的屬性;如果沒有,到類(my_obj.__class__ )中查找;如果還沒有,順著繼承樹繼續(xù)查找。 如果依舊找不到,調(diào)用 my_obj 所屬類中定義的__getattr__ 方法,傳入 self 和屬性名稱的字符串形式(如 'x')。

vector_v3.py 的部分代碼:在 vector_v2.py 中定義的Vector 類里添加 __getattr__ 方法

def __getattr__(self, name):
  cls = type(self)           #獲取Vector

  if len(name) == 1:           #如果屬性名只有一個字母,可能是shortcut_names中的一個
   pos = cls.shorcut_name.find(name)      #查找屬性name是否在xyzx中的位置,如果木有就返回-1,有就返回對應(yīng)的索引
   if 0 <= pos < len(self._components):     #判斷這個查找到的索引是否在區(qū)間內(nèi)
    return self._components[pos]      #返回查找的到的數(shù)組中的值
  msg = '{.__name__!r} object has no attribute {!r}'   #報錯的信息
  raise AttributeError(msg.format(cls, name))     #拋出異常

測試下效果:

>>> v = Vector(range(5))
>>> v
Vector([0.0, 1.0, 2.0, 3.0, 4.0])
>>> v.x                # 使用v.x獲取第一個元素v[0]
0.0
>>> v.x = 10             # 為v.x賦新的值,按理說應(yīng)該會報異常
>>> v.x                # 讀取v.x,返回來的是新的值
>>> v
Vector([0.0, 1.0, 2.0, 3.0, 4.0])# 數(shù)組并沒有改變什么~

  如果為 .x 或 .y 實例屬性賦值,會拋出 AttributeError。為了避免歧義,在 Vector 類中,如果為名稱是單個小寫字母的屬性賦值,我們也想拋出那個異常。為此,我們要實現(xiàn) __setattr__ 方法。

vector_v3.py 的部分代碼:在 Vector 類中實現(xiàn)__setattr__ 方法

def __setattr__(self, name, value):
  cls = type(self)
  if len(name) == 1:           #特別處理名稱是單個字符的屬性
   if name in self.shorcut_name:       #如果name是xyzt中的一個,設(shè)置特殊的錯誤消息
    error = 'readonly attribute {attr_name!r}'
   elif name.islower():         #如果name是小寫字母,為所有小寫字母設(shè)置一個錯誤消息
    error = "can't set attributes 'a' to 'z' in {cls_name!r}"
   else:
    error = ''
   if error:            #否則,把錯誤消息設(shè)為空字符串
    msg = error.format(cls_name=cls.__name__, attr_name=name)
    raise AttributeError(msg)       #如果有錯誤消息,拋出 AttributeError
  super().__setattr__(name, value)       #默認情況:在超類上調(diào)用__setattr__方法,提供標準行為

Vector類第4版:散列和快速等值測試

   我們要再次實現(xiàn) __hash__ 方法。加上現(xiàn)有的 __eq__ 方法,這會把Vector 實例變成可散列的對象。

    我們要使用^(異或)運算符依次計算各個分量的散列值,像這樣:v[0] ^ v[1] ^ v[2]...。這正是functools.reduce 函數(shù)的作用。

 

歸約函數(shù)(reduce、sum、any、all)把序列或有限的可迭代對象變成一個聚合結(jié)果

  我們已經(jīng)知道 functools.reduce() 可以替換成 sum() ,下面說說它的原理。它的關(guān)鍵思想是,把一系列值歸約成單個值。reduce() 函數(shù)的第一個參數(shù)是接受兩個參數(shù)的函數(shù),第二個參數(shù)是一個可迭代的對象。假如有個接受兩個參數(shù)的 fn 函數(shù)和一個 lst 列表。調(diào)用reduce(fn, lst) 時,fn 會應(yīng)用到第一對元素上,即 fn(lst[0],lst[1]) ,生成第一個結(jié)果 r1。然后,fn 會應(yīng)用到 r1 和下一個元素上,即 fn(r1, lst[2]) ,生成第二個結(jié)果 r2。接著,調(diào)用 fn(r2,lst[3]) ,生成 r3……直到最后一個元素,返回最后得到的結(jié)果 rN。

舉個🌰  使用 reduce 函數(shù)可以計算 5!(5 的階乘):

>>> 2 * 3 * 4 * 5 # 想要的結(jié)果是:5! == 120
120
>>> import functools
>>> functools.reduce(lambda a,b: a*b, range(1, 6))
120

回到散列問題上。下面的 🌰 展示了計算聚合異或的 3 種方式:一種使用 for 循環(huán),兩種使用 reduce 函數(shù)。

>>> n = 0
>>> for i in range(1, 6):       # 使用for循環(huán)和累加器變量計算聚合異或
... n ^= i
...
>>> n
>>> import functools
>>> functools.reduce(lambda a, b: a^b, range(6))   # 使用reduce傳入匿名函數(shù)
>>> import operator
>>> functools.reduce(operator.xor, range(6))  # 使用 functools.reduce 函數(shù),把 lambda 表達式換成
operator.xor

給代碼中添加__hash__方法

from array import array
import reprlib
import math
import numbers
import functools
import operator


class Vector:
 typecode = 'd'
 shorcut_name = 'xyzt'

 """
 省略的代碼
 """

 def __eq__(self, other):
  return tuple(self) == tuple(other)

 def __hash__(self):
  hashes = (hash(x) for x in self._components)
  return functools.reduce(operator.xor, hashes, 0)   #把hashes提供給reduce函數(shù),使用xor函數(shù)計算聚合的散列值;第三個參數(shù),0 是初始值

注意:

  使用 reduce 函數(shù)時最好提供第三個參數(shù),reduce(function, iterable, initializer) ,這樣能避免這個異常:TypeError: reduce() of empty sequence with no initial value(這個錯誤消息很棒,說明了問題,還提供了解決方法)。如果序列為空,initializer 是返回的結(jié)果;否則,在歸約中使用它作為第一個參數(shù),因此應(yīng)該使用恒等值。比如,對 +、| 和 ^ 來說, initializer 應(yīng)該是 0;而對 * 和 & 來說,應(yīng)該是 1。

實現(xiàn)的 __hash__ 方法是一種映射歸約計算

 

映射歸約:把函數(shù)應(yīng)用到各個元素上,生成一個新序列(映射,map),然后計算聚合值(歸約,reduce)

映射過程計算各個分量的散列值,歸約過程則使用 xor 運算符聚合所有散列值。把生成器表達式替換成 map 方法,映射過程更明顯:

  def __hash__(self):
   hashes = map(hash, self._components)
   return functools.reduce(operator.xor, hashes, 0)   #把hashes提供給reduce函數(shù),使用xor函數(shù)計算聚合的散列值;第三個參數(shù),0 是初始值

為了提高比較的效率,Vector.__eq__ 方法在 for循環(huán)中使用 zip 函數(shù)

def __eq__(self, other):
  if len(self) != len(other):         #如果對比的兩個長度不一樣,返回False
   return False
  for a, b in zip(self, other):        #如果兩個對比Vector實例傳遞的值通過惰性對比,有不不一樣的就返回FALSE
   if a != b:
    return False
  return True

zip的效率很好,不過用于計算聚合值的整個 for 循環(huán)可以替換成一行 all 函數(shù)調(diào)用:如果所有分量對的比較結(jié)果都是 True,那么結(jié)果就是 True。只要有一次比較的結(jié)果是 False,all 函數(shù)就返回False。使用 all 函數(shù)實現(xiàn) __eq__ 方法的方式如下:

使用 zip 和 all 函數(shù)實現(xiàn) Vector.__eq__ 方法,效果和上面的代碼一樣~

 def __eq__(self, other):
  return len(self) == len(other) and all(a == b for a, b in zip(self, other))

出色的 zip 函數(shù)

  使用 for 循環(huán)迭代元素不用處理索引變量,還能避免很多缺陷,但是需要一些特殊的實用函數(shù)協(xié)助。其中一個是內(nèi)置的 zip 函數(shù)。使用 zip 函數(shù)能輕松地并行迭代兩個或更多可迭代對象,它返回的元組可以拆包成變量,分別對應(yīng)各個并行輸入中的一個元素。

舉個 🌰

>>> zip(range(3), 'abc')
<zip object at 0x1024d7b48>
>>> list(zip(range(3), 'abc'))              #zip返回一個生成器,按需生成元祖
[(0, 'a'), (1, 'b'), (2, 'c')]
>>> dict(zip('123', 'abc'))                #使用zip快速構(gòu)造一個字典
{'1': 'a', '2': 'b', '3': 'c'}
>>> from itertools import zip_longest          #使用zip_longest可以給給個fillvalue設(shè)置一個默認值,當元祖迭代盡的時候可以補充默認值
>>> list(zip_longest(range(3), 'ABC', [0.0, 1.1, 2.2, 3.3], fillvalue=-1))
[(0, 'A', 0.0), (1, 'B', 1.1), (2, 'C', 2.2), (-1, -1, 3.3)]

Vector類第5版:格式化

Vector 類的 __format__ 方法與 Vector2d 類的相似,但是不使用極坐標,而使用球面坐標(也叫超球面坐標),因為 Vector 類支持 n 個維度,而超過四維后,球體變成了“超球體”。 因此,我們會把自定義的格式后綴由 'p' 變成 'h'。

下面幾個示例摘自 vector_v5.py 的 doctest,是四維球面坐標格式:

>>> format(Vector([-1, -1, -1, -1]), 'h')
'<2.0, 2.0943951023931957, 2.186276035465284, 3.9269908169872414>'
>>> format(Vector([2, 2, 2, 2]), '.3eh')
'<4.000e+00, 1.047e+00, 9.553e-01, 7.854e-01>'
>>> format(Vector([0, 1, 0, 0]), '0.5fh')
'<1.00000, 1.57080, 0.00000, 0.00000>'

vector_v5.py:Vector 類最終版的 doctest 和全部代碼;帶標號的那幾行是為了支持 __format__ 方法而添加的代碼

from array import array
import reprlib
import math
import numbers
import functools
import operator
import itertools


class Vector:
 typecode = 'd'

 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 'Vector({})'.format(components)

 def __str__(self):
  return str(tuple(self))

 def __bytes__(self):
  return (bytes([ord(self.typecode)]) + bytes(self._components))

 def __eq__(self, other):
  return (len(self) == len(other) and all(a == b for a, b in zip(self, other)))

 def __hash__(self):
  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, index):
  cls = type(self)

  if isinstance(index, slice):
   return cls(self._components[index])
  elif isinstance(index, numbers.Integral):
   return self._components[index]
  else:
   msg = '{.__name__} indices must be integers'
   raise TypeError(msg.format(cls))

 shorcut_names = 'xyzt'

 def __getattr__(self, name):
  cls = type(self)

  if len(name) == 1:
   pos = cls.shorcut_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 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, fmt_spec=''):
  if fmt_spec.endswith('h'):
   fmt_spec = fmt_spec[:-1]
   coords = itertools.chain([abs(self)], self.angles())
   outer_fmt = '<{}>'
  else:
   coords = self
   outer_fmt = '({})'
  components = (format(c, fmt_spec) for c in coords)
  return outer_fmt.format(', '.join(components))

 @classmethod
 def frombytes(cls, octets):
  typecode = octets[0]
  memv = memoryview(octets[1:]).cast(typecode)
  return cls(memv)

測試的結(jié)果為:

"""
A multidimensional ``Vector`` class, take 5
A ``Vector`` is built from an iterable of numbers::

 >>> 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, ...])


Tests with two dimensions (same results as ``vector2d_v1.py``)::

 >>> v1 = Vector([3, 4])
 >>> x, y = v1
 >>> x, y
 (3.0, 4.0)
 >>> v1
 Vector([3.0, 4.0])
 >>> v1_clone = eval(repr(v1))
 >>> v1 == v1_clone
 True
 >>> print(v1)
 (3.0, 4.0)
 >>> octets = bytes(v1)
 >>> octets
 b'd\\x00\\x00\\x00\\x00\\x00\\x00\\x08@\\x00\\x00\\x00\\x00\\x00\\x00\\x10@'
 >>> abs(v1)
 5.0
 >>> bool(v1), bool(Vector([0, 0]))
 (True, False)


Test of ``.frombytes()`` class method:

 >>> v1_clone = Vector.frombytes(bytes(v1))
 >>> v1_clone
 Vector([3.0, 4.0])
 >>> v1 == v1_clone
 True


Tests with three dimensions::

  > >> v1 = Vector([3, 4, 5])
 >>> x, y, z = v1
  >>> x, y, z
 (3.0, 4.0, 5.0)
 >>> v1
 Vector([3.0, 4.0, 5.  0])
 >>> v1_clone = eval(repr(v1))
 >>> v1 == v1_clone
 True
 >>> print(v1)
 (3.0, 4.0, 5.0)
 >> abs(v1) # doctest:+ELLIPSIS
 7.071067811...
 >>> bool(v1), bool(Vector([0, 0, 0]))
 (True, False)


Tests with many dimensions::

 >>> v7 = Vector(range(7))
 >>> v7
 Vector([0.0, 1.0, 2.0, 3.0, 4.0, ...])
 >>> abs(v7) # doctest:+ELLIPSIS
 9.53939201..


Test of ``.__bytes__`` and ``.frombytes()`` methods::
 
 >>> v1 = Vector([3, 4, 5])
 >>> v1_clone = Vector.frombytes(bytes(v1))
 >>> v1_clone
 Vector([3.0, 4.0, 5.0])
 >>> v1 == v1_clone
 True


Tests of sequence behavior::

 >>> v1 = Vector([3, 4, 5])
 >>> len(v1)
 >>> v1[0], v1[len(v1)-1], v1[-1]
 (3.0, 5.0, 5.0)
 

Test of slicing::

 >>> v7 = Vector(range(7))
 >>> v7[-1]
 6.0
 >>> v7[1:4]
 Vector([1.0, 2.0, 3.0])
 >>> v7[-1:]
 Vector([6.0])
 >>> v7[1,2]
 Traceback (most recent call last):
 ...
 TypeError: Vector indices must be integers


Tests of dynamic attribute access::

 >>> v7 = Vector(range(10))
 >>> v7.x
 0.0
 >>> v7.y, v7.z, v7.t
 (1.0, 2.0, 3.0)


Dynamic attribute lookup failures::

 >>> v7.k
 Traceback (most recent call last):
 ...
 AttributeError: 'Vector' object has no attribute 'k'
 >>> v3 = Vector(range(3))
 >>> v3.t
 Traceback (most recent call last):
 ...
 AttributeError: 'Vector' object has no attribute 't'
 >>> v3.spam
 Traceback (most recent call last):
 ...
 AttributeError: 'Vector' object has no attribute 'spam'


Tests of hashing::

 >>> v1 = Vector([3, 4])
 >>> v2 = Vector([3.1, 4.2])
 >>> v3 = Vector([3, 4, 5])
 >>> v6 = Vector(range(6))
 >>> hash(v1), hash(v3), hash(v6)
 (7, 2, 1)


Most hash values of non-integers vary from a 32-bit to 64-bit CPython build::

 >>> import sys
 >>> hash(v2) == (384307168202284039 if sys.maxsize > 2**32 else 357915986)
 True


Tests of ``format()`` with Cartesian coordinates in 2D::

 >>> v1 = Vector([3, 4])
 >>> format(v1)
 '(3.0, 4.0)'
 >>> format(v1, '.2f')
 '(3.00, 4.00)'
 >>> format(v1, '.3e')
 '(3.000e+00, 4.000e+00)'


Tests of ``format()`` with Cartesian coordinates in 3D and 7D::

 >>> v3 = Vector([3, 4, 5])
 >>> format(v3)
 '(3.0, 4.0, 5.0)'
 >>> format(Vector(range(7)))
 '(0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0)'


Tests of ``format()`` with spherical coordinates in 2D, 3D and 4D::

 >>> format(Vector([1, 1]), 'h') # doctest:+ELLIPSIS
 '<1.414213..., 0.785398...>'
 >>> format(Vector([1, 1]), '.3eh')
 '<1.414e+00, 7.854e-01>'
 >>> format(Vector([1, 1]), '0.5fh')
 '<1.41421, 0.78540>'
 >>> format(Vector([1, 1, 1]), 'h') # doctest:+ELLIPSIS
 '<1.73205..., 0.95531..., 0.78539...>'
 >>> format(Vector([2, 2, 2]), '.3eh')
 '<3.464e+00, 9.553e-01, 7.854e-01>'
 >>> format(Vector([0, 0, 0]), '0.5fh')
 '<0.00000, 0.00000, 0.00000>'
 >>> format(Vector([-1, -1, -1, -1]), 'h') # doctest:+ELLIPSIS
 '<2.0, 2.09439..., 2.18627..., 3.92699...>'
 >>> format(Vector([2, 2, 2, 2]), '.3eh')
 '<4.000e+00, 1.047e+00, 9.553e-01, 7.854e-01>'
 >>> format(Vector([0, 1, 0, 0]), '0.5fh')
 '<1.00000, 1.57080, 0.00000, 0.00000>'
"""

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學習或者工作能帶來一定的幫助,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。

相關(guān)文章

  • Python 基于jwt實現(xiàn)認證機制流程解析

    Python 基于jwt實現(xiàn)認證機制流程解析

    這篇文章主要介紹了python 基于jwt實現(xiàn)認證機制流程解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-06-06
  • 在TensorFlow中實現(xiàn)矩陣維度擴展

    在TensorFlow中實現(xiàn)矩陣維度擴展

    這篇文章主要介紹了在TensorFlow中實現(xiàn)矩陣維度擴展方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-05-05
  • 淺析Python的web.py框架中url的設(shè)定方法

    淺析Python的web.py框架中url的設(shè)定方法

    web.py是Python的一個輕量級Web開發(fā)框架,這里我們來淺析Python的web.py框架中url的設(shè)定方法,需要的朋友可以參考下
    2016-07-07
  • Python 2.x如何設(shè)置命令執(zhí)行的超時時間實例

    Python 2.x如何設(shè)置命令執(zhí)行的超時時間實例

    這篇文章主要給大家介紹了關(guān)于Python 2.x如何設(shè)置命令執(zhí)行超時時間的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-10-10
  • Python中常見的數(shù)據(jù)類型小結(jié)

    Python中常見的數(shù)據(jù)類型小結(jié)

    這篇文章主要對Python中常見的數(shù)據(jù)類型進行了總結(jié)歸納,很有參考借鑒價值,需要的朋友可以參考下
    2015-08-08
  • python數(shù)據(jù)處理之如何選取csv文件中某幾行的數(shù)據(jù)

    python數(shù)據(jù)處理之如何選取csv文件中某幾行的數(shù)據(jù)

    這篇文章主要給大家介紹了關(guān)于python數(shù)據(jù)處理之如何選取csv文件中某幾行的數(shù)據(jù)的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家學習或者使用python具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2019-09-09
  • python3.7 sys模塊的具體使用

    python3.7 sys模塊的具體使用

    這篇文章主要介紹了python3.7 sys模塊的具體使用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-07-07
  • python中map()與zip()操作方法

    python中map()與zip()操作方法

    這篇文章主要介紹了python中map()與zip()操作方法,需要的朋友可以參考下
    2016-02-02
  • Windows自動執(zhí)行python腳本操作步驟

    Windows自動執(zhí)行python腳本操作步驟

    我們想在Windows中運行一個Python腳本,我們可以通過CMD,首先進入python文件所在的目錄,之后運行。但是這樣很麻煩,跟著本文操作就可以解決啦
    2021-09-09
  • Python模型聚合查詢\Q查詢\F查詢\分組查詢操作技巧解析

    Python模型聚合查詢\Q查詢\F查詢\分組查詢操作技巧解析

    這篇文章主要介紹了模型查詢中的一些操作技巧,主要包括模型聚合查詢,Q查詢,F(xiàn)查詢,分組查詢,有需要的朋友可以借鑒參考下,希望可以有所幫助
    2021-09-09

最新評論