标签:阶段 数据 com 实例 一个 san 实验 wal 多继承
前面我们讲了类的私有属性,现在我们来说说类的公有属性,这边很容易被人弄混淆,有人觉的,在__init__()构造方法中,除了私有属性,其他的都是公有属性了,其实这是一个错误的结论,并不是定义在__init__()初始化方法中的属性是公有属性(除私有属性),那什么是公有属性呢?揭起了大家的好奇心。
定义:指的是所属这个类的所有对象,都可以访问的属性,叫做公有属性。
说明:在类中直接定义的,可以提供这个类所属的所有对象都可以访问的属性
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
class dog(object): "dog class" nationality = "JP" #定义公有属性nationality def __init__(self,name): self.name = named1 = dog("alex")d2 = dog("sanjiang")print(d1.nationality,d2.nationality) #所有的成员变量都可以访问#输出JP JP |
这边有个小疑问,d1.name,d2.name也可以访问,也可以修改, 为什么不能叫公有属性呢?代码如下
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
class dog(object): "dog class" nationality = "JP" def __init__(self,name): self.name = named1 = dog("alex")d2 = dog("sanjiang")print(d1.name,d2.name)#输出alex sanjiang |
很明显,上面的name是每个对象的属性,并不是共享,而是独立的 。
说明:公有属性不仅可以通过所属类的所有对象访问,还可以通过类本身直接访问和修改
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
class dog(object): "dog class" nationality = "JP" #定义公有属性 def __init__(self,name): self.name = named1 = dog("alex")d2 = dog("sanjiang")print(dog.nationality) #访问公有属性dog.nationality = "US" #修改公有属性print(dog.nationality)#输出JPUS |
说明:公有属性不是私有属性,它提供所有对象访问和修改,那我们其中有一个对象正在修改公共属性发生什么变化呢?或者类本身直接修改了公共属性,又放生什么变化呢?
|
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
|
class dog(object): "dog class" nationality = "JP" def __init__(self,name): self.name = named1 = dog("alex")d2 = dog("sanjiang")print("firsthand change...")print(d1.nationality,d2.nationality)print("brfore change ...")d1.nationality = "CN" #对象的d1修改公共属性得值print(d1.nationality,d2.nationality)print("after change ....")dog.nationality = "US" #dog类本省修改公共属性的值print(d1.nationality,d2.nationality)#输出firsthand change...JP JPbrfore change ...CN JP #d1对象的公共属性被修改了after change ....CN US #d1对象的公共属性值没有随着类本身的公共属性值修改而修改 |
我去,看的我头昏眼花的。。。好吧,下面我就一张图来说明一下:

对上面的图做一下总结:
从上面我们可以看出公有属性只有一个,而且是在没有定义对象的时候,就已经存在,那么类中的方法是不是每调用一次,就会生成一个呐?答案是肯定不会的。
就是说,你去实例化然后调用sayhi方法,只是拿着这块内存中的数据去调公有的sayhi方法而已,并不是有多个。
析构函数,第一次听说这个函数的名称,那这个函数到底是干嘛的呢?什么才是析构函数呐?
定义:在实例销毁的时候调用的函数
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
class dog(object): "dog class" def __init__(self,name): self.name = name def sayhi(self): print("the dog {0} is sayhi".format(self.name)) def __del__(self): #定义析构函数 print("del.....run...")d = dog("alex")del dimport timetime.sleep(5)#输出del.....run... |
其实每一个对象都是一个应用,就像每一个房间都有门牌号一样, 只要这个对象的引用被清空时,就会自动执行,就像上面的del d,其实python中有自动垃圾回收机制,会定时去的去回收一些被清空的应用,而析构函数就是在引用被清空之后会自动执行
比如说server端接受很多客户端的连接,当你手动屏蔽你的sever端的时候,这个时候客户端还在正常的连接,如果sever端用类写的,你就可以delete server端的同时,在__del__()写一些东西,说去close掉很多客户端的连接。说白了,析构函数就是做一些程序的收尾工作。
之前我们说到了类的公有属性和类的私有属性,其实就是类的封装,下面我们来讲讲继承,是面向对象的第二大特性。
面向对象编程 (OOP) 语言的一个主要功能就是“继承”。继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。
通过继承创建的新类称为“子类”或“派生类”,被继承的类称为“基类”、“父类”或“超类”,继承的过程,就是从一般到特殊的过程。在某些 OOP 语言中,一个子类可以继承多个基类。但是一般情况下,一个子类只能有一个基类,要实现多重继承,可以通过多级继承来实现。
继承概念的实现方式主要有2类:实现继承、接口继承。
在考虑使用继承时,有一点需要注意,那就是两个类之间的关系应该是“属于”关系。例如,Employee 是一个人,Manager 也是一个人,因此这两个类都可以继承 Person 类。但是 Leg 类却不能继承 Person 类,因为腿并不是一个人。
抽象类仅定义将由子类创建的一般属性和方法,OO开发范式大致为:划分对象→抽象类→将类组织成为层次化结构(继承和合成) →用类与实例进行设计和实现几个阶段
说明:在类名的括号中写入需要继承的类名即可
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
class Person(object): def talk(self): print("person is talking...")class BlackPerson(Person): #继承Person这个类 def walk(self): #定义子类自身的walk方法 print("BlackPerson is walking.....")b = BlackPerson()b.talk() #由于继承了父类的talk()方法,所以可以被调用b.walk() #调用子类自身的walk方法#输出person is talking...BlackPerson is walking..... |
说明:因为子类有自己的属性,但是又想继承父类的属性,所以需要先继承,再重构
继承类的构造方法2种写法:
注:建议使用新式类的写法,因为使用经典类的写法,在多继承的情况下,会出现重复调用参数的可能
代码如下:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
class Person(object): def __init__(self,name,age): self.name = name self.age = age self.sex = "noraml" def talk(self): print("person is talking...")class BlackPerson(Person): def __init__(self,name,age,strength): #定义时需要传入父类的属性名 Person.__init__(self,name,age) #继承父类的构造方法,也可以写成:super(BlackPerson,self).__init__(name,age) self.strength = strength #定义子类本身的属性 print(self.name,self.age,self.sex) def walk(self): print("BlackPerson is walking.....")b = BlackPerson("xiaogao",18,"strong")#输出xiaogao 18 noraml |
这边不禁的有一个疑问?我不能重新写一遍,我为啥要继承父类中的方法呢?因为你重新写一遍的话,只能继承self.name和self.age,那self.sex怎么办,它也需要重写吗?所以啊,只有把父类中的构造函数全部继承过来,只能用上面这种办法?那它是怎么实现的呢?我们来画一个图:

说明:如果我对父类中的方法不满意,我可以重写父类中的方法,当然还可以继承父类中的方法,但是我们一般不这样干。
|
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
|
class Person(object): def __init__(self,name,age): self.name = name self.age = age self.sex = "noraml" def talk(self): print("person is talking...")class BlackPerson(Person): def talk(self): #重写父类的方法 Person.talk(self) #调用父类的方法 print("BlackPerson is talking ...") def walk(self): print("BlackPerson is walking.....")b = BlackPerson("xiaogao",18) #子类不写,则继承父类的构造方法b.talk()b.walk()#输出person is talking...BlackPerson is talking ...BlackPerson is walking..... |
其实重写不是上面说的那么简单,只需要子类的方法名和父类的中的方法名一样就算重写了,其实不然,那怎么样才算重写呢?
我们再来看看下面的例子:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
class Person(object): def talk(self,food): print("person is talking...{0}".format(food))class BlackPerson(Person): def talk(self): #方法名和父类的方法名一样,但是少了一个food参数 print("BlackPerson is talking ...")b = BlackPerson("xiaogao",18,"strong")b.talk()#输出BlackPerson is talking ... |
有些同学说,这明明是重写了呀!其实不是重写,根据重写的条件明显两个方法的传入参数名和参数的个数都不一样,其实上面这种只是子类自己写了一个talk方法,只是名字一样,但是传入的参数和参数的个数不一样,并不是重写了父类中的方法。下面这个才是真正的重写:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
class Person(object): def talk(self,food): print("person is talking...{0}".format(food))class BlackPerson(Person): def talk(self,food): #重写父类的方法(方法名和传入的参数名以及参数的个数与父类的方法一样) print("BlackPerson is talking ...{0}".format(food))b = BlackPerson("xiaogao",18,"strong")b.talk("hotdog")#输出BlackPerson is talking ...hotdog |
|
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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
class SchoolMember(object): ‘‘‘学校成员基类‘‘‘ member = 0 #设置类属性 def __init__(self,name,age,sex): self.name = name self.age = age self.sex =sex self.enroll() #每次生成一个对象注册一次 def enroll(self): "注册" print("just enroll a new school member [{0}]".format(self.name)) SchoolMember.member += 1 def tell(self): print("------info:{0}-----".format(self.name)) for k,v in self.__dict__.items(): #__dict__()函数是获取对象的属性,以字典的形式返回 print("\t",k,v) print("------end--------") def __del__(self): print("开除了[{0}]...".format(self.name)) SchoolMember.member -= 1class Teacher(SchoolMember): "讲师类" def __init__(self,name,age,sex,salary,course): SchoolMember.__init__(self,name,age,sex) self.salary = salary self.course = course def teaching(self): "讲课方法" print("Teacher [{0}] is teaching [{1}]".format(self.name,self.course))class Student(SchoolMember): "学生类" def __init__(self,name,age,sex,couser,tuition): SchoolMember.__init__(self,name,age,sex) self.couser = couser self.tuition = tuition self.amount = 0 def pay_tuition(self,amount): print("student [{0}] has just paied [{1}]".format(self.name,amount)) self.amount += amountt1 = Teacher("xiaogao",18,"F*M",3000,"Python")s1 = Student("shuaigao",19,"M","PYS15",300000)s2 = Student("gaogao",12,"M","PYS15",11000)print(SchoolMember.member)del s1 #删除一个变量t1.tell()s2.tell()print(SchoolMember.member) #会执行__del__函数#输出just enroll a new school member [xiaogao]just enroll a new school member [shuaigao]just enroll a new school member [gaogao]3开除了[shuaigao]...------info:xiaogao----- salary 3000 sex F*M course Python name xiaogao age 18------end--------------info:gaogao----- couser PYS15 sex M name gaogao amount 0 tuition 11000 age 12------end--------2开除了[gaogao]...开除了[xiaogao]... |
在python还支持多继承,但是一般我们很少用,有些语言干脆就不支持多继承,有多继承,就会带来两个概念,经典类和新式类,下面我就来学学什么是多继承,什么是经典类和新式类?
说明:之前我们都是讲的单继承,那么什么是多继承呢?说白了,就是:子类可以继承多个父类,就叫多继承
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
class SchoolMember(object): #SchoolMember类 ‘‘‘学校成员基类‘‘‘ def tell(self): print("the schoolmeber is tell...")class School(object): #School类 """学校类""" def open_branch(self,addr): print("openning a new branch in",addr)class Teacher(SchoolMember,School): #子类Teacher同时继承了SchoolMember,School两个类 "讲师类" def teaching(self): "讲课方法" print("Teacher xiaogao is teaching python")t1 = Teacher()t1.tell() #拥有父类SchoolMember的tell方法t1.open_branch("shanghai") #拥有父类School的open_branch方法 |
1、概念
新式类定义时必须继承object类,被定义继承了object类的,就叫做新式类
|
1
2
|
class Person(object): #继承object类 "新式类" |
2、继承构造方法
新式类初始化构造方法用super关键字去继承
|
1
|
super(子类,self).__init__(name,age) |
3、调用父类中相同方法或者相同属性的顺序
新式类多继承的调用方法是顺序是:广度优先查询,如下图:

代码实验如下:
①全部代码
class A(object): #新式类
def __init__(self):
self.n = "A"
class B(A):
def __init__(self):
self.n = "B"
class C(A):
def __init__(self):
self.n = "C"
class D(B,C):
def __init__(self):
self.n = "D"
d = D()
print(d.n)
#输出
D
没有问题,先找自己的属性,输出D
②注释D类中代码
class A(object):
def __init__(self):
self.n = "A"
class B(A):
def __init__(self):
self.n = "B"
class C(A):
def __init__(self):
self.n = "C"
class D(B,C):
pass
d = D()
print(d.n)
#输出
B
③注释B类中的代码
class A(object):
def __init__(self):
self.n = "A"
class B(A):
pass
class C(A):
def __init__(self):
self.n = "C"
class D(B,C):
pass
d = D()
print(d.n)
#输出
C
④注释C类中的代码
class A(object):
def __init__(self):
self.n = "A"
class B(A):
pass
class C(A):
pass
class D(B,C):
pass
d = D()
print(d.n)
#输出
A
1、概念
经典类定义,什么都不继承
|
1
2
|
class Person: "经典类" |
2、继承构造方法
|
1
|
父类.__init(self,name,age) |
3、调用父类中相同方法或者相同属性的顺序
经典类多继承的调用方法是顺序是:深度优先查询,如下图:

代码实验如下:
①全部代码
class A:#经典类
def __init__(self):
self.n = "A"
class B(A):
pass
def __init__(self):
self.n = "B"
class C(A):
def __init__(self):
self.n = "C"
class D(B,C):
def __init__(self):
self.n = "D"
d = D()
print(d.n)
#输出
D
②注释D类中代码
class A:
def __init__(self):
self.n = "A"
class B(A):
def __init__(self):
self.n = "B"
class C(A):
def __init__(self):
self.n = "C"
class D(B,C):
pass
d = D()
print(d.n)
#输出
B
③注释B类中的代码
class A:
def __init__(self):
self.n = "A"
class B(A):
pass
class C(A):
def __init__(self):
self.n = "C"
class D(B,C):
pass
d = D()
print(d.n)
#输出
A
④注释A类中的代码
class A:
pass
class B(A):
pass
class C(A):
def __init__(self):
self.n = "C"
class D(B,C):
pass
d = D()
print(d.n)
#输出
C
标签:阶段 数据 com 实例 一个 san 实验 wal 多继承
原文地址:http://www.cnblogs.com/luoahong/p/7207871.html