【Python】【数据类型】
【序列更新&散列&切片】
"""
from array import array
import reprlib
array1 = array('d',(1,2,3))
print(array1) #array('d', [1.0, 2.0, 3.0])
com = reprlib.repr(array1)
components = com[com.find('['):-1]
print('Vector({})'.format(components)) #Vector([1.0, 2.0, 3.0])
"""
#10.2 Vector类第一版,与Vector2d类兼容
#例子10-2
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) # 把Vector分量保存在一个数组里 def __iter__(self):
return iter(self._components) #构造一个迭代器 def __repr__(self):
components = reprlib.repr(self._components) #使用reprlib.repr()获取self._components的有限长度表示形式(如array('d',[0.0,1.0,2.0,3.0,4.0,...]))
components = components[components.find('['):-1] #把字符串插入Vector的构造方法调用之前,去掉前面的array('d' 和后面的)
return 'Vector({})'.format(components)
'''
def __str__(self):
return str(tuple(self))
'''
__str__ = __repr__ def __bytes__(self):
return (bytes([ord(self.typecode)]) + bytes(self._components)) #直接用self._components构建bytes对象
def __eq__(self, other):
return tuple(self) == tuple(other)
def __abs__(self):
return math.sqrt(sum(x*x for x in self)) #不能直接用hypot方法了,因此我们先计算各分量的平方之和,然后再使用sqrt方法开平方
def __bool__(self):
return bool(abs(self))
@classmethod
def frombytes(cls,octets):
typecode = chr(octets[0])
memv = memoryview(octets[1:]).cast(typecode)
return cls(memv) #构造方法变了,所以不用像前面那样使用*拆包
def __len__(self): #以下两个方法实现切片的序列
return len(self._components)
def __getitem__(self, item):
cls = type(self) #获取实例的类,供后面使用
if isinstance(item,slice):
return cls(self._components[item])
elif isinstance(item,numbers.Integral):
return self._components[item]
else:
msg = '{cls.__name__} indices must be integers'
raise TypeError(msg.format(cls=cls))
def __eq__(self, other):
return len(self) == len(other) and all(a==b for a,b in zip(self,other)) #all函数,只要一次比较结果为False,则结果为False.所有结果为True,结果为True
#考虑到,按照老规则的话,Vector([1,2]) 和(1,2)的比较结果是一样的,所以出来了这个新规则
def __hash__(self):
hashes = map(hash,self._components)
return functools.reduce(operator.xor,hashes)
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())
a = list(self.angles())
outer_fmt = '<{}>'
else:
coords = self
outer_fmt = '({})'
components = (format(c,fmt_spec) for c in coords)
return outer_fmt.format(','.join(components)) #通过@property来动态获取属性,想要获取向量的四个分量时,要写四个这样的特性,太麻烦,所以选择__getattr__这个特殊方法。
#属性查找失败后,解释器会调用__getattr__方法。简单来说,对my_obj.x表达式,python会检查my_obj实例有没有名为x的属性;如果没有,到类(my_obj.__class__)中查找;如果还没有,顺着继承树继续查找。如果依旧找不到,调用my_objh所属类中
#...定义的__getattr__方法,传入self和属性名称的字符串形式。
#例子10-8
shortcut_names = 'xyzt'
def __getattr__(self, item):
cls = type(self)
if len(item) == 1:
pos = cls.shortcut_names.find(item)
if 0<= pos < len(self._components):
return self._components[pos]
msg = '{.__name__!r} object has no attribute {!r}'
raise AttributeError(msg.format(cls,item)) #【备注】1⃣️使用reprlib.repr的方式需要做些说明。这个函数用于生成大型数据结构或递归结构的安全表现形式,它会限制输出字符串的长度,用'...'表示截断的部分。我希望Vector实例的表现形式是Vector([3.0,4.0])这样,而不是
#Vector(array('d',[3.0,4.0])),因为我们不需要实例中的实现细节。
#【备注】2⃣️编写__repr__方法时,本可以使用这个表达式生成简化的componets显示形式:reprlib.repr(list(self._components))。然而,这么做优点浪费,因为要把self._components中每个元素复制带一个列表中,
#然后使用列表的表示形式。
#【备注】3⃣️调用repr()目的是调试
#【备注】4⃣️我们本可以让Vector继承Vector2d,没这么做的原因幼儿。其一,两个构造方法不兼容,因此不建议继承。这一点可以通过适当处理__init__方法的参数解决,不过第二个原因更重要:我想把Vector类当作单独的事例,以此实现序列协议 #10.3 协议和鸭子类型 '''
#例子10-3 可切片的序列
v7 = Vector(range(7))
print(v7[-1]) #6.0
print(v7[1:4]) #Vector([1.0, 2.0, 3.0])
print(v7[-1:]) #Vector([6.0])
print(v7[1,2]) #TypeError: Vector indices must be integers Vector不支持多维索引 #例子10-4 了解__getitem__和切片的行为
class MySeq:
def __getitem__(self, item):
return item
s = MySeq()
print(s[1]) #1
print(s[1:4]) #slice(1, 4, None)
print(s[1:4:2]) #slice(1, 4, 2)
print(s[1:4:2,9]) #(slice(1, 4, 2), 9)
print(s[1:4:2,7:9]) #(slice(1, 4, 2), slice(7, 9, None))
#例子10-5 查看slice属性
print(slice) #<class 'slice'>
print(dir(slice))
print(slice(None,10,2).indices(5)) #(0, 5, 2)
print('ABCDE'[:10:2]) #ACE 根据上方的原理,等同于 'ABCDE'[0:5:2]
print(slice(-3,None,None).indices(5)) #(2, 5, 1)
print('ABCDE'[-3:]) #CDE 等同于'ABCDE'[2:5:1] #例子10-15 zip内置函数的使用
print(zip(range(3),'ABC')) #<zip object at 0x102832788>
print(list(zip(range(3),'ABC'))) #[(0, 'A'), (1, 'B'), (2, 'C')]
print(list(zip(range(3),'ABC',[0.0,1.1,2.2,3.3]))) #[(0, 'A', 0.0), (1, 'B', 1.1), (2, 'C', 2.2)] zip有个奇怪的特性,当一个可迭代对象耗尽后,它不发出警告就停止
from itertools import zip_longest
print(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)] print(','.join(format(c,'.3e') for c in (3.45678,0.555555))) #3.457e+00,5.556e-01
print('{:.3e},{:.3e}'.format(3.4567855,0.555555)) #3.457e+00,5.556e-01
import itertools
print(itertools.chain('123','456')) #<itertools.chain object at 0x10c554c18>
print(list(itertools.chain('123', '456'))) # ['1', '2', '3', '4', '5', '6']
print(list(itertools.chain([3.4444],(3.4444444,)))) #[3.4444, 3.4444444]
#tests of 'format()' with spherical coordinates in 2d,3d and 4d:
v3 = Vector([1,1])
print(format(v3,'h')) #<1.4142135623730951,0.7853981633974483>
print(format(v3,'.3eh')) #<1.414e+00,7.854e-01>
print(format(v3,'0.5fh')) #<1.41421,0.78540>
v4 = Vector([1,1,1])
print(format(v4,'h')) #<1.7320508075688772,0.9553166181245093,0.7853981633974483>
v5 = Vector([-1,-1,-1,-1])
print(format(v5,'.3eh')) #<2.000e+00,2.094e+00,2.186e+00,3.927e+00>
#tests of 'format()' with cartesian coordinates in 2d:
v5 = Vector([3,4])
print(format(v5)) #(3.0,4.0)
print(format(v5,'.2f')) #(3.00,4.00)
print(format(v5,'.3e')) #(3.000e+00,4.000e+00)
#tests of 'format()' with cartesian coordinates in 3d and 7d:
v6 = Vector([3,4,5])
print(format(v6))
v7 = Vector(range(7)) #(3.0,4.0,5.0)
print(format(v7)) #(0.0,1.0,2.0,3.0,4.0,5.0,6.0)
#tests of hashing
v9 = Vector([3,4])
v10 = Vector(range(6)) #7 1
print(hash(v9),hash(v10))
#Most hash values on ono-integers vary from a 32-bit to 64-bit CPython build::
import sys
v8 = Vector([3.1,4.2])
print(hash(v8)) #384307168202284039
print(hash(v8) == (384307168202284039 if sys.maxsize > 2**32 else 357915986)) #True
#tests of '.__bytes__ ' and 'frombytes()' methods:
v11 = Vector([3,4,5])
v11_clone = Vector.frombytes(bytes(v11))
print(v11_clone) #Vector([3.0, 4.0, 5.0])
print(v11 == v11_clone) #True # 例子10-9 针对例子10-8的验证,不恰当的行为:为v.x赋值没有报错,但是前后矛盾
v12 = Vector(range(5))
print(v12) #Vector([0.0, 1.0, 2.0, 3.0, 4.0])
print(v12.x) #0.0
v12.x = 10
print(v12.x) #10
print(v12) #为向量赋新值后,向量依然没变。Vector([0.0, 1.0, 2.0, 3.0, 4.0])
#【分析】如果向量的分量数组中没有新值,为什么v12.x返回10?例子10-9之所以前后矛盾,是__getattr__的运作方式导致的:仅当对象没有指定名称的属性时,python才会调用那个方法,这是一种后备机制。可是,像v12.x=10这样赋值
#...赋值后,v12对象就有x属性了,因此使用v12.xhuoqu x属性的值时不会调用__getattr__方法了,解释器直接返回绑定到v12.x上的值,即10。为避免这种前后矛盾的现象,我们要改写Vector中设置属性的逻辑。
#例子10-10 实现__setter__方法:虽然这个例子不支持为Vector分量赋值,但是有一个问题要特别注意:多数时候,如果实现了—__getattr__方法,那么也要实现__setattr__ 方法,以防对象的行为不一致。
#如果像允许修改分量,针对Vector可以使用__setitem__,支持v[0]=1.1,或者实现__setattr__,支持v.x=1.1。不过,我们要保持Vector是不可变的,因为接下去的实验我们要把它变成可散列的。
#这里格外讲一下__setattr__
class Test:
shortcut_names = 'xyzt'
def __setattr__(self, key, value):
cls = type(self)
if len(key) == 1:
if key in cls.shortcut_names:
error = 'readonly attribute {attr_name!r}'
elif key.islower():
error = "cannot set attribute 'a' to 'z' in {cls_name!r}"
else:
error = ''
if error:
msg = error.format(cls_name=cls,attr_name=key)
raise AttributeError(msg)
super().__setattr__(key,value)
v11 = Test()
#v11.x = 2 #AttributeError: readonly attribute 'x'
#v11.a = 3 #AttributeError: cannot set attribute 'a' to 'z' in <class '__main__.Test'>
v11.B = 3
print(v11.B) #3
#【分析】
#1⃣️ 为了给AttributeError选择错误信息,我查看了内置的complex类型的行为,因为complex对象是不可变的,而且有一堆数据属性:real imag。如果试图修改任何一个属性,complex实例会抛出AttributeError,而且把错误
#消息设置为"cannot set attribute'。而如果尝试为受保护的只读属性赋值,得到的错误消息是'readonly attribute'。在__setattr__方法中为error字符串选词时,我参考了这两个错误消息
#注意,我们没有禁止为全部属性赋值,只是禁止为单个小写字母属性赋值,以防与只读属性x y z t 混淆
#2⃣️ 我们知道,在类型声明__slots__属性可以防止设置新实例属性;因此,你可能想使用这个功能,而不像这里所做的,实现__setattr__方法。可是,不将以只为了避免创建实例属性而使用它。__slots__属性只应该用于节省内存,而且仅当内存严重不足时才使用
'''
【list&tuple&dict】
# 栗子 list排序
ls = ['d.txt','a.xlxs','a.xlas','b.txt']
print(ls) #['d.txt', 'a.xlxs', 'a.xlas', 'b.txt'] ls.sort(key=lambda x:x[0])
print(ls) #['a.xlxs', 'a.xlas', 'b.txt', 'd.txt'] ls.sort(key=lambda x:x[4])
print(ls) #['a.xlas', 'b.txt', 'd.txt', 'a.xlxs'] students = [('john','A',15),('jane','B',12),('dave','B',10)]
print(sorted(students,key=lambda s:s[2])) #[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
【Python】【数据类型】的更多相关文章
- python 数据类型---布尔型& 字符串
python数据类型-----布尔型 真或假=>1或0 >>> 1==True True >>> 0==False True python 数据类型----- ...
- Python 数据类型及其用法
本文总结一下Python中用到的各种数据类型,以及如何使用可以使得我们的代码变得简洁. 基本结构 我们首先要看的是几乎任何语言都具有的数据类型,包括字符串.整型.浮点型以及布尔类型.这些基本数据类型组 ...
- day01-day04总结- Python 数据类型及其用法
Python 数据类型及其用法: 本文总结一下Python中用到的各种数据类型,以及如何使用可以使得我们的代码变得简洁. 基本结构 我们首先要看的是几乎任何语言都具有的数据类型,包括字符串.整型.浮点 ...
- Python数据类型及其方法详解
Python数据类型及其方法详解 我们在学习编程语言的时候,都会遇到数据类型,这种看着很基础也不显眼的东西,却是很重要,本文介绍了python的数据类型,并就每种数据类型的方法作出了详细的描述,可供知 ...
- Python学习笔记(五)--Python数据类型-数字及字符串
Python数据类型:123和'123'一样吗?>>> 123=='123'False>>> type(123)<type 'int'>>> ...
- python数据类型之元组、字典、集合
python数据类型元组.字典.集合 元组 python的元组与列表类似,不同的是元组是不可变的数据类型.元组使用小括号,列表使用方括号.当元组里只有一个元素是必须要加逗号: >>> ...
- 1 Python数据类型--
常见的Python数据类型: (1)数值类型:就是平时处理的数字(整数.浮点数) (2)序列类型:有一系列的对象并排或者排列的情况.如字符串(str),列表(list),元组(tuple)等 (3)集 ...
- Python数据类型和数据操作
python数据类型有:int,float,string,boolean类型.其中string类型是不可变变量,用string定义的变量称为不可变变量,该变量的值不能修改. 下面介绍python中的l ...
- Python数据类型(python3)
Python数据类型(python3) 基础数据类型 整型 <class 'int'> 带符号的,根据机器字长32位和64位表示的范围不相同,分别是: -2^31 - 2^31-1 和 - ...
- 二、Python数据类型(一)
一.Python的基本输入与输出语句 (一)输出语句 print() 示例: print('你好,Python') print(4+5) a = 10 print(a) 输出的内容可以是字符串,变量, ...
随机推荐
- SpringBoot打成的jar包发布,shell关闭之后一直在服务器运行
1:可以编写shell脚本, 切换到执行的jar包目录,然后使用nohup 让改命令在服务器一直运行 #!/bin/bash cd /srv/ftp/public nohup java -jar l ...
- [vue]vue v-on事件绑定(原生修饰符+vue自带事件修饰符)
preventDefault阻止默认行为和stopPropagation终止传递 event.preventDefault() 链接本来点了可以跳转, 如果注册preventDefault事件,则点了 ...
- .Net Core 使用依赖注入
ASP.NET Core 源码阅读笔记(1) ---Microsoft.Extensions.DependencyInjection 在asp .net中使用依赖注入很简单,只需要在Startup类的 ...
- http://ttaa.210997.com/恶意修改主页
嗯,,,,之前似乎写过关于篡改主页的文章. 但今天下了个游戏,然后不小心又出现了这个问题. 我先用原始的方式检测了一下(比如检索注册表之类的),但这个不奏效. 省略一些查看问题的方式. 最终得出:新的 ...
- QQ 客服设置
不说那么多了. 目前可以通过此方式实现添加的效果 <a target="_blank" href="http://wpa.qq.com/msgrd?v=3& ...
- 【笔记】DataTable或IList使用GroupBy方法的lamda表达式
DataTable GroupBy的用法 var result = dt.AsEnumerable(). GroupBy(g => new { StaffID = g.Field<stri ...
- JavaScript: apply 方法 详解(转)——非常好
转载自 http://www.cnblogs.com/KeenLeung/archive/2012/11/19/2778229.html 我在一开始看到javascript的函数apply和call ...
- python webdriver 从无到有搭建混合驱动自动化测试框架的过程和总结
一步一步实现混合驱动自动化测试框架的搭建 混合驱动自动化测试框架,是一个非常高级的框架,非常好用,但也很难,不好掌握,需要多练习,就像搭建数据驱动框架一样,需要自己去一点一点的写,一边搭建一边做思路整 ...
- python-自定义异常,with用法
抛出异常 #coding=utf-8 def exceptionTest(num): if num<0: print "if num<0" raise Excepti ...
- Kotlin新语言简介和快速入门知识点
Kotlin新语言简介和快速入门知识点 简介:Kotlin是最近由JetBrains发布的一种基于JVM的编程语言,已经被Google宣布为开发Android App的一级语言Kotlin有着与Jav ...