----------------------
面向对象与类#程序 = 指令+数据 代码可以选择以指令为核心或以数据为核心进行编写#两种范型 以指令为核心:围绕“正在发生什么”进行编写 面向过程编程:程序具有一系列线型步骤:主题思想是代码作用于数据 以数据为核心:围绕"将影响谁"进行编写 面向对象编程:围绕数据及数据严格定义的接口来组织程序,用数据控制代码对代码的访问 所有编程语言最终目的都是提供一种抽象方法 &在机器模型(“解空间或方案空间”)与实际解决问题模型之间,程序员必须建立一种联系 面向过程:程序=算法 + 数据结构 面向对象:将问题空间中的元素以及他们在解空间中的表示物抽象为对象,允许通过问题来描述问题而不是方案 可以把对象(实例)想象成为一种新型变量,它保存着数据,但是可以对自身的数据执行操作------------------------------------------------------------面向对象核心概念:类型由形态集合(数据)和转换这些状态的操作集合组成 #类抽象 类:定义了被多个同一类型对象共享的结构和行为(数据和代码) 类的数据和代码:即类的成员 数据:成员变量或实例变量 成员方法:简称为方法,是操作数据的代码,用于定义如何使用成员变量;因此一个类的行为和接口是通过方法来定义的 方法和变量: 私有:颞部使用 公有:外部可见类定义了方法和数据结构--------------------------------------------面向对象程序设计方法:所有东西都是对象程序是一大堆对象的组合 通过消息传递,各对象知道自己该做什么 消息:即调用请求,它调用的是从属于目标对象的一个方法每个对象都有自己的存储空间,并可容纳其它对象 通过封装现有对象,可以制作新型对象每个对象都属于某一类型 类型,即类 对象是类的实例 类的一个重要特性为“能发什么样的消息给它”同一个类的所有对象都能接受相同的消息 ------------------------------------------------------对象的接口#定义一个类后,可以根据需要实例化出多个对象#每个对象仅能接受特定的要求 能向对象发送的请求由其“接口”进行定义 对象的“类型”或“类”则规定了它的接口形式 类与类之间的关系:1 依赖关系:一个类的方法操纵另一个类的对象 2 聚合:类A的对象包含类B的对象3 继承:描述特殊与一般关系 一个对象获得另外一个对象属性的过程;用于实现按层分类的概念 一个深度继承的子类继承了类层次中它的每个祖先的所有属性 超类,基类,父类 子类,派生类--------------------------------------面向对象编程的原则: 封装,继承,多态 允许一个接口被多个通用的类动作使用的特性,具体使用哪个动作与应用场合相关 一个接口,多个方法 用于为一组相关的动作设计一个通用的接口,以降低程序复杂性 --------------- python类和实例-------------------------类是一种数据结构,可用于创建实例 一般情况下,类封装了数据和可用于该数据的方法Python类是一个可调用对象,即类对象Python2.2之后,类是一种自定义类型,而实例则是生命某个自定义类型的变量实例初始化 通过调用类来创建实例 instance = ClassName(args..) 类在实例化时可以使用__init__和__del__两个特殊方法 ------------python中创建类-------------------------------python使用class关键字创建类,语法格式如下 class classname(bases): class documentation string class_suit 超类是一个或多个用于继承的父类的集合 类体可以包含:声明语句,类成员定义,数据属性,方法 注意: 如果不存在继承关系:classname后面的"(bases)"可以不提供 类文档为可选 class语句的一般形式 class classname(bases): data = value def method(self,...): self.member = value 例子: python中,class语句类似def,是可执行代码;直到运行class语句后类才会存在。 >>>class FirstClass: spam = 30 类属性 def display(self): 类方法,属于可调用的属性 print self.spam >>>x = FirstClass() 创建类实例 >>>x.display() 调用方法 30 class语句内,任何赋值语句都会创建类属性 每个实例对象都会继承类额属性并获得自己的名称空间 ------------python类方法及调用----------------实例(对象)通常包含属性 可调用的属性:方法 object.method() 数据属性在OOP中,实例就像是带有“数据”的记录,而类是处理这些记录的程序 通过实例调用方法相当于调用所属类的方法来处理当前实例 类似instance.method(args...)会被自动转换为 class.method() 如前面的例子,x.display()会被自动FirstClass.display(),即调用类的方法来处理实例 因此类中的每个方法必须具有self参数,它隐含当前实例之意 在方法内对self属性做赋值运算会产生每个实例自己属性 python规定,没有实例,方法不允许被调用,此即为绑定----------类和实例的属性----------------class语句中的赋值语句会创建类属性,如前面例子中的spam在类方法中对传给方法的特殊参数self进行赋值会创建实例属性例如: >>>class myclass(): gender = "data" def setname(self,x): self.name = x >>>aa = myclass() >>>aa.gender data >>>aa.setname("wy") >>>aa.name wy -----python构造器-----------------------创建实例时,python会自动调用类中的__init__方法,以隐性地为实例提供属性。 __init__方法被称为构造器
如果类中没有定义__init__方法,实例创建之初仅是一个简单的名称空间1 #例如: 2 class myclass(): 3 def __init__(self): 4 self.name="我是类的属性" 5 print self.name 6 sex = "男" 7 def func(self): 8 self.age=22 9 print self.age10 c1=myclass() #在创建c1这个对象的过程中,会同时执行一遍__init__()这个方法11 print c1.name #name这个变量可以看做是类myclass的属性,创建对象c1的时候继承了这个属性12 print c1.sex #sex这个变量也可以看做是类myclass的属性,c1同样继承这个属性,只需要调用13 14 输出:15 我是类的属性16 我是类的属性17 男18 19 20 #我们可以试试调用func()函数中的self.age变量21 print c1.age22 输出:23 AttributeError: myclass instance has no attribute 'age' age不是属性,24 25 当我们调用函数func()之后再次调用self.age这个变量26 c1.func()27 print c1.age28 输出:29 22 果然调用成功,因为执行func()后age变量生效了,并且成为c1的属性 30 2231 32 #总结一下:当我们通过类创建一个对象的过程中,类中定义的变量和__init__方法中定义的变量同时生效了,33 # 而这就是类的属性,对象继承了这个属性,只需要调用即可.34 # 但是当我们想要调用其它函数中定义的变量时,需要先调用这个变量的所属函数即可35 36 注意:属性的值可以通过函数的参数传递
----类的特殊属性-----------------------可以使用类的__dict__字典属性或python内置的dir()函数来获取类的属性class Myclass(): data = "hello myclass" def __init__(self,who): self.name=who>>>dir(Myclass)["__doc__","__init__","__module__","data"]>>>Myclass.__dict__{'__doc__': None, '__init__': <function __main__.__init__>, '__module__': '__main__', 'data': 'hello myclass'} classname.__name__ 类的名字 classname.__doc__ 类的文档字符串 classname.__bases__ 类的所有父类构成的元组 classname.__dict__ 类的属性 classname.__module__ 类定义所在的模块 C.__class__ 实例C对应的类 -------实例属性--------------------------------------------##实例仅拥有数据属性(严格意义上说,方法是类属性) 通常通过构造器"__init__"为实例提供属性 这些数据属性独立于其他实例或类 实例释放时,其属性也将被清除##内建函数dir()或实例的特殊属性__dict__可用于查看实例属性 >>>dir() >>> 实例的特殊属性 L.__class__ 实例化L的类 L.__dict__ L的属性 ----------python类方法中可用的变量--------- 实例变量:指定变量名称及实例自身进行引用 self.变量名 局部变量:方法内部创建的变量,可直接使用 类变量(也称静态变量):通过指定变量名与类名进行引用 类名.变量名 全局变量:直接使用 >>> x = FirstClass() >>> y = FirstClass() >>> x.spam,y.spam (30,30) >>>x.spam = 40 为实例继承的属性重新赋值 >>>x.spam,y.spam (40,30) >>>FirstClass.spam = 56 >>>x.spam,y.spam (40,30) >>>FirstClass.spam = 56 >>>x.spam,y.spam (40,56) 数字为不可变类型,因此x.spam已经已经指向其他对象,但是y.spam已经随类的重新赋值而改变 -----------------继承-------------------------------------------继承描述了基类的属性如何“遗传”给派生类 子类可以继承它的基类的任何属性,包括属性和方法 一个未指定基类的类,其默认有一个名为object的基类 Python允许多重继承创建子类 创建子类时,只需要在类名后跟一个或从其派生的父类 class SubClassName(ParentClass1[,ParentClass2,...]) optional class documentation string class_suite In [4]: class ParentClass(object): ...: "Parent Class" ...: gender = "Male" ...: def setName(self,who): ...: self.name = who In [5]: class ChildClass(ParentClass): ...: "Child Class" ...: def displayInfo(self): ...: print self.gender,self.nameIn [6]: x = ChildClass()In [7]: x.setName("tom")In [8]: x.displayInfo()Male tom------------python类的继承和属性搜索------python中几乎所有属性的获取都可以使用”object.attribute“的格式 不过,此表达式会在python中启动搜索————搜索连续的树class语句会产生一个类对象,对class的调用会创建实例,实例自动连接至创建了此实例的类 类连接至其超类的方式 将超类列在类头部的括号内,其从左至右的顺序会决定树种的次序 由下至上,由左至右 ----------继承方法专用化---------------------------------##继承会先在子类寻找变量名,然后才查找超类,因此,子类可以对超类的属性重新定义来取代继承而来的行为 子类可以完全取代从超类继承而来的属性 也可以通过已覆盖的方法回调超类来扩展超类的方法 例如:>>>class ParClass(object): def setinfo(self,sex="male"): self.gender = sex>>>class ChiClass(ParClass): def setinfo(self,who): 注意:子类重新定义了超类 self.name = who>>>xx = ChiClass()>>>xx.name10>>>xx.gender 没有这个参数AttributeError: 'ChiClass' object has no attribute 'gender' 例如:>>>class ParClass(object): ....: def setinfo(self,sex="wy"): ....: self.gender=sex>>>class ChiClass(ParClass): ....: def setinfo(self,who): 这里也可以写作构造器__init__ ....: self.name = who ....: ParClass.setinfo(self) 注意:这里实现了回调功能>>>xx = ChiClass()>>>xx.setinfo("tom")>>>xx.nameOut[16]: 'tom'>>>xx.genderOut[19]: 'wy'-----类,实例和其它对象的内建函数--------------------issubclass() 布尔函数,判断一个类是否由另一个类派生,语法:issubclass(sub,sup) 例如: >>>issubclass(ChildClass,ParentClass) True isinstance() 布尔函数,判断一个对象是否是给定类的实例,语法:isinstance(obi1,class_obj2) hasattr() 常用来做反射 布尔函数,判断一个对象是否拥有指定的属性,语法:hasattr(obj,"attr") 同类的函数还有getattr(),setattr()和delattr() 例如: >>> class cl(): data = "wy" def __init__(self,name="www"): self.user=name >>> d1=c1() >>>hasattr(d1,"data") 注意:要用引号 True >>>hasattr(d1,"user") Truesuper() 在子类中找出其父类以便于调用其属性 一般情况下仅能采用非绑定方式调用祖先类方法 而super()可用于传入实例或类型对象,语法:super(type[,obj])--------------------运算符重载-------------------------------------运算符重载是指在方法中拦截内置的操作————当类的实例出现在内置操作中,python会自动调用自定义的方法,并且返回自定义方法的操作结果运算符重载让类拦截常规的python运算 类可重载所有python表达式运算符 类也可重载打印,函数调用,属性点号运算等内置运算重载使类实例的行为像内置类型重载通过提供特殊名称的类方法实现运算符重载并非必须,并且通常也不是默认 基于特殊的方法定制类: 除__init__和__del__之外,python类支持使用许多的特殊方法 特殊方法都以下双划线开头和结尾,有些特殊方法有默认行为,没有默认行为的是为留到需要的时候再实现 这些特殊方法是python中用来扩充类的强大工具,他们可以实现 模拟标准类型 重载操作符 特殊方法允许通过重载标准操作符+,*,甚至包括分段下表及映射操作[]来模拟标准类型 可调用对象: 函数 内置函数 自定义函数 def lambda 类 类方法 函数属性: __doc__ __name__ __dict__ __code__ __globals__ 方法属性: __doc__ __name__ __class__:方法所属类 __func__:实现该方法的函数对象 __self__:调用此方法的实例 内置函数: __doc__ __name__ __self__ 类: __doc__ __name__ __bases__ __dict__ __module__:定义了当前类的模块名称 实例: __class__ __dict__ 对象都有特殊方法: __init__,__new__,__del__ __dir__() __add__() __ge__() a > b a.__ge__(b)