一、封装
私有化
封装:
1、私有化属性
2、定义公有的set和get方法
__属性:将属性私有化,访问范围仅仅限于类中
优点:
1、隐藏属性,不被外界随意修改
2、也可以修改,通过函数
def setXXX(self, xxx):
3、筛选赋值的内容
if xxx是否符合条件:
赋值
else:
不赋值
4、如果想获取具体的某一个属性
使用get函数
def getXXX(self):
return self.__xxx
attribute setName getName setAge getAge
在开发中,看到一些私有化处理:装饰器
class Student:
# __age = 18 #类属性
def __init__(self, name, age):
self.name = name
self.__age = age
self.__score = 59
def __str__(self):
return '姓名{},年龄{},考试分数{}'.format(self.name, self.__age, self.__score)
#旧版set、get方法
#定义公有的set和get方法
#set是为了赋值
# def setAge(self, age):
# if age > 0 and age < 120:
# self.__age = age
# else:
# print("年龄不在规定范围内")
# #get是为了取值
# def getAge(self):
# return self.__age
#新版
#先定义get的xxx,再有xxx.set,因为set依赖get
@property
def age(self):
return self.__age
@age.setter
def age(self, age):
if age > 0 and age < 100:
self.__age = age
else:
print("年龄赋值错误")
#旧版
s = Student('name1', 18)
print(s)
# s.setAge(20)
# print(s)
print(dir(Student)) #获取类中所有属性
print(s.__dir__()) #获取类中所有属性,包括私有
print(s._Student__age) #系统自动将私有属性改名, _Student__age其实就是__age
print(__name__)
print("*" * 80)
#新版
s1 = Student('name333', 15)
print(s1.name)
#私有化的赋值
# s1.setAge(30)
# print(s1.getAge())
print(s1.age)
二、继承
继承: is a, has a
例如:
公路(Road) 属性:公路名称、公路长度
车(Car) 属性:车名、时速
方法:
1、求车名在那条公路上以多少的时速行驶了多长get_time(self, road)
2、初始化车属性信息 __init__方法
3、打印对象显示车的属性信息
1、has a 包含, 类中有...
1)、一个类中使用了另外一种自定义的类型
2)、类型:
系统类型:
str int float
list dic tuple set
自定义类型:
自定义的类,都可以将其当成一种类型
s = Student()
s是Student类型的对象
import random
class Road:
def __init__(self, name, len):
self.name = name
self.len = len
class Car:
def __init__(self, road, brand, speed):
self.road = road
self.brand = brand
self.speed = speed
def get_time(self): #road 与 r指向同一个地址空间
ran_time = random.randint(1, 10)
msg = '{}品牌的车在{}上,以{}的时速行驶{}时间'.format(self.brand, self.road.name, self.speed, ran_time)
print(msg)
def __str__(self):
return '{}品牌的,速度{}'.format(self.brand, self.speed)
#创建实例化对象
r = Road("青藏公路", 12000)
c = Car(r, "奥迪", 120) #此处 Car类中使用了另一个自定义类Road 为 has a
print(c)
c.get_time()
2、is a base class 基类 父类
父类 子类
ValueError Exception BaseException
Student, Employee, Doctor 都属于人类
相同代码--->代码冗余,可读性不高
将相同代码提取--->Person类
Student, Employee, Doctor 继承 Person
父类
class Person:
pass
子类
class Student(Person):
pass
特点:
1、如果类中不定义__init__,默认调用父类 super class的__init__
2、如果类继承父类,也需要定义自己的__init__,就需要在子类__init__中
调用父类的__init__
3、如何调用父类__init__:
super().__init__(参数)
super(类名, self).__init__(参数)
4、如果父类有eat(),子类也定义一个eat()方法,搜索的原则:
先找当前类,没有再去找父类
override 重写(覆盖)
父类提供的方法,不能满足子类的需求,就需要在子类中定义一个同名的方法,
这种行为为:重写
5、子类的方法中,也可以调用父类的方法
super().方法名(参数)
#将每个类共同的属性和方法提取出来
class Person:
def __init__(self, name, age):
self.name = name
self.age = 20
print("------> Person的init")
def run(self):
print("{}正在跑步".format(self.name))
def eat(self):
print("{}正在吃饭".format(self.name))
class Student(Person):
def __init__(self, name, age, clazz):
print('--->Student的init')
#如何调用父类__init__ super() 父类对象
super().__init__(name, age)
self.clazz = clazz
def study(self, course):
print("{}正在学习{}课程".format(self.name, course))
#子类中与父类同名的方法,直接调用自己的方法,优先找自己的方法,不去找父类的方法
def eat(self, food):
super().eat() #先调用父类的代码
print("{}正在吃饭,喜欢吃{}".format(self.name, food))
class Employee(Person):
def __init__(self, name, age, salary, manager):
super().__init__(name, age)
self.salary = salary
self.manager = manager
class Doctor(Person):
def __init__(self, name, age, patient):
super(Doctor, self).__init__(name, age)
self.patient = patient
s = Student("stu", 20, "一年级")
s.run()
s.study('python')
s.eat('满汉全席')
e = Employee('ee', 40, 10000, 'king')
e.run()
list1 = ['aaa', 'bbb', 'ccc']
d = Doctor('d', 40, list1)
d.run()
3、多继承
python允许多继承
def 子类(父类1, 父类2, ...)
类名.__mro__ 输出搜索顺序
import inspect
inspect.getmro(类名)
如果父类中有相同名称的方法,搜索顺序 经典类 新式类
python2.7 -- 从左至右,深度优先 一个父类搜索完再搜索其它的父类
python3 -- 广度优先 现在执行的环境 子类所有父类,其中一个父类所有父类...
class Base:
def test(self):
print("-------Base---------")
class A(Base):
def test(self):
print("--->AAAAAAA")
class B(Base):
def test(self):
print("--->BBBBBB")
class C(Base):
def test(self):
print("------>CCCCCC")
class D(A, B, C):
pass
c = C()
c.test() #输出:------>CCCCCC
d = D()
d.test()
print(D.__mro__) #查看搜索顺序
import inspect
print(inspect.getmro(D)) #查看继承搜索顺序
三、多态
class Person:
def __init__(self, name):
self.name = name
def feed_pet(self, pet): #既可以接收cat,也可以接收dog,还可以接受tiger
# isinistance(obj, 类) --->验证obj是不是类的对象,或者判断obj是不是该类子类的对象
if isinstance(pet, Pet):
print("{}喜欢养宠物:{},暱称是{}".format(self.name,pet.role, pet.nickname))
else:
print("不是宠物")
#宠物
class Pet:
role = "宠物"
def __init__(self, nickname, age):
self.nickname = nickname
self.age = age
def show(self):
print("暱称是:{}, 年龄:{}".format(self.nickname, self.age))
class Cat(Pet):
role = "猫"
def catch_mouse(self):
print("抓老鼠")
class Dog(Pet):
role = "狗"
def watch_house(self):
print("看门")
class Tiger:
def eat(self):
print("吃人")
#创建对象
cat = Cat('小猫', 2)
dog = Dog('小狗', 3)
tiger = Tiger()
p = Person('人')
p.feed_pet(cat)
p.feed_pet(tiger)
Pet
pet 父类 cat dog 子类
pet 大类型 cat dog 小类型
四、总结
面向对象的特点:
封装、继承、多态
1、封装:
私有化属性,定义公有set和get方法
class Student:
def __init__(self, age):
self.__age = age
@property
def age(self):
return self.__age
@age.setter
def age(self, age)
self.__age = age
s = Student()
s.age = 10
继承:
父类中的私有属性,子类无法继承
is a:
父类(提取出来的共同的特征) 子类
class Student(Person):
pass
has a:
class Student:
def __init__(self, 参数)
参数是自定义类型
s = Student()
多继承:
class C(A, B):
pass
C.__mro__ 查看搜索顺序
多态:
class Person:
def feed_pet(self, pet) #只要是pet的子类,都可以
if isinstance(pet, Pet):
pass