1 Python中的类型与对象
来源:互联网 发布:第三方网络销售平台 编辑:程序博客网 时间:2024/06/05 07:17
类型与对象
转载请标明出处(http://blog.csdn.net/lis_12/article/details/52693637)
1 术语
程序中所有数据都是对象(实例),每个对象都有一个身份,一个类型和一个值.如a = 10,使用值10创建一个整数对象,对象的身份可以看做它在内存中所处位置的指针(id(a)获取),a就是引用这个位置的名称.
实例的类型决定了实例内部的表示以及它支持的方法.
实例被创建后,它的身份和类型就不可改变,如果对象的值是可以修改的称为可变对象(list,dict);如果对象的值不可修改称为不可变对象(int,str,tuple).
2 身份与类型
a = 10,b = 10
身份的获取,id(a);
类型的获取,type(a)
is用来比较地址是否相同,即两个对象身份是否相同,==用来比较两个对象的值是否相同;
type(a) is type(b) # true
对象的类型本身也是一个对象,称为对象的类,该对象的定义是唯一的,对于某个类型的所有实例都是相同的.
检查某个实例的类型最佳方式是用,isinstance(object,(int,str,list…..))
3 引用计数与垃圾收集
所有对象都有引用计数,无论是给一个对象分配一个新名称,还是放入容器当中,都会让该对象的引用计数增加.
a = 10 #创建一个值为10的对象b = a #增加10的引用计数c = [] c.append[a] #增加10的引用计数#上面只有一个包含10的对象,其他操作都只是创建了该对象的引用.del a #减少10的引用计数,此时a也就无法访问了b = 10 #减少10的引用计数c[0] = 5 #减少10的引用计数'''使用del或者重新赋值时,对象的引用计数会减少'''print sys.getrefcount(b) #查看b的引用次数,一般情况下会比预想情况多- -a = {}b = {}a['a'] = bb['b'] = adel adel b'''虽然del语句销毁了a与b,但是他们相互引用,所以引用计数不会归零,对象也不会销毁(从而导致内存泄漏),为了解决这个问题,解释器会有一个循环检测器,搜索不可访问对象并删除.'''
4 引用和复制
a = 1b = 1print id(a) #0print id(b) #0#a与b的地址相同,因为1是不可变对象,不可改变,a和b都是对1的引用.a = range(10)b = range(10)print id(a) #0print id(b) #1#a与b的地址不同,因为list是可变对象,可变对象是可修改的for i,j in zip(a,b): print id(i) == id(j)#result:10个True,因为list里面的对象都是不可变对象,a和b里面的元素分别引用了0,1,...,8,9
#可变对象a = range(4)b = ab[1] = 100print a #[0,100,2,4]#不可变对象c = 1d = cd = 2print c #1
a,b引用的是同一个对象,修改其中任何一个都会影响另一个,为了避免这种情况,必须创建对象的副本而不是新的引用.
可变对象的复制分为浅,深复制.
- 浅复制将创建一个新对象,但它包含的是对原始对象中包含的项的引用.
a = [0,[1,2]]b = a #此时b就相当于a的别名c = list(a)#创建a的一个浅复制a is b #Truea is c #Falseb.append(2)c.append(3)print a #[0, [1, 2], 2]print b #[0, [1, 2], 2]print c #[0, [1, 2], 3]c[1][0] = 10print a #[0, [10, 2], 2]print b #[0, [10, 2], 2]print c #[0, [10, 2], 3]a[1][0]=20 #可变对象print a #[0, [20, 2], 2]print b #[0, [20, 2], 2]print c #[0, [20, 2], 3]a[0] = 3 #不可变对象print a #[3, [20, 2], 2]print b #[3, [20, 2], 2]print c #[0, [20, 2], 2]
a和c是单独的列表对象,但是他们包含的公共元素是共享的,修改a的元素就会修改c(可变类型才会变哦,如果是不可变类型会新建对象的).
- 深复制将创建一个新对象,并且递归地复制它包含的所有对象.可以使用copy.deepcopy()完成该工作.
import copya = [0,[1,2]]b = copy.deepcopy(a)b.append(2)print a #[0, [1, 2]]print b #[0, [1, 2], 2]b[1][0] = 10print a #[0, [1, 2]]print b #[0, [10, 2], 2]b[0] = 3print a #[0, [1, 2]]print b #[3, [10, 2], 2]
5 数据类型
5.1 None
None类型表示一个null对象,如果一个函数没有显式地返回值,则返回None,如果None在布尔表达式求值时为False。
5.2 序列
序列表示索引为非负值整数的有序对象集合(list,tuple,str).字符串是字符的序列,而列表和元组是任意Python对象的序列,字符串和元组是不可变的,而列表支持插入,删除,替换元素.索引序列都支持迭代.
1) 序列通用操作
- s[i]
- s[i:j] 切片,返回s[i]至s[j-1]的元素
- s[i:j:step],返回s[i],s[i+step],s[i+2*step],…..直至i + n * step >= j,如a = range(10) a[0:5:2] = [0,2,4],
如果i < j,step < 0,则返回[],(step不能为0)- len(s)
- min(s),max(s)
- sum(s)
- all(s),检查s中所有项是否为True
- any(s),检查s中任意项为True,有一个元素为真则返回True
- s[i] = value
- s[i:j] = t,切片赋值,
- s[i:j:step],扩展切片赋值
a = range(5)print a[0:5:2] #[0,2,4]print a[0:5:-1] #[]print a[4:0:-1] #[4,3,2,1]a = range(5)a[0:2] = [10]print a #[10,2,3,4]a[0:3] = range(10) #[1,2,3,4,5,6,7,8,9,4]a = range(5)a[0:5:2] = [10,20,30] #个数必须相同print a #[10, 1, 20, 3, 30]
2) 列表,特有的函数
内置函数list(s)可以将任意可迭代对象转换为列表,如果s已经是一个列表,则该函数构造的新列表是s的一个浅复制.
a = [0,5,3,6,9,4]f = lambda a:a%8a.sort(key = f)#[0, 9, 3, 4, 5, 6]
3) 字符串,特有的函数
通用操作虽然都是字符串实例,但是他们并不会修改原始的字符串数据(因为是不可变类型啊).
可利用help(str)查看所有方法
a = '123123' b = '1234123'c = ' 123123'd = '123444451\n222\n2'#测试lstrip([chars])print a.lstrip() #123123print c.lstrip() #123123,去掉了空格print a.lstrip('123') #空,去掉了123123print b.lstrip('123') #4123,去掉了123print c.lstrip('123') # 123123,啥都没去掉#测试partitionprint a.partition('23') #('1', '23', '123')print a.partition('3') #('12', '3', '123')#rsplitprint b.rsplit('3') #['12', '12', '']print b.rsplit('3') #['12', '412', '']#splitlinesprint d.splitlines() #['123444451', '222', '2']#formata = "{0}-{1}-{1}-{2}"a.format(4,5,6) #'4-5-5-6'
4) xrange()
xrange([i,]j[,step])创建的对象表示一个整数范围k,如果i<= k < j.
i,step是可选的默认值为0和1.
很像list,但是并不是list,不支持切片等操作
a = list(xrange(0,10,2)) #[0,2,4,6,8]print type(a) #<type 'xrange'>
5) 映射类型dict
dict,无序,任何不可变对象都可以用作字典键值,包含可变对象的列表,字典,元组不能作为键值,因为字典类型要求键值保持不变.
a = ([1,2],3) #a是元组不可变print id(a[0]) #48835016print id(a[0][0]) #31359704a[0][0] = 100print id(a[0]) #48835016 与上述一样print id(a[0][0]) #31361312,改变了哦print a '''([100,2],3),我擦改变了!因为tuple是不可变类型,a[0]未改变,符合tuple要求,但是list是可变类型啊,只要不改变a[0]的引用即可(a[0] = range(5)这样是不可以的哦),对list内部的操作是可以的(如a[0].append(3).这就是为什么键值不能为包含可变类型的不可变类型的对象'''a[0].append(3)print a #([100, 2, 3], 3)
dict内置方法
6) 集合
集合是唯一项的无序集,无切片操作,放入集合的项目必须是不可变的.
set,可变集合
frozenset,不可变集合
5.3 表示程序结构的内置类型
在Python中,函数,类,模块都可以当做数据操作的对象.
1) 可调用类型
用户自定义函数,具有如下属性
def f():
pass
2) 类,类型与实例
定义类的时候,通常会生成一个type类型的对象
class Foo(object): passtype(Foo) # <type 'type'>
下表表示一个类型对象Foo = t的常用属性
下面为实例 i = Foo()的特殊属性
__dict__属性通常用于存储与一个实例相关的所有数据.就像i.var = value,这样的值就会保存在dict里面.但是如果用户使用的类使用了__slots__,就会使用一种更加有效的内部表示,实例也不会有__dict__属性.
__slots__是一个类变量,由一序列型对象组成,由所有合法标识构成的实例属性来表示.任何试图创建其名不在__slots__中的名字的实例属性都将导致AttributeError异常.
3) 模块
模块类型就是一个容易,可保存使用import语句加载的对象.例如,import foo,就会把名称foo模块的属性赋给调用的模块.可用属性如下:
5.4 对象行为和特殊方法
Python中的对象通常根据它们的行为和实现的功能进行分类.例如,所有序列类型放在一组,如list,tuple,因为他们都支持一系列相同操作,如s[n],len(s)等.所有基本的解释器操作都通过特殊的对象方法来实现.
特殊的方法名称前后始终带有双下划线__.当程序执行时,这些方法都由解释器自动触发.如x + y被映射为内部方法 x.__add__(y),x[k]映射为x.__getitem__(k).
每种数据类型的行为完全取决于它实现的一组特殊方法.
《对象行为完全取决于特殊方法啊= =》
1) 对象的创建与销毁
调用A(args)创建对象时候,会进行以下步骤:
- x = A.__new__(A,args)
- is isinstance(x,A): x.__init__(args)
自定义的对象中,很少定义__new__()或者__del__()方法.
- new通常只定义在元类或继承不可变类型之一的用户自定义对象中.
- del方法只在有某种关键资源管理问题的情况才会定义,如释放锁定或关闭连接.
2) 对象的字符串表示
__repr__(),通常返回一个表达式字符串,可对该字符串重新求值以重新创建对象.
如果无法创建字符串表达式,repr()返回一个\<_message>形式的字符串
a = range(3) #[0,1,2]s = repr(a) #'[0,1,2]'b = eval(s) #[0,1,2]class a(object): passb = a()print a.__repr__() # errorprint b.__repr__() #'<__main__.a object at 0x0000000002EF7EF0>'
__str__()与__repr__()的区别是它返回的字符串更加简明易懂.如果该方法未定义就会调用__repr__()方法
__format__ , “{0}a{0}b{1}”.format(123,456,789) 等价于
“{0}a{0}b{1}”.__format__(123,456,789)
3) 对象比较与排序
对象测试与散列的特殊方法.
用于比较的方法见下表:
4) 类型检查
5) 属性访问
访问属性时始终会调用__getattribute__()方法,如果找到属性则返回之,否则调用__getattr__()方法来触发异常.设置属性会调用__setattr__()方法,删除属性时候则会调用__delattr__()方法.
6) 属性包装与描述符
描述符的__get__(),__set__()和__delete__()方法用于同类型的__getattribute__(),__setattr__(),__delattr__()方法进行交互.如果在用户自定义类的主体中放入一个描述符对象的实体,这种交互就会发生.
7) 序列与映射方法
如果对象要模拟序列和映射对象的行为,用下表的方法.
a = [0,1,2,3,4,5,6]len(a) #a.__len__()a[2] #a.__getitem__(2)a[0:4] #a.__getitem__(slice(0,4,None)),slice对象描述切片范围的属性a[1] = 7 #a.__setitem__(1,7)del a[1] #a.__delitem__(1)5 in a #a.__contains__(5)
8) 迭代器
如果对象obj支持迭代,它必须提供方法obj.__iter__(),该方法返回一个迭代器对象.迭代器对象iter必须返回一个方法iter.next(),该方法返回下一个对象,迭代结束引发异常.
class A(object): def __init__(self): self.num = 10 def __iter__(self): return self def next(self): if self.num > 0: self.num -= 1 return self.num else: raise StopIterationa = A()b = iter(a)print b.next() # 9for i in b: print i #8,7,6,5,4,3,2,1,0#for遇到StopIteration会停止循环
9) 可调用接口
对象可提供__call__(self[,*arg[,**kwargs])方法可模拟函数的行为.如果一个对象x提供了该方法,就可以像函数一样调用它.就是说x(arg1,arg2….)等同于调用了x.__call__(self,arg1,arg2…).模拟函数的对象可以用于创建仿函数或者代理.
10) 上下文管理协议
with operate as var:
statements
执行with语句时,就会调用__enter__()方法,该方法的返回值将被放入var中,离开with语句的时候回调用__exit__()方法.__exit__()方法接收当前异常的类型、值和跟踪作为参数.如果没有要处理的错误,所有三个值都将被置为None.
11) 对象检查dir
__dir__(self)获得对象可用函数名称列表.
- 1 Python中的类型与对象
- 深入源码解析Python中的对象与类型
- python中的对象与参考
- python中的类与对象
- Python对象类型判断与函数重载
- python对象类型(1)
- 有趣的python:关于python中的整数类型对象
- python中的可变与不可变类型
- js中的对象类型与具体的对象
- 配置squid代理python中的类型和对象yiya
- Python中的对象赋值与拷贝
- 初识python中的类与对象
- Python学习笔记1--运行Python&&python对象类型介绍
- python笔记1 对象类型小结
- Python判断对象类型
- Python类型和对象
- Python类型和对象
- python对象类型
- 235. Lowest Common Ancestor of a Binary Search Tree
- 深度学习(7) 人工神经网络
- http://www.open-open.com/lib/view/open1421995285109.html
- 关于热插拔usb hotplug /proc/sys/kernel mdev udev busybox
- SQL语句
- 1 Python中的类型与对象
- 优秀程序员的六个品质
- The more, The Better
- Socket 网络编程
- clock() / time() 函数
- java中几种获取项目路径方式
- Andriud Intent實現頁面的跳轉
- 预编译头(.pch)
- leetcode 135.Candy