Day7笔记

1.知识点回顾

a.简述面向过程和面向对象的区别

面向过程:
	思路:问题是怎样一步一步解决的,然后亲力亲为的去解决问题【执行者】
	代码:代码从上往下依次执行
面向对象:
	思路:将复杂的问题简单化,找到一个具有特殊功能的个体,然后委托这个个体帮忙完成某件事情【指挥者】
	代码:类和对象【核心】

b.简述类和对象之间的区别和联系

类:将多个具有相同特征和行为的对象进行抽取,抽取其中相同的特征和行为,形成一个类,类是一个抽象的存在
对象:将类具体化【在一个类中,具体的存在】
联系:不严谨的理解,包含关系【在代码中,先定义类,然后再通过类创建对象】

c.定义一个类,在类中书写构造函数和成员函数,在类外面创建对象,调用成员函数

class Person():
  #构造函数
  def __init__(self,name,age):
    #实例属性
    self.name = name
    self.age = age
    
  #成员函数
  def show(self):
    print("show")
    
p = Person("abc",18)
p.show()
2.作业讲解
#1.定义一“圆”(Circle)类,圆心为“点”Point类,构造一圆,求圆的周长和面积,并判断某点与圆的关系

"""
圆类:
    特征:圆心,半径
    行为:周长,面积


点类:
    特征:x坐标,y坐标
"""

#1.导入模块
from homework.circle import Cirlce
from homework.point import Point
import  math

#2.创建圆心【点】的对象
circlePoint = Point(10,20)
print(circlePoint.x,circlePoint.y)

#3.创建圆的对象
ci = Cirlce(circlePoint,15)
print(ci.radius,ci.circlePoint.x,ci.circlePoint.y)

#4.让圆执行自己的行为
print(ci.cirlceLength())
print(ci.circleArea())

#5.创建某点的对象
x = int(input("请输入点的x坐标:"))
y = int(input("请输入点的y坐标:"))
myPoint = Point(x,y)

#6.计算某点到圆心之间的距离
#(x1,y1)  (x2,y2)   距离:sqrt((x1 - x2) ** 2 + (y1 - y2) ** 2)
#(myPoint.x,myPoint.y)  (ci.circlePoint.x,ci.circlePoint.y)
result = (myPoint.x - ci.circlePoint.x) ** 2 + (myPoint.y - ci.circlePoint.y) ** 2
disance = math.sqrt(result)


#7.判断半径和距离之间的大小关系
if disance > ci.radius:
    print("圆外")
elif disance < ci.radius:
    print("圆内")
else:
    print("圆上")
"""
圆类:
    特征:圆心,半径
    行为:周长,面积

"""
class Cirlce():
    #构造函数
    #circlePoint:圆心,传参的时候必须传 的一个点的对象
    #radius:半径
    def __init__(self,circlePoint,radius):
        self.circlePoint = circlePoint
        self.radius = radius

    #成员函数
    #周长
    def cirlceLength(self):
        return 3.14 * self.radius * 2

    #面积
    def circleArea(self):
        return  3.14 * self.radius ** 2
"""
点类:
    特征:x坐标,y坐标
"""

#文件名的命名:小驼峰,尽量不要使用中文
class Point():
    #构造函数
    def __init__(self,x,y):
        self.x = x
        self.y = y

二、析构函数

构造函数:创建对象的时候第一个被自动调用的函数,__init__
	作用:在其中定义实例属性,给实例属性赋值
析构函数:和构造函数相反,当对象被销毁的时候自动调用的函数,__del__
	作用:当程序执行结束的时候需要做的一些清理工作,比如:关闭文件,关闭数据库等
	
问题:对象什么时候会被销毁?

import  time

class Animal():
    #构造函数
    def __init__(self,name,age):
        self.name = name
        self.age = age
        print("构造函数被执行了")

    #成员函数
    def show(self):
        print(self.name,self.age)


    #析构函数
    #析构函数执行的时机:对象的生命周期结束【全局:程序执行结束,局部:函数执行完毕】
    #生命周期的结束:正常的生老病死,通过del中途夭折
    def __del__(self):
        print("析构函数被执行了~~~")

