面向对象的三大特征
封装:提高程序的安全性
- 将数据(属性)和行为(方法)包装到类对象中。在方法内部对属性进行操作,在类对象的外部调用方法。这样,无需关心方法内部的具体实现细节,从而隔离了复杂度
class Car:
def __init__(self, brand):
self.brand = brand
def start(self): # 实例方法
print('汽车已启动')
car = Car('宝马X5')
car.start()
print(car.brand)
--------------------------------
点击代码行处的”-“时class Car这个类相关内容就变成了"...",即进行了封装
- 在Python中没有专门的修饰符用于属性的私有,如果该属性不希望在类对象外部被访问,前边使用两个“—”。
class Student:
def __init__(self, name, age):
self.name = name
self.__age = age # 年龄不希望在类的外部使用,所以加了两个"_"
def show(self):
print(self.name, self.__age)
stu = Student('张三', 20)
stu.show()
# 在类的外部使用name与age
print(stu.name)
# print(stu.__age)报错的原因是由于age在类属性中设置了两个'_',禁止在类的外部使用
# 查阅age的方法
# print(dir(stu)) # dir()获取实例对象中所有的属性
print(stu._Student__age) # 使用dir()函数所获取的有关age的属性可以通过属性_Student__age进行访问age
---------------------------------------------------------
张三 20
张三
20
继承:提高代码的复用性
- 语法格式
class 子类类名(父类1, 父类2...):
pass
eg:
该关系图谱中,爬行动物是鳄鱼和蛇的父类,动物又是爬行动物的父类;通过这种形式来了解继承特征
- 如果一个类没有继承任何类,则默认继承object
class Person(object): # Person继承object类,通常object可省略;也就是我们常见的class Person:来定义类
def __init__(self, name, age):
self.name = name
self.age = age
def info(self):
print(self.name, self.age)
# 定义子类
class Student(Person):
def __init__(self, name, age, stu_no):
super().__init__(name, age)
self.stu_no = stu_no
class Teacher(Person):
def __init__(self, name, age, teach_year):
super().__init__(name, age)
self.teach_year = teach_year
stu = Student('张三', 20, '1001')
teacher = Teacher('李四', 30)
stu.info()
teacher.info()
--------------------------------------
张三 20
李四 30
上述代码继承关系为:
- Python支持多继承
# 多继承
class A(object):
pass
class B(object):
pass
class C(A, B):
pass
- 定义子类时,必须在其构造函数中调用父类的构造函数
方法重写
- 如果子类对继承自父类的某个属性或方法不满意,可以在子类中对其(方法体)进行重新编写
- 子类重写后的方法中可以通过super.xxx()调用父类中被重写的方法
class Person(object): # Person继承object类,通常object可省略;也就是我们常见的class Person:来定义类
def __init__(self, name, age):
self.name = name
self.age = age
def info(self):
print(self.name, self.age)
# 定义子类
class Student(Person):
def __init__(self, name, age, stu_no):
super().__init__(name, age)
self.stu_no = stu_no
def info(self):
super().info() # 调用object类中的 print(self.name, self.age)
print('学号为', self.stu_no)
class Teacher(Person):
def __init__(self, name, age, teach_year):
super().__init__(name, age)
self.teach_year = teach_year
def info(self):
super().info()
print('教龄为', self.teach_year)
stu = Student('张三', 20, '1001')
teacher = Teacher('李四', 30, 10)
stu.info()
print('-'*50)
teacher.info()
---------------------------------------
张三 20
学号为 1001
--------------------------------------------------
李四 30
教龄为 10
上述代码中的学号和教龄就是通过方法重写来实现父类中不存在而子类中需要的属性
object类
- object类是所有类中的父类,因此所有类都有object类的属性和方法。
- 内置函数dir()可以查看指定对象的所有属性
- Object有一个_ _ str _ _()方法,用于返回一个对于‘’对象的描述‘’,对应于内置函数str()经常用于print()方法,帮我们查看对象的信息,所以我们经常会对 _ _ str _ _()进行重写
class Student:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return'我的名字是{0},今年{1}岁啦'.format(self.name, self.age)
stu = Student('张三', 20)
print(dir(stu))
print(stu) # 默认会调用__str__()这样的方法
--------------------------------------------------------
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'age', 'name']
我的名字是张三,今年20岁啦
多态:提高程序的可扩展性和可维护性
-
简单地说,多态就是‘’具有多种形态‘’,它指的是:即便不知道一个变量所引用的对象到底是什么类型,任然可以通过这个变量调用方法,在运行过程中根据变量所引用对象的类型,动态决定调用哪个对象中的方法
-
静态语言和动态语言关于多态的区别
静态语言(例如Java)实现多态的三个必要条件:继承、方法重写、父类引用指向子类对象
- 动态语言的多态崇尚‘’鸭子类型‘’当看到一直鸟走起来像鸭子、游泳起来像鸭子,那么这只鸟就可以被称为鸭子。在鸭子类型中,不需要关心对象是什么类型,到底是不是鸭子,只关心对象的行为。
**注意:**静态语言(如Java)实现多态要求满足三个必要条件;但Python是动态语言,因此实现多态时鸭子类型就可以