简单get Python面向对象

面向对象


一.对面向对象和面向过程的认知

面向对象是一种抽象化的编程思想,是当前软件开发领域的主流技术。如Python,适用于大型项目

而面向过程适用于中小型项目,例如C语言

面向对象和面向过程的不同:

1.面向过程是将问题的解决步骤全部分析出来,然后通过函数一步一步实现,依次调用。而面向对象是将一个问题分为若干个对象,建立该对象的目的并不是为了完成某一个步骤,而是为了描述在解决某个问题过程中的行为。

2.面向过程思想偏向于我们做一件事的流程,首先做什么,其次做什么,最后做什么。面向对象思想偏向于了解一个人,他的特长,性格,有没有遗传到什么能力。

3.面向过程流程化的编程使编程任务十分明确,在实行之前已经基本考虑了实现方式和结果,便于节点分析。效率高,代码短小精悍,善于结合数据结构来高效率的开发程序。但是需要编程者深度的思考,耗费精力。代码的重用性低,扩展能力差,后期维护的难度大。面向对象易维护、易拓展、易复用、,有封装、继承、多态的特性、更容易设计出耦合的系统。但性能比面向过程低。
点击此处查看原图
点击此处查看原图

二.类和对象

开发中现有类再有对象

1.类(大驼峰命名)

类就是对一系列具有相同属性和行为的事物的统称

属性:就是特征,用来描述是什么样子(静态概念,如身高、体重)

行为:所具有的功能,用来说明能做什么(动态概念,如跑步、考试)

类是一个抽象的概念,并不是真实存在的

2.对象:

是类的具体表现,是类创建出来的真实存在的事物,也是面向对象的核心(Python万物皆为对象)

3.定义类

三种定义方式
<1>

class A:
   pass
a=A()

<2>目前使用这种方法

class A():
  pass  #占位符,表示空语句,运行时直接跳过
a=A()

<3>推荐使用,在了解继承后便可以理解了

object是顶级父类,如果一个类没有使用继承任何类,默认也会继承object类

class A(object):
  pass  
a=A()

4.实例化对象

Python可以根据已经定义的类创建一个或多个对象

class FriendName():
"""朋友名字类"""
  pass     
hong=FriendName()   #第一次实例化对象
print("hong:",hong)
ming=FriendName()   #第二次实例化对象
print("ming:",ming) 

运行结果:(运行结果是对象的内存地址,因为没有任何的方法调用)

hong: <main.FriendName object at 0x000001B506B33DC8>
ming: <main.FriendName object at 0x000001B506B73788>

内存地址不一样,说明是不同的对象

5.在类中定义方法

<1>实例方法(方法即是函数)

由对象来调用,至少有一个self函数,执行实例方法的时候,自动将调用该方法的对象赋给self

class Person():  #定义类Person
  def eat(self):  #定义方法eat,实例方法必须有参数self,用来代表对象本身
      print("爱干饭")
      print("self:",self)  #哪一个对象调用实例方法,那么实例方法中的self就是对象本身的内存地址
su=Person()  #实例化对象
print("su:",su)
su.eat()   #由对象去调用实例方法

在这里插入图片描述

<2>静态方法

静态方法用@stadicmethod来修饰,既不需要传递类对象也不需要传递实例对象

可以取消不需要的参数传递,有利于减少不必要的内存占用和性能消耗

当方法中既不需要用到实例对象、实例属性,又不需要用到类对象时定义静态方法

格式: class 类名(object):
         @staticmethod
         def 方法名(形参):
         方法体
class person():
   @staticmethod
   def eat(name):
      print(f"{name}需要干饭")
person.eat("susu")   #susu需要干饭

<3>类方法

使用@classmethod作为标识的方法。对于类方法,第一个参数必须是类对象,一般以cls为第一个参数
类方法一般和类属性配合使用,当方法中需要使用类(如访问类属性、调用其它类方法)时可以定义类方法

格式: class 类名(object):
        @classmethod
        def 方法名(cls,形参)
        方法体
class person():
   @classmethod
   def eat(cls):  #cls代表类对象
      print(cls)
person.eat()
print(person)

在这里插入图片描述

6.在类中定义属性

<1>类属性

class Person():
  favourite = "干饭"  #类属性
  def eat(self):
      print("self:",self)