#a是一个对象,同时他也是一个全局变量,生命周期:从代码开始执行到执行结束
#情况一
# a = Animal("大黄",18)
# a.show()
# print("over")
# time.sleep(3)

#情况二
# def func():
#     a = Animal("大黄", 18)
#     print("func函数被执行了")
#
# func()
# print("over")


#情况三
a = Animal("大黄", 18)

#删除变量
del a

print("over")

#总结:常用构造函数,析构函数不常用,但是,不管怎样,构造函数和析构函数都会被调用

三、封装

面向对象语言三大特征:封装,继承,多态

学习思路:

​ 是什么

​ 如何使用

​ 有什么作用

1.概念【掌握】

广义的封装:函数和类的使用,就是封装的体现

​ 函数:将某段特殊功能提取出来,定义 一个函数

​ 类:将多个具有相同特征和行为的对象提取出来,定义一个类

狭义的封装【面向对象中的封装】:一个类的某些属性,在使用的过程中,如果不希望外界可以直接访问它,就可以将该属性作为私有的【private:私有的,public:公开的】,然后暴露给外界一个访问的方法即可【对属性进行间接访问】

私有的:只有当前类持有或者只能被当前类直接访问

封装的本质:就是属性私有化的过程

举例:插排【不需要关心属性在类的内部做了什么样的操作,只需要关心将值传进去,也可以将值获取出来,也就是说:只需要关心暴露给外界的接口能不能用】

封装的好处:提高了数据的安全性,提高了代码的复用性

封装的使用流程:

​ a.将属性私有化

​ b.提供给外界一个访问的函数

​ c.外界需要通过函数间接的访问属性

2.属性私有化

如果一个属性不想要被外界直接访问,则可以在属性名称的前面添加两个下划线,则该属性被称为私有化的属性【私有成员变量】

私有属性的特点:只能在当前类的内部被直接访问

#1.属性未被私有化
class Person1():
    def __init__(self,name,age):
        self.name = name
        self.age  = age

    def myprint(self):
        print("姓名:%s 年龄:%d" % (self.name,self.age))

p1 = Person1("zhangsan",19)
p1.myprint()
#直接访问:对象.属性名
p1.name = "lisi"
p1.myprint()
print(p1.name,p1.age)

print("**********************")

#2.属性被私有化
class Person2():
    def __init__(self,name,age):
        self.__name = name
        self.age  = age

    def myprint(self):
        print("姓名:%s 年龄:%d" % (self.__name,self.age))
p2 = Person2("abc",18)
p2.myprint()
#注意1:下面两种写法,并不是访问定义的实例属性__name,而都属于动态绑定
#p2.name = "yyyy"
#p2.__name = "ppppp"

#print(p2.age)

#注意2:在实例属性名称的前面添加__,则该属性在外界不能被直接访问
#print(p2.name)  #AttributeError: 'Person2' object has no attribute 'name'
#print(p2.__name)  #AttributeError: 'Person2' object has no attribute '__name'

#注意3:私有变量在内存中的存储的形式
#属性一旦被私有化之后,在内存中的存在:Python解释器将__name解释成了_Person2__name
#存在的问题:虽然可以通过_Person2__name访问该私有属性,但是不建议这么做,因为Python是一门跨平台的语言,
# 在不同的平台上,可能存在不同的Python解释器
#print(p2._Person2__name)
3.get函数和set函数

get函数和set函数在Java中是一个特有的语法,但是在Python,只是一个过渡

get函数和set函数并不是系统内置的函数,而是通过封装的概念自定义的,为了和封装的概念相吻合,命名为:getXxx() setXxx()

get函数:获取值【p1.name

set函数:设置值【p1.name = “xxx”】

说明:getXxx() 和setXxx()中的Xxx其实就是被私有化的属性的名称

举例:在一个类中,私有的属性__name,getName() setName()

