python进阶-面向对象编程:类和对象一:抽象类/接口/继承组合/封装/多态
基本过程:
面向对象的程序设计 如何使用类: 1,实例化 2,引用类的特征(变量)和技能(函数) 如何使用类: 1,实例化 2,引用名(类名.变量名,类名.函数名) 3,实例(实例.类变量,实例.绑定类函数名)
# 面向对象的程序设计: # 找对象---》归纳对象共同的特征与技能,还有每个对象独有的特征---》抽象成类 # 面向对象编程: # 定义类---》实例化对象
看一个学生类简单例子
class Student:
country = 'china'
def __init__(self,ID,NAME,SEX,PROVINCE,score):
self.id = ID
self.name = NAME
self.sex = SEX
self.province = PROVINCE
self.score = score
def search_score(self):
print(self.name,"的分数是",self.score)
def study(self):
print(self.name,"study")
def walk(self):
print(self.name,"walk")
def attack(self):
print("attack")
#类的变量
print(Student.country)
Student.x=100
print(Student.x)
# china
# 100
#对象,查询,绑定方法的含义就是,谁调用就是作用谁
s1 =Student('37232323','ddamanter','male','广东省',98)
print(s1)#查看对象 <__main__.Student object at 0x1068e82b0>
print("Student.__dict__:",Student.__dict__) #查看类的名称空间,以字典的形式包含类的所有属性:变量和方法以及内置函数
# Student.__dict__: {'study': <function Student.study at 0x1058e2b70>,
# 'x': 100, '__weakref__': <attribute '__weakref__' of 'Student' objects>,
# 'search_score': <function Student.search_score at 0x1058e2a60>,
# '__dict__': <attribute '__dict__' of 'Student' objects>,
# 'walk': <function Student.walk at 0x1058e2bf8>,
# '__init__': <function Student.__init__ at 0x1058e2ae8>,
# '__doc__': None, 'attack': <function Student.attack at 0x1058e2c80>,
# 'country': 'china', '__module__': '__main__'}
print("s1.__dict__:",s1.__dict__) #查看对象的名称空间,以字典的形式包含对象的所有属性
# s1.__dict__: {'score': 98, 'sex': 'male', 'id': '37232323', 'province': '广东省', 'name': 'ddamanter'}
print(s1.country)
print(s1.id)
print(s1.name)
print(s1.sex)
print(s1.province)
print(s1.search_score())
print(s1.study())
print(s1.walk())
# china
# 37232323
# ddamanter
# male
# 广东省
# ddamanter 的分数是 98
# None
# ddamanter study
# None
# ddamanter walk
#增加
s1.height="178cm"
s1.weight="70kg"
s1.age="23"
print(s1.height)
print(s1.weight)
print(s1.age)
# 178cm
# 70kg
# 23
#删除
# del s1.weight
# print(s1.weight)
#修改
s1.height="180cm"
print(s1.height)
一个系统例子
class School:
tag="school"
def __init__(self,addr):
self.addr=addr
self.teacher_list=[]
self.course_list=[]
def admissions(self):
print("招生")
class Teacher:
nationality = "china"
school="peking university"
def __init__(self,t_name,t_class,t_lesson):
self.name=t_name
self._class=t_class
self.lesson=t_lesson
def teach(self):
print("teach",self)
class Student:
nationality = "china"
school = "peking university"
def __init__(self,id,name,sex):
self.id=id
self.name=name
self.sex=sex
self.course_list=[]
def search_score(self):
print("view grades:",self)
def handin(self):
pass
class Course:
def __init__(self,name,price,period):
self.name=name
self.price=price
self.period=period
python_obj=Course('python',20000,'1years')
linux_obj=Course('python',20000,'1years')
s1=Student("001","ada","男")
s1.course_list.append(python_obj)
print("课程名:%s \n课程价格:%s \n课程时间:%s"%(s1.course_list[0].name,s1.course_list[0].price,s1.course_list[0].period))
什么是抽象类以及特点
import abc
# 什么是抽象类:接口只能提供功能的集合,抽象类:本质还是类,
# 与普通类额外特点是:加了装饰器@abc.abstractmethod的函数,所有子类必须实现装饰器的方法
class Animal(metaclass=abc.ABCMeta):
tag="hello"
@abc.abstractmethod
def eat(self):
pass
@abc.abstractmethod
def run(self):
pass
class People(Animal):
def eat(self):
print("peple eat")
def run(self):
print("peple run")
基于抽象类的接口与归一化设计
# java 有接口,功能的集合,利用interface ,implament实现,
# python 没有,是模仿,但是一般自己的定义都能用
# 接口提取了一堆函数。是函数的集合
# 接口的意义就是必须实现接口内的所有方法
class Animal:
def eat(self):
raise AttributeError("子类必须使用该方法")
def run(self):
pass
class People(Animal):
def eat(self):
print("peple eat")
def run(self):
print("peple run")
面向对象编程的三大特点:封装,继承,多态
类的继承和派生以及组合:
为什么要用继承:解决代码重用问题
# 关联类的继承,是一种什么是什么的关系,比如人是动物,用继承
# 非关联类,是一种什么有什么有什么的关系,比如学生有课程,老师有课程,用类之间的组合
# 英雄的昵称,攻击力,生命值 class Hero: def __init__(self,nickname,agressivity,life_value): self.nickname=nickname self.agressivity=agressivity self.life_value=life_value def attack(self): print("Hero attck") # 具体英雄的昵称,攻击力,生命值,台词 class Garen(Hero): def __init__(self,nickname,agressivity,life_value,script): # Hero.__init__(self,nickname,agressivity,life_value) super(Garen,self).__init__(nickname,agressivity,life_value) #以上两种初始化父类的方法都可以,推荐后一种 self.script=script def attack(self,enemy): Hero.attack(enemy) print("%s attck %s"%(self.nickname,enemy)) class Alex(Hero): def __init__(self,nickname,agressivity,life_value,script): Hero.__init__(self,nickname,agressivity,life_value) self.script=script def attack(self,enemy): Hero.attack(enemy) print("%s attck %s" % (self.nickname,enemy)) g1=Garen("Garen",20,200,"我是盖伦") a1=Alex("Alex",10,300,"我是亚历山大") print(Hero.__bases__) print(Garen.__bases__) # (<class 'object'>,) # (<class '__main__.Hero'>,) print(g1.attack(a1.nickname)) print(g1.script) # Hero attck # Garen attck Alex # None
# 解决非关联类,是(有) 的关系,使用代码重用,用继承不能实现,要用组合,将一个类作为另一个类的输入
# 老师、学生与课程
class Teacher:
def __init__(self,name,sex,course):
self.name=name
self.sex=sex
self.course=course
class Student:
def __init__(self,name,sex,course):
self.name=name
self.sex=sex
self.course=course
class Course:
def __init__(self,course_name,course_price,course_period):
self.course_name=course_name
self.course_price=course_price
self.course_period=course_period
python_obj=Course("python",20000,"7m")
t1=Teacher("alex","male",python_obj)
s1=Student("adamander","male",python_obj)
print(t1.__dict__)
print(s1.__dict__)
# {'name': 'alex', 'sex': 'male', 'course': <__main__.Course object at 0x1036014e0>}
# {'name': 'adamander', 'sex': 'male', 'course': <__main__.Course object at 0x1036014e0>}
# 非关联类老师、学生与生日
class Teacher:
def __init__(self,name,sex,birth):
self.name=name
self.sex=sex
self.birth=birth
class Student:
def __init__(self,name,sex,birth):
self.name=name
self.sex=sex
self.birth=birth
class Birth:
def __init__(self,birth_date,birth_gift,birth_cake):
self.birth_date=birth_date
self.birth_gift=birth_gift
self.birth_cake=birth_cake
birth_obj=Birth("11月11号","bmw car","banana cake")
t2=Teacher("alex","male",birth_obj)
s2=Student("adamander","male",birth_obj)
print(t2.__dict__)
print(s2.__dict__)
# {'name': 'alex', 'birth': <__main__.Birth object at 0x103601588>, 'sex': 'male'}
# {'name': 'adamander', 'birth': <__main__.Birth object at 0x103601588>, 'sex': 'male'}
类的封装
# 第一个层面的封装(什么都不用做): # 创建类和对象会分别创建二者的名称空间,我们只能用类名.或者obj.的方式去访问里面的名字,这本身就是一种封装 # 注意:对于这一层面的封装(隐藏),类名.和实例名.就是访问隐藏属性的接口 # 第二个层面的封装:类中把某些属性和方法隐藏起来(或者说定义成私有的), # 只在类的内部使用、外部无法访问,或者留下少量接口(函数)供外部访问。 # 在python中用双下划线的方式实现隐藏属性(设置成私有的),单下划线是保护变量 # 对于这一层面的封装(隐藏),我们需要在类中定义一个函数(接口函数)在它内部访问被隐藏的属性,然后外部使用接口函数 # 在继承中,父类如果不想让子类覆盖自己的方法,可以将方法定义为私有的 # 为什么要用property # 将一个类的函数定义成特性以后,对象再去使用的时候obj.name,本来是obj.name(), # 用了@property这个装饰器以后,只需要obj.name # 用户根本无法察觉自己的name是执行了一个函数然后计算出来的, # 这种特性的使用方式遵循了统一访问的原则,大概是类似统一访问属性这种
类的多态
# 多态和多态性:
# 多态:一种事物有多种形态,比如一个抽象类有多个子类,动物的多态:人,牛,羊,狗
# 多态性:具有不同功能的函数可以使用相同的函数名
# 同一种行为叫:人的叫,狗的叫,猫的叫
import abc
class Animal(metaclass=abc.ABCMeta):
@abc.abstractmethod
def talk(self):
pass
class Peoole(Animal):
def talk(self):
print("people talk")
class Sheep(Animal):
def talk(self):
print("sheep talk")
class Cow(Animal):
def talk(self):
print("cow talk")
c=Cow()
s=Sheep()
p=Peoole()
# 多态性:具有不同功能的函数可以使用相同的函数名
def func(animal):
animal.talk()
func(c)
func(s)
func(p)
# 多态的好处:
# 1.增加了程序的灵活性
# 以不变应万变,不论对象千变万化,使用者都是同一种形式去调用,如func(animal)
# 2.增加了程序额可扩展性
# 通过继承animal类创建了一个新的类,使用者无需更改自己的代码,还是用func(animal)去调用
接口函数隐藏访问内部隐藏属性
# 接口函数访问内部隐藏数据属性
# class A:
# def __init__(self):
# self.__x=1
# def tell(self):
# print(self.__x)
# a=A()
# a.tell()
# 接口函数访问内部隐藏函数属性
class A:
def __fa(self):
print("hello word class A")
def test(self):
print(self.__fa())
class B(A):
def hello(self):
print("B")
b=B()
b.test()
经典类和新式类
经典类是py2 的深度优先的类
新式类是py3 的广度优先的类

浙公网安备 33010602011771号