su=Person()
print(su.favourite) #干饭
print(Person.favourite) #干饭

类属性不仅可以通过对象名访问,也可以通过类名访问

<2>实例属性

定义在类的方法中的属性,只能用于当前对象

class Person():
  favourite = "干饭"
  def eat(self):
      print(f"su的年龄是{self.age}")  #实例属性
su=Person()
print(su.favourite)  #干饭
su.age=18
su.eat()  #su的年龄是18
mao=Person()
mao.age=19
mao.eat()  #su的年龄是19
lin=Person()
lin.age=20
lin.eat()  #su的年龄是20

每实例化一次,都需要给实例化属性赋值,很麻烦。因此就有了构造函数

7.构造函数

构造函数是一种特殊的 实例方法实例化对象时,会自动执行该函数

通常用来属性的初始化赋值

class Person():
    def __init__(self,name,age): #设置形参
        self.name=name
        self.age=age
    def say(self):
        print(f"我的名字是{self.name},年龄是{self.age}")
p1=Person("susu",18)   #带入实参
p1.say()   #我的名字是susu,年龄是18
p2=Person("linlin",19)
p2.say()   #我的名字是linlin,年龄是19

8.析构函数

在程序执行到最后时或对象被删除时自动执行析构函数

用途:

1.用于程序执行后

class Person():
    def __init__(self):    #构造函数
       print("我是程序执行开始时时执行的")
    def __del__(self):   #析构函数
       print("我是程序结束时执行的")
p1=Person()
print("123")
p2=Person()
print("34")

在这里插入图片描述
我们可以看出并不是在一个对象的方法结束后执行del,而是全部代码执行后之后执行的

2.对象被删除后

class Person():
    def __del__(self):
        print("程序被删除")
p1 = Person()
del p1
print("qqq")
p2 = Person()
del p2
print("qqq")

在这里插入图片描述

我们可以看出是在对象被删除后执行的,而不是程序结束时

使用场景:对象即将被销毁的时候需要做的一些工作,比如关闭文件、关闭数据库、关闭各种方法

10.__str__方法

用于对象的描述信息,如果在类中定义了该方法,在打印对象的时候,默认输出该方法的返回值

str方法必须有返回值,而且返回值必须是字符串类型的数据

class Person():
    def __str__(self):
       return "打印成功"
p1=Person()
print(p1) #打印成功
p2=Person()
print(p2)  #打印成功

在这里插入图片描述

三.三大特性:封装、继承、多态

1.封装性

<1>基本认知

根据职责将属性和方法都放在抽象的类中,然后通过实例化对象来处理。类本质上就是一种封装

面向对象编程:

1.定义类,将属性和方法封装到抽象的类中

2.外界使用类创建对象,然后由独对象调用类中方法(使用缩进来控制界外界内)

3.对象方法的细节都被封装在类的内部

class Person():   #1.定义类
   def __init__(self,name,age):
      self.name=name  
      self.age=age
   def say_hello(self):
      print(f"hello,my name is {self.name},age is {self.age}")
p1=Person("susu",21)   #2.外界使用类创建对象
p1.say_hello()
print(p1.age)   #通过对象访问实例属性

在这里插入图片描述

<2>私有属性

注意在python中并没有专门的修饰符用于定义属性/方法的私有。

如果不希望被外部访问,在属性名前使用==__==

class Person():   #1.定义类
   def __init__(self,name,age):
      self.name=name  
      self.__age=age   #不希望在类的外部被使用,加入了双下划线,只允许在类的内部使用
   def say_hello(self):
      print(f"hello,my name is {self.name},age is {self.age}")
p1=Person("susu",21)   #2.外界使用类创建对象
print(p1.name)      #susu
print(p1.age)       #报错

方法一:dir
但是这种方法是不严谨的,仍然有其他方法可以读取出age

class Person():
   def __init__(self,name,age):
      self.name=name
      self.__age=age   #加下划线
   def say_hello(self):
      print(f"hello,my name is {self.name},age is {self.age}")
p1=Person("susu",21)
print(dir(p1))
print(p1._Person__age)
p1._Person__age=17
print(p1._Person__age)

在这里插入图片描述

