一、面向对象
1.简单介绍
"""
面向过程:怎么做
面向对象:谁来做
1.确定职责 -- 要做的事(方法)
2.对象内部封装不同方法(多个)
3.不同对象调用不同方法
类 对象
类:模板,对象都是根据这个模板创建出来的
类只需要有一个,对象可以有多个
类:属性(信息)和方法(你能干什么)
1.类名
2.属性
3.方法
面向对象的程序设计的
优点是:解决了程序的扩展性。对某一个对象单独修改,会立刻反映到整个体系中,如对游戏中一个人物参数的特征和技能修改都很容易。
缺点:可控性差,无法向面向过程的程序设计流水线式的可以很精准的预测问题的处理流程与结果,面向对象的程序一旦开始就由对象之间的交互解决问题,即便是上帝也无法预测最终结果。于是我们经常看到一个游戏人某一参数的修改极有可能导致阴霸的技能出现,一刀砍死3个人,这个游戏就失去平衡。
应用场景:需求经常变化的软件,一般需求的变化都集中在用户层,互联网应用,企业内部软件,游戏等都是面向对象的程序设计大显身手的好地方。
面向过程的程序设计的核心是过程(流水线式思维),过程即解决问题的步骤,面向过程的设计就好比精心设计好一条流水线,考虑周全什么时候处理什么东西。
优点是:极大的降低了写程序的复杂度,只需要顺着要执行的步骤,堆叠代码即可。
缺点是:一套流水线或者流程就是用来解决一个问题,代码牵一发而动全身。
应用场景:一旦完成基本很少改变的场景,著名的例子有Linux內核,git,以及Apache HTTP Server等。
"""
"""
例:小猫爱吃鱼,小猫要喝水
self:哪一个对象调用的方法,self就是哪个对象的引用
"""
class Cat():
def eat(self):
print('%s爱吃鱼' %self.name)
def drink(self):
print('小猫要喝水')
tom = Cat()
tom.name = 'Tom'
tom.drink()
tom1 = Cat()
# print(tom1)
tom1.drink()
print(id(tom))
print(id(tom1)) ##查看两个调用类方法的地址,虽然输出内容相同,但是地址不同
2.类和实例化
"""
1.如何定义类 class 类名(): pass
2.类创建对象的过程称为实例化,把抽象的类具体化
对象名 = 类名(参数1、参数2...参数n)
"""
#类:模板
class People():
#属性:类中的变量
name = 'yy'
age = 21
#方法:类中的函数
def eat(self):
print('吃东西')
def sleep(self):
print('睡觉中')
#实例化:通过类创建对象
p1 = People()
p2 = People()
print(p1.name)
print(p2.name)
#在实例化后调用类中的方法
p1.eat()
p2.sleep()
3.类和属性
class People():
#构造方法:
def __init__(self): ##一般常用为self,也可以自己定义名称
print('self',self)
p1 = People()
print('p1',p1) ##可以看出self就是调用的对象本身,地址是相同的
二、面向对象的三个基本特征
1.封装
#封装就是把同一类型的东西放在一起,通过self.xxx去调用
class People():
def __init__(self,name,age):
#类里的self实质就是对象本身
#self是对象,name是属性,self.name就是将对象和属性封装在一起
self.name = name
self.age = age
def run(self):
print('%s正在跑步' %(self.name))
def year(self):
print('%s今年%s岁了' %(self.name,self.age))
p1 = People('yy',21) ##定义了两个属性时,即使只用到其中一个,但是两个值都得有输入
p1.run()
p2 = People('zz',18)
p2.year()
2.继承
"""
定义一个类,可以从现有的某个类继承
新的类称为子类、扩展类(Subclass),被继承的称为父类、基类、超类
(Baseclass、Superclass)
"""
'''(1)'''
class Father():
def __init__(self,name,age):
#构造方法在实例化对象时自动执行
self.name = name
self.age = age
def eat(self):
print('%s正在吃东西' %(self.name))
def sleep(self):
print('%s正在睡觉' %(self.name))
#实例化对象默认执行构造方法,子类没有的方法会调用父类的
class Son(Father):
def eat(self):
#Father.eat(self) ##子类与父类方法相同时,先调用父类方法,再调用子类方法,一般用第二种方法,因为它没有调用父类名称
super(Son,self).eat() ##子类与父类方法相同时,先调用父类方法,再调用子类方法
print('%s没有吃饭' %(self.name))
father = Father('yy',21)
son = Son('y',18)
#子类中有与父类相同的方法时,默认调用的是子类中的方法
son.eat()
#子类中没有,会自己调用父类方法
son.sleep()
'''2.继承具有传递性,子类可以调用父类的父类的属性和方法'''
class Animal():
def eat(self):
print('吃鱼')
def drink(self):
print('喝水')
def sleep(self):
print('睡觉')
class Cat(Animal):
def yell(self):
print('喵~')
class Jiqimao(Cat):
def speak(self):
print('我会说话')
jqm = Jiqimao()
jqm.speak()
jqm.yell()
jqm.eat()
'''3.多个父类的继承,类中的方法相同时,谁写在前面先继承谁,第一个中没有才会继承第二个父类'''
class A():
def test(self):
print('A --- test方法')
def demo1(self):
print('A --- demo1方法')
class B():
def test(self):
print('B --- test方法')
def demo(self):
print('B --- demo方法')
class C(A,B):
pass
c = C()
c.test()
c.demo()
3.str方法
class People():
def __init__(self,name):
self.name = name
def __str__(self):
##必须返回一个字符串
return '我是%s' %(self.name)
p1 = People('yy')
print(p1)
举个简单的应用例子:
"""
题目要求1:
1.小明体重75.0公斤
2.小明每次跑步会减肥0.5公斤
3.小明每次吃东西体重会增加1公斤
题目要求2:
1.小明和小美都爱跑步
2.小美体重45.0公斤
3.小明体重75.0公斤
4.每次跑步都会减少0.5公斤
5.每次吃东西都会增加1公斤
"""
class People():
def __init__(self,name,weight):
self.name = name
self.weight = weight
def __str__(self):
return '我的名字叫%s,体重是%.2f' %(self.name,self.weight)
def run(self):
print('%s爱跑步' %(self.name))
self.weight -= 0.5
def eat(self):
print('%s吃东西' %(self.name))
self.weight += 1
yy = People('小明',75)
yy.run()
print(yy)
zz = People('小美',45)
zz.eat()
print(zz)
4.多态性
"""
对扩展开放:允许子类重写方法
对修改封闭:不修改,直接继承父类方法
"""
class Student():
def get_score(self):
print('获取学生成绩')
class Chinese():
def get_score(self):
print('获取语文成绩')
class Math():
def get_score(self):
print('获取数学成绩')
student1 = Student()
student2 = Chinese()
student3 = Math()
student1.get_score()
student2.get_score()
student3.get_score()
5.类属性类方法
"""
类属性:使用赋值语句在class关键字下定义
类方法:在类内部可以直接访问类属性或者其他类方法
类方法由类调用,至少一个cls参数,并且需要装饰器@classmethod修饰
cls指向当前的类对象,类对象不等于实例对象,类对象和实例对象都有单独的内存空间存储,
当调用一个含有@classmethod装饰的方法,则会先加载这个类的内存空间
"""
class Student(object):
count = 0
def __init__(self,name):
self.name = name
Student.count += 1
@classmethod
def Show_Student_count(awda): ##一般为self,但是也可以是自己定义的,函数内应该统一这个名称
print('学生数量为 %d' %(awda.count)) ##这里的awda.count实际上就是Student.count,但是不等同
student1 = Student('小明')
student2 = Student('小美')
Student.Show_Student_count()
6.静态方法
"""
静态方法由类调用,不需要参数,需要装饰器@staticmethod修饰
静态方法不不要使用实例对象的属性方法也不需要使用类对象的属性所有无论往静态方法中传一个self还是cls都会加载对应的资源,
而静态方法又不使用,所有为了节省资源静态方法就应运而生
"""
class Cat(object):
@staticmethod
def call():
print('喵~')
Cat.call()
7.私有属性和私有方法
"""
Python默认的成员函数和成员变量都是公开的,
在Python中定义私有变量只需要在变量名或函数名前加上 "__"两个下划线,那么这个函数或变量就会为私有的了
若声明该方法为私有方法,则不能在类的外部调用
"""
class Women():
def __init__(self,name):
self.name = name
self.__age = 18
def __secret(self):
print('%s的年龄是%d' %(self.name,self.__age))
lily = Women('lily')
print(lily.name)
# print(lily.__age) ##私有属性不能在外部访问,会报错
lily.__secret() ##在外部调用私有方法也会报错
"""
通过内部调用私有方法可以让外部看到私有属性
"""
class Student(object):
def __init__(self,name,score):
self.__name = name
self.__socre = score
def get_name(self):
return self.__name
def get_score(self):
return self.__socre
tom = Student('Tom',89)
print(tom.get_score())
print(tom.get_name())