面向对象编程(OOP)
面向过程的程序设计把计算机程序视为一系列命令的集合,典型的面向过程的思想是把函数切分成子函数,把大块的函数通过切割成小块函数来降低系统的复杂性;
而面向对象的程序设计把计算机程序视为一组对象的集合,而每个对象都可以接收其他对象发过来的消息,处理这些消息,程序的执行就是一系列消息在各个对象之间的传递;面向对象设计思想是抽象出class,根据class创建出Instance。
|
|
类和实例(Class & Instance)
Class 是抽象的模板,是创建实例的模板
Instance 是根据类创建出来的一个个具体的对象,各个实例拥有的数据相互独立,互不影响
Method 是于实例绑定的函数,在类中定义,和普通函数不同,方法可以直接方问实例的数据
|
|
访问限制(Access Restriction)
- 若要让内部属性不被外部访问,可以把属性的名称前加上两个下划线
__
,变量名如果以__
开头,说明这个变量是一个私有变量(Private),只有内部可访问,外部不能访问; - 如果看到一个下划线
_
开头的实例变量,这个变量是可以直接访问的,但是约定俗成是“虽然可以被访问,但请把我视为私有变量,不要随意访问”
|
|
继承和多态( Inheritance and Polymorphic)
|
|
多态:调用方只管调用,不用管细节,开闭原则:
- 对扩展开放:允许新增
Animal
子类; - 对修改封闭:不需要修改依赖
Animal
类型的run_twice
函数
静态语言Vs动态语言 在多态上的表现差别:
- 静态语言(如C++)来说,如果传入的是
Animal
类型,传入的对象必须是Animal
类型或者是它的子类型,否则无法调用run()
方法; - 动态语言(如Python)来说,不一定需要传入
Animal
类型或者子类型,只需要保证传入的对象有run()
方法。 - 比如类
Timeir
可以调用run_twice
,这个就是动态语言的鸭子类型,一个对象只要“看起来像鸭子,走起路来像鸭子”,那它就被视作鸭子 - Python中的“file-like object”就是一种鸭子类型。
获取对象信息(使用常见函数)
type(): 基本类型(int,str)、一个变量指向的函数或类(上例子中的Animal) 可以使用type()函数判断,返回的是对应的
Class
类型12type(a)<class '__main__.Animal'>isinstance(): 判断
class
的类型,也可以判断一个变量是否是某些类型中的一种123451,2,3],list)isinstance([True1,2,3),tuple)isinstance((True1,2,3),(tuple,list))isinstance((dir(): 可以获取一个对象的所有属性和方法,返回一个包含字符串的list;
12dir(li)['_Student__name', '_Student__score', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'get_name', 'get_score', 'set_name', 'set_score']其他方法
可以配合使用getattr()、setattr()、hasattr()
来操作一个对象的状态
|
|
类属性和实例属性
- 给实例绑定属性的方法:通过实例变量或者
self
变量 - 给类本身绑定属性:直接在class中定义属性,这种属性是类属性,归该类所有,但类的所有实例都可以访问
|
|
面向对象高级编程
- 动态语言的灵活性:定义一个class,并创建一个class实例后,可以对该实例绑定任何属性和方法(只作用在该实例);也可以给class绑定一个方法或者属性,对该class的所有实例起作用
|
|
- 使用
__slots__
限制实例的属性: 例如只允许对Student
实例添加name
和age
属性,可以在定义Student
class的时候,使用slots,要注意的是,使用该方法定义的属性只对 当前类的实例 起作用,对继承的子类不起作用
|
|
装饰器@property
实现既能检查参数,又可以用类似属性的方式来访问类的变量,如下例,可以直接使用s.score=90
的方式来设置属性,并且可以有限制。
|
|
多重继承(MixIn)
主线用正常的方式继承,副线用MixIn继承(只是起个名字而已,加在后面),如:
定制类
Python中,[xxx] 类似于这样的变量或者函数名,在Python中有特殊用途,可以用来定制类,定制类中各种返回的特殊值。
|
|
使用枚举类(Enum)
|
|
使用元类(metaclass)
- type()函数:可以使用该函数返回一个对象类型,也可以创建出新的类型。
要创建一个class对象,type()
依次传入三个参数:
- class的名称
- 继承的父类集合,如果只有一个父类,需要在该父类后加逗号(tuple的单元素写发)
- class的方法名称和函数的绑定。下例中是函数fn绑定在方法名hello上。1234def fn(self,name='world'):print('Hello,%s.'%name)Hello=type('Hello',(object,),dict(hello=fn))
- metaclass:
称为元类,先定义metaclass,然后创建类。可以把类看成是metaclass创建出来的“实例”。按照习惯,metaclass的类名总是以Metaclass结尾,表示这个是一个metaclass。先定义metaclass,就可以创建类,然后创建实例
讲的比较详细的看链接