语法:

get函数:设置返回值

def getXxx(self):

​ return 被私有化的属性

set函数:设置参数

def setXxx(self,xxx):

​ 私有化属性 = xxx

#3.get函数和set函数
class Person3():
    def __init__(self,name,age):
        self.__name = name
        self.__age  = age

    def myprint(self):
        print("姓名:%s 年龄:%d" % (self.__name,self.__age))

    #get函数和set函数
    #get函数:获取私有化属性的值
    #命名方式:getXxx
    #特点:设置返回值,但是没有参数
    def getName(self):
        return self.__name

    #set函数:给私有化属性赋值
    #命名方式:setXxx
    #特点:设置参数,但是没有返回值
    def setName(self,name):
        self.__name = name

    def getAge(self):
        return self.__age

    def setAge(self,age):
        #数据的过滤【在类的内部对属性做操作:逻辑处理】
        if age < 0:
            age = abs(age)
        self.__age = age

p3 = Person3("abc",18)
p3.myprint()
print(p3.getName())   #print(p3.name)
p3.setName("nnbv")
print(p3.getName())

print(p3.getAge())   #18
p3.setAge(-10)
print(p3.getAge())

#get函数和set函数------》Python的装饰器【常用】

4.@property装饰器【掌握】

property:属性

装饰器的作用:可以给 函数动态的添加功能,对于类的成员函数而言,装饰器仍然起作用

@property装饰器的作用:

​ a.作用相当于get函数,获取私有属性的值

​ b.实际的作用:可以将可以函数转换为属性使用【p1.getAge()----->p1.getAge】

​ c.使用@property之后,会自动生成一个新的装饰器,命名@私有属性名.setter,相当于set函数,给私有属性进行赋值

注意:@property装饰器的出现简化了get函数和set函数的使用

#4.@property的使用
class Person4():
    def __init__(self,name,age):
        self.__name = name
        self.__age  = age

    def myprint(self):
        print("姓名:%s 年龄:%d" % (self.__name,self.__age))

    #注意:函数的命名方式:被私有化属性的名称 ,例如:self.__age------>age
    #相当于get函数:设置返回值,但是没有参数
    #说明:函数名的命名并不是固定的,只要是一个合法的标识符即可,但是,为了区分不同的私有属性,
    # 一套流程中一般是相似或者相同的命名
    @property
    def age(self):
        return  self.__age

    #注意:装饰器的命名:@【和property修饰的函数名相同】.setter
    #相当于set函数:设置参数,但是没有返回值
    @age.setter
    def age(self,age):
        if age < 0:
            age = abs(age)
        self.__age = age


    @property
    def name(self):
        return self.__name


    @name.setter
    def name(self,name):
        self.__name = name


    #补充:@propery除了进行操作私有化属性之外,还可以修改普通的成员函数,将普通的成员函数当做属性使用
    #调用函数的语法:对象.函数名
    @property
    def show(self):
        print("show")
        return "show"

p4 = Person4("abc",18)
#调用函数
#print(p4.age())
#添加了@property之后,就可以将一个函数当做属性使用
#注意:下面出现的age并不是私有的属性名,而是定义的函数名
print(p4.age)  #相当于get函数,将私有化属性的值返回
p4.age = 100    #相当于set函数,给私有化属性赋值
print(p4.age)

print(p4.name)
p4.name = "fjakdg"
print(p4.name)

#print(p4.show())
print(p4.show)
5.属性的不同形式
#属性的不同形式
class Person():
    def __init__(self,pid,name,age,height,score):
        #1.普通变量:小驼峰或者Python官方【字母全部小写,不同的单词使用_分隔】
        self.pid = pid
        self.score_num = score

        #2.私有变量
        self.__name = name

        #3.受保护的变量,虽然能够在外界直接访问,但是不建议使用,是一种约定
        self._age = age

        #4.__xxx__:一般是系统的变量或者函数名,不建议使用,是一种约定
        self.__height__ = height

    @property
    def name(self):
        return self.__name

    @name.setter
    def name(self,name):
        self.__name = name

