1.面向对象(上)
1.1定义
- 面向对象编程:oop [object oriented programming] 是一种python的编程思路;
- 面向过程:就是我们一开始学习的,按照解决问题的步骤去写代码 【根据业务逻辑去写代码】,在思考问题的时候, 首先分析’怎么按照步骤去实现’ 然后将问题解决拆解成若干个步骤,并将这些步骤对应成方法一步一步的 最终完成功能。
- 面向对象:关注的是设计思维【找洗车店 给钱洗车】
1.2类和对象
类和对象
类:类是具有一组 相同或者相似特征【属性】和行为【方法】的一系列[多个]对象组合
现实世界 计算机世界
行为---------> 方法
特征---------->属性
对象: 对象是实实在在的一个东西,类的实例化,具象化
类是对象的抽象化 而对象是类的一个实例
1.3定义类和创建对象、实例方法和属性、init方法
实例方法:在类的内部,使用def 关键字来定义 第一个参数默认是 self
【名字标识可以是其他的名字,但是这个位置必须被占用】
实例方法是归于 类的实例所有
属性:类属性 实例属性
在类的内部定义的变量【类属性】
在方法内部定义的【通过类似于self.变量名】 变量,是实例属性
class Person:
'''
对应人的特征
'''
age=20
'''
对应人的行为 实例方法
'''
def __init__(self):
self.name='小明'
pass
def eat(parms):
print("大口的吃饭")
pass
def run(self):
print('飞快的跑')
pass
pass
def printInfo():
'''
普通方法
:return:
'''
pass
xm=Person()
xm.eat()
xm.run()
print("{}的年龄是:{}".format(xm.name,xm.age))
xw=Person()
xw.eat()
1.4 init方法
class Pepole:
def __init__(self,name,sex,age):
'''
实例属性的声明
'''
self.name=name
self.sex=sex
self.age=age
pass
def eat(self,food):
'''
吃的行为
:return:
'''
print(self.name+'喜欢吃'+food)
pass
zp=Pepole('张鹏','男生',18)
print(zp.name,zp.age)
zp.eat('香蕉')
lh=Pepole('李辉','男生',28)
lh.eat('苹果')
print(lh.name,lh.age)
xh=Pepole('小花','女生',20)
xh.eat('橘子')
print(xh.name,xh.age)
1.5 self理解
小结 self特点
self只有在类中定义 实例方法的时候才有意义,在调用时候不必传入相应的参数 而是由解释器 自动去指向;![在这里插入图片描述](https://img-blog.csdnimg.cn/6021b15274424412930d9e9cfee67965.png)
self的名字是可以更改的 可以定义成其他的名字,只是约定俗成的定义成了 self
self 指的是 类实例对象本身, 相当于java中 this
class Person:
def __init__(self,pro,name,food):
'''
:param pro: 专业
:param name: 姓名
:param food: 食物
'''
self.pro=pro
self.name=name
self.food=food
print('----init-----函数执行')
pass
'''
定义类
'''
def eat(self,name,food):
'''
实例方法
:return:
'''
print('%s 喜欢吃 %s 修的专业是:%s'%(self.name,self.food,self.pro))
pass
pass
xw=Person('心理学','小王','榴莲')
print(xw)
1.6 魔术方法
- 定义:
class Person:
def __init__(self,pro,name,food):
'''
:param pro: 专业
:param name: 姓名
:param food: 食物
'''
self.pro=pro
self.name=name
self.food=food
print('----init-----函数执行')
pass
'''
定义类
'''
def eat(self,name,food):
'''
实例方法
:return:
'''
print('%s 喜欢吃 %s 修的专业是:%s'%(self.name,self.food,self.pro))
pass
def __str__(self):
'''
打印对象 自定义对象 是内容格式的
:return:
'''
return '%s 喜欢吃 %s 修的专业是:%s'%(self.name,self.food,self.pro)
pass
def __new__(cls, *args, **kwargs):
'''
创建对象实例的方法 每调用一次 就会生成一个新的对象 cls 就是class的缩写
场景:可以控制创建对象的一些属性限定 经常用来做单例模式的时候来使用
:param args:
:param kwargs:
'''
print('----new-----函数的执行')
return object.__new__(cls)
pass
pass
xw=Person('心理学','小王','榴莲')
print(xw)
2.面向对象(中)
2.1析构方法
class Animal:
def __init__(self,name):
self.name=name
print('这是构造初始化方法')
pass
def __del__(self):
print('当在某个作用域下面 没有被使用【引用】的情况下 解析器会自动的调用此函数 来释放内存空间')
print('这是析构方法')
print('%s 这个对象 被彻底清理了 内存空间也释放了'%self.name)
pass
cat=Animal('小花猫')
print(cat.name)
input('程序等待中.....')
2.2单继承
class Animal:
def eat(self):
'''
吃
:return:
'''
print('吃饭了')
pass
def drink(self):
'''
喝
:return:
'''
pass
class Dog(Animal):
def wwj(self):
'''
子类独有的实现
:return:
'''
print('小狗汪汪叫')
pass
class Cat(Animal):
def mmj(self):
'''
子类独有的实现
:return:
'''
print('小猫喵喵叫')
pass
d1=Dog()
d1.eat()
d1.wwj()
print('**************cat 的行为**********************')
c1=Cat()
c1.eat()
c1.mmj()
2.3多继承
注:# 问题是 当多个父类当中存在相同方法的时候 应该去调用哪一个呢? 答:广度优先/(print(A.mro) #可以显示类的依次继承关系)
class shenxian:
def fly(self):
print("神仙都会飞")
pass
class Monkey:
def chitao(self):
print('猴子喜欢吃桃')
pass
class Sunwukong(shenxian,Monkey):
pass
class D(object):
def eat(self):
print('D.eat')
pass
pass
class C(D):
def eat(self):
print('C.eat')
pass
pass
class B(D):
pass
class A(B,C):
pass
a=A()
a.eat()
print(A.__mro__)
2.4间接继承
class GrandFather:
def eat(self):
print('吃的 方法')
pass
pass
class Father(GrandFather):
pass
class Son(Father):
pass
son=Son()
print(Son.__mro__)
son.eat()
2.5重写和调用父类方法
- 所谓重写,就是子类中,有一个和父类相同名字的方法,在子类中的方法会覆盖掉父类中同名的方法
- 为什么要重写, 父类的方法已经不满足子类的需要,那么子类就可以重写父类或者完善父类的方法
class Dog:
def __init__(self,name,color):
self.name=name
self.color=color
def bark(self):
print('汪汪叫....')
pass
pass
class kejiquan(Dog):
def __init__(self,name,color):
super().__init__(name,color)
self.height=90
self.weight=20
pass
def __str__(self):
return '{}的颜色会{} 它的身高是{}cm 体重是:{}'.format(self.name,self.color,self.height,self.weight
)
def bark(self):
super().bark()
print('叫的跟神一样')
print(self.name)
pass
kj=kejiquan('柯基犬','红色')
kj.bark()
print(kj)
注: super是自动找到父类 进而调用方法
2.6 类属性和实例属性
注: 类属性 就是类对象所拥有的属性(类对象不同于实例对象,这里和java有点不同,这里所说的类对象应该就是java里面的元对象)
- 小结
- 类属性是可以 被类对象和实例对象共同访问使用的
- 实例属性只能由实例对象所访问
class Student:
name='李明'
def __init__(self,age):
self.age=age
pass
@staticmethod
def aaa(x,y):
print(x+y)
pass
Student.name='李易峰'
lm=Student(18)
print(lm.name)
print(lm.name)
print(lm.age)
Student.aaa(4,6)
print('---------xh的数据---------------')
xh=Student(28)
print(xh.name)
print(xh.age)
print('---------通过类对象 student 去访问name---------------')
分析:
2.7类方法和静态方法
- 类方法是类所拥有的,可以访问类变量,可以通过类对象和实例对象访问。必须传参数。
- 静态方法和类方法差不多,但是不必须传参数。
- 为什么要使用静态方法呢?1. 由于静态方法主要来存放逻辑性的代码,本身和类以及实例对象没有交互;2.也就是说,在静态方法中,不会涉及到类中方法和属性的操作;3.数据资源能够得到有效的充分利用。
class People:
country='china'
@classmethod
def get_country(cls):
return cls.country
pass
@classmethod
def change_country(cls,data):
cls.country=data
pass
@staticmethod
def getData():
return People.country
pass
@staticmethod
def add(x,y):
return x+y
pass
print(People.add(10,56))
p=People()
print(p.getData())
import time
class TimeTest:
def __init__(self,hour,min,second):
self.hour=hour
self.min = min
self.second = second
@staticmethod
def showTime():
return time.strftime("%H:%M:%S",time.localtime())
pass
pass
print(TimeTest.showTime())
t=TimeTest(2,10,15)
print(t.showTime())
2.8三种方法对比
- 从方法定义的形式可以看出来
- 1.类方法的第一个参数是类对象 cls 进而去引用类对象的属性和方法 必须用装饰器 @classmethod来修饰
- 2.实例方法的第一个参数必须是self,通过这个self 可以去引用类属性或者实例属性,若存在相同名称实例属性和类属性的话,实例属性的优先级最高
- 3.静态方法不需要定义额外的参数,若是要引用属性的话 则可以通过类对象或者是实例对象去引用即可 必须用装饰器 @staticmethod来修饰
2.9多态
class Animal:
'''
父类【基类】
'''
def say_who(self):
print('我是一个动物....')
pass
pass
class Duck(Animal):
'''
鸭子类 【子类】 派生类
'''
def say_who(self):
'''
在这里重写父类的方法
:return:
'''
print('我是一只漂亮的鸭子')
pass
pass
class Dog(Animal):
'''
小狗类 【子类】 派生类
'''
def say_who(self):
print('我是一只哈巴狗')
pass
pass
class Cat(Animal):
'''
小猫类 【子类】 派生类
'''
def say_who(self):
print('我是一只小花猫 喵喵喵喵')
pass
pass
class Bird(Animal):
'''
新增鸟类 无需修改原来的代码
'''
def say_who(self):
print('我是一只黄鹂鸟')
pass
class People:
def say_who(self):
print('我是人类')
pass
class student(People):
def say_who(self):
print('我是一年级的学习 张明')
pass
def commonInvoke(obj):
'''
统一调用的方法
:param obj: 对象的实例
:return:
'''
obj.say_who()
listObj=[Duck(), Dog(),Cat(),Bird(),student()]
for item in listObj:
'''
循环去调用函数
'''
commonInvoke(item)
2.10 三大特征(面向对象)
-
在python中展现面向对象的三大特征: -
封装、继承、多态 -
封装:指的是把内容封装到某个地方,便于后面的使用 他需要: 把内容封装到某个地方 从另外一个地方去调用被封装的内容 对于封装来说 其实就是使用初始化构造方法将内容封装到对象中,然后通过对象直接或者self来获取被封装的内容 -
继承: 和现实生活当中的继承是一样的:也就是 子可以继承父的内容【属性和行为】(爸爸有的儿子都有,相反 儿子有的爸爸不一定有) 所以对于面向对象的继承来说 其实就是将多个类共有的方法提取到父类中 子类仅需继承父类而不必一一去实现 这样就可以极大的提高效率 减少代码的重复编写,精简代码的层级结构 便于拓展 class 类名(父类):
'''
子类就可以继承父类中公共的属性和方法
'''
pass
-
多态:顾名思义就是多种状态、形态,就是同一种行为 对于不同的子类【对象】有不同的行为表现 要想实现多态 必须的有两个前提需要遵守: 1、继承:多态必须发生在父类和子类之间 2、重写: 子类重写父类的方法
|