基本过程:
面向对象的程序设计
如何使用类:
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 的广度优先的类