p = Person("1001","zhangsan",18,178.0,87)
#1
print(p.pid,p.score_num)

#2
print(p.name)
p.name = "lisi"


#3
print(p._age)

#4
print(p.__height__)


"""
【面试题:解释下面变量的作用】
xxx:普通变量,可以任意的访问
_xxx:受保护的变量,在实际项目开发中,尽量不要使用
__xxx:私有变量,只能在当前类中被直接访问
__xxx__:一般一用于系统的变量和函数的命名,尽量不要使用,比如__name__,__init__,__del__等
"""
6.私有成员方法

函数名相当于是一个变量名,变量可以被私有化,函数也可以被私有化

写法:在函数名的前面添加两个下划线

特点:私有函数只能在当前类中被调用

class Site():
    def __init__(self,name):
        self.name = name

    #成员函数
    #公开函数
    def func(self):
        print("普通函数")

        #在类的内部,可以在其他普通函数的内部调用私有函数
        #类的内部的函数相互之间进行调用,都必须通过self调用
        self.__check()

        self.show()

    #私有函数
    def __check(self):
        print("check")

    def show(self):
        print("show")

s = Site("千锋")
#直接调用
s.func()
#对象不能直接调用私有函数
#s.check()
#s.__check()

四、继承

1.概念【掌握】

如果两个或者两个以上的类具有相同的属性或者方法,我们就可以重新抽取一个类出来,在抽取出来的类中声明其他类公共的部分,把这个实现的过程被称为继承

被抽取出来的类:父类【parent】,超类【super】,基类【base】

两个或者两个以上的类:子类,派生类

他们之间的关系:父类 派生了 子类

​ 子类 继承了 父类

2.单继承

extends;继承

概念:一个子类只有一个父类,

注意:默认情况下,所有类的父类都是object,如果在自定义类的时候,没有指明的父类,则继承自object

语法:

父类

class 父类类名(object):

​ 类体【公共的部分】

子类

class 子类类名(父类类名):

​ 类体【子类特有的内容】

from extends01.person import Person
from extends01.worker import Worker
from extends01.doctor import Doctor
from extends01.student import Student

#s = Student("jack",19,"语文")

#1.创建子类的对象
w = Worker("tom",17,"铁路工人")
#注意1:子类对象如果要访问父类中的变量,想办法调用父类的构造函数
print(w.name,w.age,w.kind)
print(w.kind)
#注意2:子类的对象不能直接访问父类中私有化属性,但是当父类中提供了@property的函数,则可以访问

#3.子类的对象可以调用父类中未被私有化的成员函数
w.eat()

#4.如果在子类中出现了和父类重名的成员函数,则子类对象优先调用子类中的函数【就近原则】
#重写:override
w.func()


