0%

5.面向对象

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(FooChild,self).__init__() //python2语法
super().__init__()
print ('Child')

def bar(self,message):
#super(FooChild, self).bar(message)//这里是python2的语法
super().bar(message)
print ('Child bar fuction')
print (self.parent) #继承父类属性

C = Child()
C.bar('HelloWorld')

#执行结果:
#Parent
#Child
#HelloWorld from Parent
#Child bar function
#I'm the parent

多继承顺序实例

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)

#自动执行__init__方法
obj1 = B('anda',28)

print(obj1.name) #直接调用对象属性

obj1.f1() #obj1将self作为参数传递给f1(),因此self就是obj1,实现self的间接调用

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'

# 由于在Java或C#中定义函数参数时,必须指定参数的类型
# 为了让Func函数既可以执行S1对象的show方法,又可以执行S2对象的show方法,所以,定义了一个S1和S2类的父类
# 而实际传入的参数是:S1对象和S2对象

def Func(F1 obj):
"""Func函数需要接收一个F1类型或者F1子类的类型"""

print obj.show()

s1_obj = S1()
Func(s1_obj) # 在Func函数中传入S1类的对象 s1_obj,执行 S1 的show方法,结果:S1.show

s2_obj = S2()
Func(s2_obj) # 在Func函数中传入Ss类的对象 ss_obj,执行 Ss 的show方法,结果:S2.show

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'}

  1. __ 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] # 自动触发执行 __getslice__
obj[0:1] = [11,22,33,44] # 自动触发执行 __setslice__
del obj[0:2] # 自动触发执行 __delslice__

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
##case 1:

class Foo(object):
pass

obj = Foo()

for i in obj:
print i

# 报错:TypeError: 'Foo' object is not iterable

## case 2:

class Foo(object):

def __iter__(self):
pass

obj = Foo()

for i in obj:
print i

# 报错:TypeError: iter() returned non-iterator of type 'NoneType'

## case 3:

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