Python【第三章】:python 面向对象 (new)
- 面向对象是一种编程方式,此编程方式的实现是基于对 类 和 对象 的使用
- 类 是一个模板,模板中包装了多个“函数”供使用(可以讲多函数中公用的变量封装到对象中)
- 对象,根据模板创建的实例(即:对象),实例用于调用被包装在类中的函数
- 面向对象三大特性:封装、继承和多态
- 适用于每个事物属性有相同,共同值情况使用面向对象。
面向对象把重复操作放入类中,类中self代表实例的对象。
- class是关键字,表示类
- 创建对象,类名称后加括号即可
class Foo: def Bar(self): print 'Bar' def Hello(self, name): print 'i am %s' %name # 根据类Foo创建对象obj obj = Foo() obj.Bar() #执行Bar方法 obj.Hello('wupeiqi') #执行Hello方法
ps:类中的函数第一个参数必须是self(详细见:类的三大特性之封装)
类中定义的函数叫做 “方法”
函数式的应用场景 --> 各个函数之间是独立且无共用的数据
一、封装 把调用内容,通过类内函数把内容封装入类内。
将内容封装到某处
self 是一个形式参数,当执行 obj1 = Foo('wupeiqi', 18 ) 时,self 等于 obj1
当执行 obj2 = Foo('alex', 78 ) 时,self 等于 obj2
所以,内容其实被封装到了对象 obj1 和 obj2 中,每个对象中都有 name 和 age 属性,在内存里类似于下图来保存。
从某处调用被封装的内容
调用被封装的内容时,有两种情况:
- 通过对象直接调用
- 通过self间接调用
1、通过对象直接调用被封装的内容
上图展示了对象 obj1 和 obj2 在内存中保存的方式,根据保存格式可以如此调用被封装的内容:对象.属性名
class Foo: def __init__(self, name, age): self.name = name self.age = age obj1 = Foo('wupeiqi', 18) print obj1.name # 直接调用obj1对象的name属性 print obj1.age # 直接调用obj1对象的age属性 obj2 = Foo('alex', 73) print obj2.name # 直接调用obj2对象的name属性 print obj2.age # 直接调用obj2对象的age属性
2、通过self间接调用被封装的内容
执行类中的方法时,需要通过self间接调用被封装的内容
class Foo: def __init__(self, name, age): self.name = name self.age = age def detail(self): print self.name print self.age obj1 = Foo('wupeiqi', 18) obj1.detail() # Python默认会将obj1传给self参数,即:obj1.detail(obj1),所以,此时方法内部的 self = obj1,即:self.name 是 wupeiqi ;self.age 是 18 obj2 = Foo('alex', 73) obj2.detail() # Python默认会将obj2传给self参数,即:obj1.detail(obj2),所以,此时方法内部的 self = obj2,即:self.name 是 alex ; self.age 是 78
综上所述,对于面向对象的封装来说,其实就是使用构造方法将内容封装到 对象 中,然后通过对象直接或者self间接获取被封装的内容。
二、继承 子类中没有的函数,从父类复制到子类。
子类中可以继承父类中内容
所以,对于面向对象的继承来说,其实就是将多个类共有的方法提取到父类中,子类仅需继承父类而不必一一实现每个方法。
称为:父类 - 子类 ,基类 - 派生类
单继承:
class F1: # 父类,基类 def show(self): print('show') def foo(self): print(self.name) class F2(F1): # 子类,派生类 def __init__(self, name): self.name = name def bar(self): print('bar') def show(self): print('F2.show') obj = F2('alex') # obj.show() obj.foo()
多继承:
#!/usr/bin/env python # -*- coding:utf-8 -*- class C3: def f1(self): print('C3') class C2(C3): def f1(self): print("C2") class C4: def f2(self): print("C4") class C1(C2,C4): pass a = C1() a.f2()
#!/usr/bin/env python # -*- coding:utf-8 -*- class CC: def f2(self): print("CC") class C3(CC): def f1(self): print('C3') class C2(C3): def f1(self): print("C2") class C5(CC): def f2(self): print("C5") class C4(C5): def f2(self): print("C4") class C1(C2,C4): pass a = C1() a.f2()
三、多态性 类中传参时,参数可以为任何类型。
没有强类型中,一定要指定传参数的类型。
class F1: pass class S1(F1): def show(self): print 'S1.show' class S2(F1): def show(self): print 'S2.show' def Func(obj): print obj.show() s1_obj = S1() Func(s1_obj) s2_obj = S2() Func(s2_obj)
类和对象在内存中保存方式:
类以类中方法在内存中只有一份,而根据类创建每一个对象都 在内存中需要一份
根据类创建对象时,对象中除了封装属性值外,还会保存一个类对象指针,该值指向当前对象的类。
当通过obj1执行时
1、根据当前对象中类对象指针找到类中方法。
2、将对象obj1当作参数传给方法的第一个参数self