• 面向对象的设计思想是抽象出Class(类),根据Class创建Instance(实例)。

  • 类是一个相对抽象的概念,而实例是其具体化。例如将学生视为,那么李华,王丽等具体的学生就是实例

  • 类由属性和方法组成,属性用来描述其特征,例如学生的姓名、成绩等;方法用来描述其拥有的动作行为,例如格式化输出学生的成绩,判断成绩的等级等

1、创建类与实例

1.1 创建类

  • 使用class关键字定义类,类名的首字母通常大写。

  • 通过__init__方法创建类的属性,注意第一个参数为self

  • 创建类的方法时,类似之前的创建函数的方式。注意第一个参数为self,可以调用类自身的属性self.xxx数据。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
class Student():
    def __init__(self, name, score):
        self.name = name
        self.score = score
    def print_score(self):
        '格式化输出学生成绩'
        print('%s: %s' % (self.name, self.score))
    def get_grade(self):
        '将成绩分为不同的等级'
        if self.score >= 90:
            return 'A'
        elif self.score >= 60:
            return 'B'
        else:
            return 'C'

1.2 创建实例

  • 来源同一类的不同实例的属性一般不同,但都有相同的方法
  • 创建实例后,仍然可以修改实例的属性值,甚至增删属性。
 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
#(1)注意需要提供与 __init__ 参数顺序一致的属性数据
stuA = Student("LiHua",95)
stuB = Student("WangZi",88)

#(2)查看属性值
stuA.name 
stuB.score

#(3)调用方法
stuA.print_score()
## LiHua: 95
stuB.get_grade()
## 'B'

#(4)修改属性
stuA.score=100
stuA.score

#(5)增删属性
stuA.age = 17
stuA.age
## 17
del stuA.age
stuA.age
# Traceback (most recent call last):
  # File "<stdin>", line 1, in <module>
# AttributeError: 'Student' object has no attribute 'age'

#(5)查看属性和方法
##查看所有属性与方法
dir(stuA)
# 返回列表,包含所有属性与方法名
##判断是否有某属性
hasattr(stuA, "name")
# True
##获得对象的属性值,如果没有该属性则返回默认值
getattr(stuA, "newscore", 404)
# 404

2、私有属性

  • 如果要让内部属性不被外部访问,可以把属性的名称前加上两个下划线__
 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
class Student():
    
    def __init__(self, name, score):
        '双下划线设置私有变量'
        self.__name = name
        self.__score = score
        
    def get_name(self):
        '方法仍可以调用私有变量'
        return self.__name
    
    def set_score(self, score):
        '方法仍可以修改私有变量;通过引入if语句可添加参数检查步骤'
        self.__score = score
        
    def print_score(self):
        print('%s: %s' % (self.__name, self.__score))
 
stuA = Student("zhangsan", 66)
##(1) 无法通过正常访问对象属性的方式查看实例的私有属性
stuA.name #无法访问
# Traceback (most recent call last):
  # File "<stdin>", line 1, in <module>
# AttributeError: 'Student' object has no attribute 'name'
stuA.__name #无法访问
# Traceback (most recent call last):
  # File "<stdin>", line 1, in <module>
# AttributeError: 'Student' object has no attribute '__name'

##(2)但是仍可以通过方法访问、修改私有属性
stuA.get_name()
# 'zhangsan'
stuA.set_score(99)
stuA.print_score()
# zhangsan: 99

3、类与子类

3.1 继承

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#(1)创建类以及类的实例
class Animal():
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def run(self):
        print(self.name,'is running...')

aniA = Animal("Xiaochai", 5)
aniA.run()
## Xiaochai is running...

#(2)创建子类以及子类的实例
class Dog(Animal):
    def eat(self, food):
        print("Look, This is a dog and it is eating",food)
##继承父类的属性
dogA = Dog("Xiaobai","3")
##继承父类的方法
dogA.run()
# Xiaobai is running...
##调用自己的方法
dogA.eat("meat")
# Look, This is a dog and it is eating meat

当子类新定义的方法名与从父类继承的方法名相同时,会优先调用前者。

3.2 多态

  • 定义一个class的时候,我们实际上就定义了一种数据类型。
  • 可以使用isinstance()判断是否为某个类型
 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
a = [1,2,3]
isinstance(a, list)
# True
b = 'anything'
isinstance(b, str)
#True

#(1)定义父类
class Animal():
    def run(self):
        print('Animal is running...')
##实例化父类
aniA = Animal()
##判断实例的类型
isinstance(aniA, Animal)
# True


#(2)定义子类
class Dog(Animal):
    pass

##实例化子类
dogA = Dog()
##判断实例的类型:既属于父类,也属于子类
isinstance(dogA, Dog)
# True
isinstance(dogA, Animal)
# True
isinstance(aniA, Dog)
# False

#(3) 多态的应用之一:编写函数
##编写一个接受Animal类型的变量
def run_twice(animal):
    animal.run()
    animal.run()
run_twice(aniA)
run_twice(dogA)
#任何依赖父类(Animal)作为参数的函数或者方法都可以不加修改地正常运行子类(Dog),原因就在于多态。