Python 原创基础教程
第五章 面向对象
5.1 继承
1 2 3 4 5 6 7 8
| class Animal: def eat(self): print("%s 吃 "%self.name) def drink(self): print("%s 喝 " %self.name)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| class Cat(Animal): def __init__(self, name): self.name = name self.breed = '猫' def cry(self): print '喵喵叫' class Dog(Animal): def __init__(self, name): self.name = name self.breed = '狗' def cry(self): print '汪汪叫'
|
5.5.1 多继承
- 可以继承多个类
- 继承类分为经典类和新式类
- 当前类或者父类继承了object类,那么该类便是新式类,否则便是经典类。
- 经典类时,多继承会按照深度优先查找覆盖方法
- 新式类时,多继承会按照广度优先查找覆盖方法
- 子类中,super()可以调用父类的属性和方法
调用super()的实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| class Parent(object): def __init__(self): self.parent = 'I\'m the parent.' print ('Parent') def bar(self,message): print ("%s from Parent" %message) class Child(Parent): def __init__(self): super().__init__() print ('Child') def bar(self,message): super().bar(message) print ('Child bar fuction') print (self.parent) C = Child() C.bar('HelloWorld')
|
多继承顺序实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| class A: def say(self): print("A Hello:", self) class B(A): def eat(self): print("B Eating:", self) class C(A): def eat(self): print("C Eating:", self) class D(B, C): def say(self): super().say() print("D Hello:", self) def dinner(self): self.say() super().say() self.eat() super().eat() C.eat(self) d = D() d.eat() C.eat(d) D.__mro__ d.dinner()
|
5.2 封装
- 封装,即隐藏对象的属性和实现细节,仅对外公开接口,控制在程序中属性的读和修改的访问级别。
- 将内容封装到类
- 从某处调用被封装的内容(通过对象或者self)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| class B: def __init__(self,name,age): self.name = name self.age = age def f1(self): print(self.name,self.name)
obj1 = B('anda',28)
print(obj1.name)
obj1.f1()
|
5.3 多态
- 多态是同一个行为具有多个不同表现形式或形态的能力。
- 多态就是同一个接口,使用不同的实例而执行不同操作
- 实现多态的三要素(继承、重写、父类引用指向子类对象)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| class F1: pass class S1(F1): def show(self): print 'S1.show' class S2(F1): def show(self): print 'S2.show'
def Func(F1 obj): """Func函数需要接收一个F1类型或者F1子类的类型""" print obj.show() s1_obj = S1() Func(s1_obj) s2_obj = S2() Func(s2_obj)
|
5.4 type()产生对象
Python中一切事物都是对象,类也是
类可由type类实力化产生
type() 函数如果你只有第一个参数则返回对象的类型,三个参数返回新的类型对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| # case 1:普通方式
class Foo(object): def func(self): print 'hello wupeiqi' # case 2:特殊方式
def func(self): print 'hello wupeiqi' Foo = type('Foo',(object,), {'func': func}) #type第一个参数:类名 #type第二个参数:当前类的基类 #type第三个参数:类的成员
|
5.5 类的特殊成员
1.__ doc__:表示类的描述
1 2 3 4 5 6 7 8
| class Foo: """ 描述类信息,这是用于看片的神奇 """ def func(self): pass print(Foo.__doc__)
|
2.__ module__:表示当前操作对象在哪个模块
模块:组织函数和类的单位(类似java的一类一文件,有时不同模块可能有同名函数),例如Django
1
| print(obj.__module__) #输出对象所在模块
|
3.__ class__:表示当前操作对象的是什么
类
1
| print(obj.__class__) #输出对象所在类
|
4.__ init(self,..)__:
构造方法、类创建对象时自动执行
5.__ del(self,..)__:
析构方法、当对象在内存释放时、自动触发执行。
此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。
6.__ call(self,..)__:
除析构方法外,执行对象的另一种特殊方法,对象加括号执行
1 2 3 4 5 6 7 8 9 10 11
| class Foo: def __init__(self): pass def __call__(self, *args, **kwargs): print '__call__' obj = Foo() # 执行 __init__ obj() # 执行 __call__
|
7.__ dict__:
显示类(静态变量、方法)和对象(普通字段)的所以成员
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| class Province: country = 'China' def __init__(self, name, count): self.name = name self.count = count def func(self, *args, **kwargs): print 'func' # 获取类的成员,即:静态字段、方法、 print Province.__dict__ # 输出:{'country': 'China', '__module__': '__main__', 'func': , '__init__': , '__doc__': None} obj1 = Province('HeBei',10000) print obj1.__dict__ # 获取 对象obj1 的成员 # 输出:{'count': 10000, 'name': 'HeBei'} obj2 = Province('HeNan', 3888) print obj2.__dict__ # 获取 对象obj1 的成员 # 输出:{'count': 3888, 'name': 'HeNan'}
|
- __ str__:如果一个类中定义了__str__方法,那么在打印(print)对象时,默认输出该方法的返回值。
9.__ getitem__、__ setitem__、__ delitem__
用于对象的索引操作,如字典。以上分别表示获取、设置、删除数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| #!/usr/bin/env python # -*- coding:utf-8 -*- class Foo(object): def __getitem__(self, key): print '__getitem__',key def __setitem__(self, key, value): print '__setitem__',key,value def __delitem__(self, key): print '__delitem__',key obj = Foo() result = obj['k1'] # 自动触发执行 __getitem__ obj['k2'] = 'wupeiqi' # 自动触发执行 __setitem__ del obj['k1'] # 自动触发执行 __delitem__
|
10.getslice__、__setslice__、__delslice
用于对象的分片操作(如列表)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| class Foo(object): def __getslice__(self, i, j): print '__getslice__',i,j def __setslice__(self, i, j, sequence): print '__setslice__',i,j def __delslice__(self, i, j): print '__delslice__',i,j obj = Foo() obj[-1:1] obj[0:1] = [11,22,33,44] del obj[0:2]
|
11.__ iter__:迭代器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
|
class Foo(object): pass obj = Foo() for i in obj: print i
class Foo(object): def __iter__(self): pass obj = Foo() for i in obj: print i
class Foo(object): def __init__(self, sq): self.sq = sq def __iter__(self): return iter(self.sq) obj = Foo([11,22,33,44]) for i in obj: print i
|
迭代的变种
1 2 3 4 5 6 7 8 9 10 11
| obj = iter([11,22,33,44]) for i in obj: print i
############################ obj = iter([11,22,33,44]) while True: val = obj.next() print val
|
12.__new__方法
继承自object的新式类才有__new__
__new__方法接受的参数虽然也是和__init__一样,但__init__是在类实例创建之后调用,而 __new__方法正是创建这个类实例的方法。
依照Python官方文档,__new__方法主要是当你继承一些不可变的class时(比如int, str, tuple), 提供给你一个自定义这些类的实例化过程的途径。还有就是实现自定义的metaclass。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| # 创建一个类,继承int,并返回绝对值 class PositiveInteger(int): def __init__(self, value): super(PositiveInteger, self).__init__(self, abs(value)) i = PositiveInteger(-3) print i #结果还是-3
class PositiveInteger(int): def __new__(cls, value): return super(PositiveInteger, cls).__new__(cls, abs(value)) i = PositiveInteger(-3) print i #结果是 3
|
因为类的每一次实例化都是通过__new__实现的,通过重载类来实现单例
1 2 3 4 5 6 7 8 9 10 11 12 13
| class Singleton(object): def __new__(cls): # 关键在于这,每一次实例化的时候,我们都只会返回这同一个instance对象 if not hasattr(cls, 'instance'): cls.instance = super(Singleton, cls).__new__(cls) return cls.instance obj1 = Singleton() obj2 = Singleton() obj1.attr1 = 'value1' print obj1.attr1, obj2.attr1 print obj1 is obj2
|