1. 类html
1.1 python使用关键字 class 来建立类。class后跟类名,类名子后的括号中是继承的父类。若无父类,则从 object 基类中继承。python
class ClassName(bases): # 继承自"bases" 'class documentation string' # class的文档字符串 pass class ClassName2(object): # 无父类,则从object基类继承 pass
2 类属性安全
2.1 静态变量/静态数据 app
静态变量是与类绑定的,不依赖于实例,一般仅用来跟踪与类相关的值。dom
>>> class C(object): ... C.foo = 100 ... >>> print C.foo 100 >>> C.foo += 1 >>> print C.foo 101
2.2 Methods函数
方法是做为类定义中的一部分的函数,仅能经过实例来调用。像调用函数那样直接调用方法名字、或者由类对象调用都会异常ui
2.3 类的属性code
要知道一个类有哪些属性,两种方法:①使用 dir() 内建函数 ②经过访问类的字典属性"__dict__",这是全部类都具有的特殊属性。orm
首先定义一个类:htm
# -*- coding: utf-8 -*- class MyClass(object): 'MyClass class definition' myVersion = '1.1' def showMyVersion(self): print MyClass.myVersion
对该类调用内建函数 dir() 和字典属性"__dict__"结果以下:
从上面能够看出,dir()返回对象属性的列表,__dict__返回一个对象属性为key、相应的属性对象的数据值为value的字典。内建的vars()函数则接受类对象,返回内容和__dict__相同。
2.4 类的特殊属性
对一个类C,下图显示了它所具备的全部特殊属性
对以前定义的MyClass,其相应的返回对象以下:
__name__ 适合只须要类名字的字符串表示,而不是类对象自己的状况,一些内建类型也有这个属性:
__doc__ 是类的文档字符串,相似函数/模块,是紧跟第一行下面的字符串,且不能被子类继承。
__bases__ 包含一个由全部父类组成的元组
__module__ 用来定位类的位置,当类没有使用全名时尤其重要:
>>> class C(object): ... pass ... >>> C <class '__main__.C'> >>> C.__module__ 'main' >>> from mymod import C >>> C <class 'mymod.C'> >>> C.__module__ 'mymod'
3. 实例
类被实例化获得实例,实例的类型就是被实例化的类。
3.1 __init__() 和 __new__()
二者之间区别与联系参见 http://www.cnblogs.com/ifantastic/p/3175735.html
3.2 __del__() 解构器方法
Python的 __del__() 是在实例的引用计数为0即被释放前提供特殊处理的方法,一般不被实现,由于不多会显式的释放实例。
下面是一个运用了 __init__() 和 __del__() 的例子
>>> class C(P): ... def __init__(self): ... print "initialized" ... def __del__(self): ... P.__del__(self) ... print 'deleted' ... >>> c1 = C() initialized >>> c2 = c1 >>> c3 = c1 >>> id(c1), id(c2), id(c3) (11938912, 11938912, 11938912) >>> del c1 >>> del c2 >>> del c3 deleted
关于 __del__() 的一些注意事项:
3.3 运用 __init__() 和 __del__() 记录实例建立次数的案例
4. 实例的属性
实例仅拥有数据属性,它是与某个类的实例相关的值,经过句点来访问,且独立于其余实例或类。
4.1 实例化实例属性
设置实例属性能够在实例建立后,也能够在初始化时 __init__中建立。下面是使用默认参数进行实例化的一个例子
class HotelRoomCalc(object): 'Hotel room rate calculator' def __init__(self, rt, sales=0.085, rm=0.1): '''HotelRoomCalc default arguments: sales tax == 8.5% and room tax == 10%''' self.salesTax = sales self.roomTax = rm self.roomRate = rt def calcTotal(self, days=1): 'Calculate total; default to daily rate' daily = round((self.roomRate * (1 + self.salesTax + self.roomTax)), 2) return float(days) * daily
其用法以下:
4.2 查看实例属性
内建函数dir()也能够查看实例属性;实例也有一个__dict__特殊属性,返回实例的属性构成的一个字典,能够用 vars() 传入实例来获取。
4.3 实例属性和类属性
4.3.1.访问类属性
类属性能够经过类或实例来访问,前提是没有在实例中重定义相同名字的属性。另外,对于不可变的属性对象,只有类引用类的属性时,才能更新其值;若尝试在实例中更新,则会建立一个同名的实例属性;对于可变对象,在实例中更新属性会影响类中定义的属性,因此需谨慎操做。例子以下:
4.3.2. 类属性持久性
类属性的修改会影响全部实例,当实例在类修改后才建立,那么更新的值将生效
5.静态方法和类方法
静态方法仅是类中的函数,不须要实例便可调用,经过内建函数 "staticmethod()"来实现。类方法须要类而不是实例做为第一个参数,由解释器传入,类不须要特殊命名,但一般用"cls"做为变量名,经过内建函数 "classmethod()"实现。下面是一个例子:
class TestStaticMethod: @staticmethod def foo(): print "Calling static method foo()" class TestClassMethod: @classmethod def foo(cls): print "Calling class method foo()" print "foo() is part of class:", cls.__name__
输出:
6. 继承
子类能够继承其基类/父类的全部属性和方法。文档字符串除外,它不会被继承
6.1 __bases__
下面的例子能够说明 __bases__属性与继承的关联:
该例中,C是B的子类,同时经过B间接是A的子类,但声明中C的父类是B,因此其__bases__属性显示B;而D则是声明中就多重继承自A、B,因此其__bases__属性中显示A、B
6.2 多重继承
经典类的方法解释顺序是从左到右,深度优先;新式类则是广度优先,而不是深度优先。
7.类、实例和其余对象的内建函数
7.1 issubclass()
issubclass(),布尔函数,判断一个类是不是另外一个类的子类或子孙类,语法是 issubclass(sub, sup)。当给定的类sub是sup(sup能够是一个可能的父类组成的元组)的子类时,返回True,不然返回False。其判断是不严格的,一个类是能够视为自身的子类的。
7.2 isinstance()判断一个对象是不是另外一个给定类的实例。给定类也能够是一个可能的类型组成的元组
7.3 *attr()
*attr() 系列函数能够做用于多种对象,不局限于类。hasattr()是布尔函数,用来检查一个对象是否有一个特定的属性。getattr()取得相应对象的属性,当属性不存在且未给出可选的默认参数时,会抛出AttributError;setattr()则要么加入一个新属性,要么取代一个已存在的属性;delattr()会从一个对象中删除属性
下面是使用这一系列内建函数的例子
7.4 类和类实例的内建函数包括如下各类:
8. 特殊方法定制类
python提供了一些特殊方法用于扩充类,容许类经过重载标准操做符+、*甚至是下标或映射操做[]实现模拟标注类型。下表是全部特殊方法及描述:
8.1 基本定制
用RoundFloat例子来演示__str__和__repr__的用法。先看没有定义特殊方法时的输出:
用了断言之后,rfm输入的数据不是浮点型时会被抛出异常;rfm实例输入时浮点型时,获得的却不是想要的,即便用print 也不行。添加__str__方法后输出以下:
在定义了__str__()之后,print语句能够打印出想要的信息,可是命令后解释器中直接输入对象时显示的信息仍有问题,这能够经过覆盖__repr__()方法来解决。最后修改后的源代码以下:
#!/usr/bin/env python class RoundFloatManual(object): def __init__(self, val): assert isinstance(val, float), \ "Value must be a float" self.value = round(val, 2) def __str__(self): return "%.2f" % self.value __repr__ = __str__
输出以下:
8.2 数值定制
经过实现加法和增量加法,来理解稍微复杂的特殊定制类。
注意点:①__str__()和__repr__()定制更有意义的输出
②+重载__add__,+=重载__iadd__,obj+self用__radd__重载
③计算出个别的总数之后,调用类构造器返回一个新的对象。此时不直接经过调用类名来构造类,而是用"self.__class__"属性调用,能够避免一些问题。
④当试图重载一个没有定义的操做符时,会抛出TypeError。
⑤在增量赋值时,区别在于__i*__方法必须返回self。
源代码:
#!/usr/bin/env python class Time60(object): 'Time60 - track hours and minutes' def __init__(self, hr, min): 'Time60 constructor - takes hours and minutes' self.hr = hr self.min = min def __str__(self): return "%s:%s" % (self.hr, self.min) __repr__ = __str__ def __add__(self, other): return self.__class__(self.hr + other.hr, self.min + other.min) def __iadd__(self, other): self.hr += other.hr self.min += other.min return self
输出:
8.3 迭代器
8.3.1 RandSeq
本节介绍了两个迭代器,第一个是RandSeq,给类传入一个初始序列,而后能够经过next()无穷迭代,这也是惟一的亮点。
注意点:①__iter__()方法仅返回self,这是将对象声明为迭代器的方式
②与以前同样,调用next()来迭代,获得连续的值
源代码:
#!/usr/bin/env python from random import choice class RandSeq(object): def __init__(self, seq): self.data = seq def __iter__(self): return self def next(self): return choice(self.data)
输出: # 没法结束的循环。。
8.3.2 AnyIter
第二个例子中建立了一个迭代器,并经过给next()传递一个参数,控制返回条目的数目。同时定义一个安全标识符对过程作出一些控制。
源代码:
#!/usr/bin/env python class AnyIter(object): def __init__(self, data, safe = False): self.safe = safe self.iter = iter(data) def __iter__(self): return self def next(self, howmany=1): retval = [] for eachitem in range(howmany): try: retval.append(self.iter.next()) except StopIteration: if self.safe: break else: raise return retval
输出:
8.4 多类型定制
建立由数字-字符对组成的的类,数字和字符记为n和s,数值类型使用整型,用[n::s]来表示。类NumStr具备几个特征:①类要对数字和字符串进行初始化,默认n=0、s=''②加法操做符把数字加起来,字符按顺序链接③乘法操做符数字相乘、字符累积④当数字为0且字符为空时,类实例布尔值为False⑤实现cmp()比较并返回适当的值
源代码:
#!/usr/bin/env python class NumStr(object): def __init__(self, num=0, string=''): self.__num = num self.__string = string def __str__(self): return '[%d::%r]' % (self.__num, self.__string) __repr__ = __str__ def __add__(self, other): if isinstance(other, self.__class__): return self.__class__(self.__num + \ other.__num,\ self.__string + other.__string) else: raise TypeError, \ 'Illegal argument type for built-in operation' def __mul__(self, num): if isinstance(num, int): return self.__class__(self.__num * num,\ self.__string * num) else: raise TypeError, \ "Illegal argument type for bulit-in operation" def __nonzero__(self): return self.__num or len(self.__string) def __norm_cval(self, comres): return cmp(comres, 0) def __cmp__(self, other): return self.__norm_cval( cmp(self.__num, other.__num)) + \ self.__norm_cval( cmp(self.__string, other.__string))
输出示例:
注意点:①双下划线开始的属性属于内部私有变量,不要从外部直接访问。
②%r和%s的区别
③__nonzzero__ 覆盖此方法定义类的布尔值