我们可以看出,实际上是对名称做了特殊处理。使用双下划线开头的属性会让python自动为属性改名字:_类名__属性名 使得外界无法访问。当找出其真正的名称时仍然可以进行修改、查看操作(但是不推荐这种方法,不正规,像小偷小摸似的)

方法2:在类中定义方法使用

class Person():
   def __init__(self,name,age):
      self.name=name
      self.__age=age   #加下划线
   def say_hello(self):
      print(f"hello,my name is {self.name},age is {self.age}")
   def tell_age(self):
      print(self.__age)
p1=Person("susu",21)
print(p1.age)   #报错
p1.tell_age()   #21

2.继承性

指多个类之间的所属关系,即让类和类之间转换为父子关系,子类默认继承父类的所有属性和关系

实现代码的重用,相同的代码不需要重复编写,以提高开发的效率

父类可以写多个,父类之间用 , 隔开。也可以不写父类,默认继承object(顶级父类)

#语法:class 类名(父类名):
#       类体

<1>单继承

单继承:子类只有一个父亲,具有父亲的属性和方法

class Person():
   """父类   人"""
   def sleep(self):
      print("人类需要睡觉")
   def eat(self):
      print("人类需要吃饭")
class Man(Person):
   """子类 男人"""
class Woman(Person):
   """子类 女人"""
M1=Man()
M1.sleep()   #人类需要睡觉
M1.eat()    #人类需要吃饭
W1=Woman()
W1.sleep()   #人类需要睡觉
W1.eat()    #人类需要吃饭

在Man类中他没有任何的方法,但是调用方法却成功了。这就是因为他继承了他父类的所有属性和方法.而且一个父类是可以继承多个子类的。

<2>继承的传递

A1、A2、A3类,A3继承A2,A2继承A1 A3具有A2和A1的属性和方法

即子类拥有父类和父类的父类……的属性和方法

class Grandfather():
   """父类   爷爷"""
   def Retirement_pay(self):
      print("有退休金")
class Father(Grandfather):
   def salary(self):
      print("有工资")
class younth(Father):
   pass
y1=younth()
y1.salary()   #有工资
y1.Retirement_pay()   #有退休金

<3>方法的重写

指在子类中有定义与父类同名的方法

方法一;覆盖父类方法

在子类中定义一个和父类同名的方法,调用会使子类重写

class Grandfather():
   """父类   爷爷"""
   def Retirement_pay(self):
      print("有退休金")
class Father(Grandfather):
    """子类  父亲"""
   def Retirement_pay(self):
      print("需要交五险一金")
y1=Father()
y1.Retirement_pay()      #需要交五险一金

方法二:对父类方法进行拓展

继承父类的方法,子类还可以增加自己的功能.共有三种实现方式(但是第三种方式在python2中的方法现在已经过时了,便不陈述了)

【1】父类名.方法名(self)

class Grandfather():
   """父类   爷爷"""
   def Retirement_pay(self):
      print("有退休金")
class Father(Grandfather):
   def Retirement_pay(self):
      Grandfather.Retirement_pay(self)   #!!!!!
      print("需要交五险一金")
y1=Father()
y1.Retirement_pay()

在这里插入图片描述

但是使用这种方式,如果想要改变父类名的话,下面子类中的调用就必须都得进行改变,不利于代码的可维护性

【2】super().方法名(self)

class Grandfather():
   """父类   爷爷"""
   def Retirement_pay(self):
      print("有退休金")
class Father(Grandfather):
   def Retirement_pay(self):
      super().Retirement_pay(self)   #!!!!!!
      print("需要交五险一金")
y1=Father()
y1.Retirement_pay()

在这里插入图片描述

super代表上级父类对象,可以使用父类中的方法

<4>例题

需求:创建Person类,属性有姓名name、年龄age、性别sex、方法有printInfo方法,用于打印这个人的信息

创建Student类,继承Person类,属性有学院college,班级class,重写父类printInfo方法,调用父类方法打印个人信息外,将学生的学院、班级信息也打印出来

class Person():
   def __init__(self,name,age,sex):
      self.name=name
      self.age=age
      self.sex=sex
   def printInfo(self):
      print(f"此人的姓名为{self.name},年龄为{self.age},性别为{self.sex}")