#5.父类的对象无法访问子类中特有的变量和成员函数
#在父类中书写各个类公共的部分,在子类中书写的是该类特有的数据
p = Person("abc",17)
p.work()
class Person(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def eat(self):
        print("eating")

    def func(self):
        print("父类中的func")
from extends01.person import Person

class Worker(Person):
    def __init__(self,name,age,kind):
        # self.name = name
        # self.age = age

        #2.调用父类的构造函数
        #注意:调用父类中的构造函数,只能在子类的构造函数中调用,原因:创建子类对象的时候就需要将父类中的实例属性继承过来
        #在子类的构造函数中调用父类的构造函数
        """
        self:自己,表示当前对象的引用
        super:表示父类的对象的引用
        """
        #方式一:super(当前类名,self).__init__(属性列表)
        #super(Worker,self).__init__(name,age)
        #方式二:父类名.__init__(self,属性列表)
        #Person.__init__(self,name,age)
        #方式三:super().__init__(属性列表)
        super().__init__(name,age)

        self.kind = kind


    # def eat(self):
    #     print("eating")

    def work(self):
        print("working")


    def func(self):
        print("子类中的func~~~~")

特殊情况:

from extends02.student import Student
from  extends02.graduateStudent import GraduateStudent

#创建父类的对象
s1 = Student()
s1.name = "jakc"
s1.age = 17
print(s1.name,s1.age)
# s1.score = 89
# print(s1.score)

#创建子类的对象
gs1 = GraduateStudent()
gs1.score = 18
print(gs1.score)

#结论:如果在父类中作了属性的限制绑定,则只对当前类起效,子类不会起效

class Student(object):
    __slots__ = ("name","age")
from extends02.student import Student


class GraduateStudent(Student):
    pass

总结:

继承的特点:

​ a.子类对象可以直接访问父类中未被私有化的属性

​ b.子类对象可以直接调用父类中未被私有化的成员函数

​ c.父类对象不能访问子类中的属性和调用子类的中成员函数

优缺点:

优点:

​ a.可以简化代码,减少冗余

​ b.提高代码的维护性

​ c.提高了代码的安全性

​ d.继承是多态的前提

缺点:

​ 耦合和内聚被用来描述类与类之间的关系,耦合性越低,内聚性越高,说明代码质量比较好

​ 但是,在继承关系中,耦合性相对比较高的【如果修改了父类,则子类也会随着发生改变】

3.多继承

概念:一个子类可以有多个父类,一个子类可以同时获得多个父类中的功能

语法:

class 子类类名(父类1,父类2.。。):

​ 类体

from extends03.child import Child

c = Child(8,10000,"打游戏")
print(c.faceValue,c.money,c.hobby)
c.eat()
c.play()
c.study()

#注意:如果多个父类中出现了重名的函数,则子类对象调用函数的时候,
# 查找规则:在父类列表中从前往后依次查找,如果找到第一个符合条件的,则直接执行该函数,停止查找
c.func()
class Mother(object):
    def __init__(self,faceValue):
        self.faceValue = faceValue


    def eat(self):
        print("eating")

    def cook(self):
        print("cooking")

    def func(self):
        print("Monther~~~func")
class Father(object):
    def __init__(self, money):
        self.money = money

    def play(self):
        print("playing")


    def func(self):
        print("Father~~~func")
from extends03.father import Father
from extends03.mother import Mother

class Child(Mother,Father):
    def __init__(self,faceValue,money,hobby):
        # self.faceValue= faceValue
        # self.money = money

        #调用父类中的构造函数
        Father.__init__(self,money)
        Mother.__init__(self,faceValue)
        self.hobby = hobby


    def study(self):
        print("studying")

    def func(self):
        #调用父类中的普通函数
        super().func()
        print("子类")

扩展:继承树


#继承树和方法解析
# 【如果类与类之间存在复杂的继承关系:单继承,多继承,一个子类也可以是另外一个类的父类,则将不再遵循单层解析的原则】
#父类
class BaseClass(object):
    def show(self):
        print("BaseClass")
#子类
class SubClassA(BaseClass):
    def show(self):
        print("enter subclass~~~~A")
        super().show()
        print("exit   subclass~~~~A")
class SubClassB(BaseClass):
    def show(self):
        print("enter subclass~~~~B")
        super().show()
        print("exit   subclass~~~~B")
class SubClassC(SubClassA):
    def show(self):
        print("enter subclass~~~~C")
        super().show()
        print("exit   subclass~~~~C")
class SubClassD(SubClassB,SubClassC):
    def show(self):
        print("enter subclass~~~~D")
        super().show()
        print("exit   subclass~~~~D")
s = SubClassD()
s.show()

"""
enter subclass~~~~D
enter subclass~~~~B
enter subclass~~~~C
enter subclass~~~~A
BaseClass
exit   subclass~~~~A
exit   subclass~~~~C
exit   subclass~~~~B
exit   subclass~~~~D
"""

"""
多继承树,如果在中间层某类有向上一层解析的迹象,则会把本层平级的其他类方法解析完,返回再接着解析,被称为广度优先解析

D---->B,B有向上解析的迹象,所以解析C———》A---->BaseClass
"""
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值