class Student(Person):
   def __init__(self,name,age,sex,college,class1):
      super().__init__(name,age,sex)
      self.college=college
      self.class1=class1
   def printInfo(self):
      super().printInfo()
      print(f"学院为{self.college}班级为{self.class1}")
s1=Student("susu","21","men","河工大","204")
s1.printInfo()

<2>多继承

多继承:子类可以有多个父亲,并且具有所有父亲的属性和方法

class Father(object):
   def weight(self):
      print(f"爸爸体重160")
class Mother(object):
   def appearance(self):
      print(f"妈妈颜值90分")
class Son(Father,Mother):    #son继承了两个父类的所有方法
   pass
son1=Son()
son1.weight()   #爸爸体重160
son1.appearance()   #妈妈颜值90分

如果有一个子类继承多个父类方法,但是父类方法有重名时,使用就近原则,子类先继承谁,就是用谁的属性(如果子类有着自己的同名属性时,优先使用自己的)

class Father(object):
   def weight(self):
      print(f"爸爸体重160")
class Mother(object):
   def weight(self):
      print(f"妈妈体重90")
class Son(Mother,Father):   #同名方法,采用就近原则,先继承的Mother
   pass
son1=Son()
son1.weight()   #妈妈体重90

在搞不清楚的情况下可以使用mro来查看方法搜索顺序

多继承在有同名方法时,调用方法的时候,会按照mro属性的值,按照从左到右的顺序进行查找

class Father(object):
   def weight(self):
      print(f"爸爸体重160")
class Mother(object):
   def weight(self):
      print(f"妈妈体重90")
class Son(Mother,Father):
   def weight(self):
      print(f"自己体重128")
son1=Son()
print(Son.__mro__)   #注意这里是子类的方法查找顺序号
son1.weight()   

在这里插入图片描述

3.多态

同一行为具有多个不同的表现形式。不同的对象调用同一个方法会产生不同的执行结果,能够增加代码的灵活度

多态的两大前提:继承,重写

class Animal():
   def shout(self,obj):   #obj为形参,在此例中obj=cat
      print("动物会叫")
      obj.shout()    #cat.shout()
class Cat(Animal):
   def shout(self):
      print("猫咪喵喵")
class Dog(Animal):
   def shout(self):
      print("修狗汪汪")
a=Animal()
cat=Cat()
a.shout(cat)

在这里插入图片描述
通过定义函数设置形参来控制调用不同的对象的同名方法,来实现多态性

例题

利用多态思想,编写程序模拟主人喂养宠物的场景

class master():
   def feed(self,obj):   #obj为形参,在此例中obj=cat
      obj.feed()    #cat.shout()
class Cat(master):
   def feed(self):
      print("主人喂猫咪鱼")
class Dog(master):
   def feed(self):
      print("主人喂修狗骨头")
a=master()
cat=Cat()
dog=Dog()
a.feed(cat)   #主人喂猫咪鱼
a.feed(dog)   #主人喂修狗骨头

四.各种小例题

1.定义一个Point类为父类,在父类中分别有x,y,z,h四个属性,用来传入未知整数,再定义一个Line类为子类,继承Point类,并在Line类中定义getPoint方法,getPoint方法用于计算x-y的绝对值和z-h的绝对值相乘的结果,最后通过子类创建对象传入实参检测是否继承成功。
计算公式:(x-y)*(z-h)

class Point(object):
    def __init__(self,x,y,z,h):
        self.x=x
        self.y = y
        self.z = z
        self.h = h
class Line(Point):
    def getPoint(self):
        result=abs(self.x-self.y)*abs(self.z-self.h)
        print(result)
l=Line(2,3,4,5)
l.getPoint()

2.定义一个Car类,并在类中定义一个move方法,然后分别创建BMW_X9、AUDI_A9对象,并在类里面添加颜色、马力、型号等属性,然后通过调用move方法方法分别打印出属性值。
提示: 使用__ init__方法完成属性赋值。

class Car():
    def __init__(self,color,horsepower,model):
        self.color=color
        self.horsepower=horsepower
        self.model=model
    def move(self):
        print(f"该车颜色为{self.color},马力为{self.horsepower},型号为{self.model}")
BMW_X9=Car("blue",150,"x9")
AUDI_A9=Car("red",160,"a9")
BMW_X9.move()
AUDI_A9.move()
  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

苏茂林别干饭了

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值