python学习笔记12(类)

一、上堂回顾

1.默写题目

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

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

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

类:将多个具有特殊功能的个体进行提取,提取相同的特征和行为【类是一个抽象的模板】
对象:在一个指定的类中,具体的存在
包含关系

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

class MyClass():
    #name = ""
    #构造函数
    #注意1:创建对象     在其中定义成员变量
    #注意2:self的作用:区分成员变量还是局部变量
    #注意3:self的含义:当前类的实例
    def __init__(self,name,age):
        self.name = name
        self.age = age
    #注意4:成员函数和普通函数之间的区别和联系
    def show(self):
        pass
    
m = MyClass("lisi",10)
m.show()       

2.知识点回顾

作业:

textDemo01.py

#.定义一“圆”(Circle)类,圆心为“点”Point类,构造一圆,求圆的周长和面积,并判断某点与圆的关系
​
#测试类
"""
分析:
Circle:
    特征:圆心,半径
    行为;圆的周长和面积
​
Point:
    特性:x y
"""
from homework.circle import Circle
from homework.point import Point
import math
​
#1.创建一个圆心的对象
circlePoint = Point(10,20)
​
#2.创建一个圆的对象
ci = Circle(8,circlePoint)
#半径,x坐标,y坐标
print(ci.radius,ci.circlePoint.x,ci.circlePoint.y)
​
#3.求圆的面积和周长【调用成员函数】
print(ci.area())
print(ci.zhouChang())
​
#4.判断某一点和圆之间的关系
#创建某一个点的对象
myPoint = Point(33,55)
result = (circlePoint.x - myPoint.x) ** 2 + (circlePoint.y - myPoint.y) ** 2
distance = math.sqrt(result)
if distance > ci.radius:
    print("圆外")
elif  distance < ci.radius:
    print("圆内")
else:
    print("圆上")

circle.py

class Circle():
    #构造函数
    def __init__(self,radius,circlePoint):
        self.radius = radius   #半径
        self.circlePoint = circlePoint      #圆心,是一个点的对象
​
    #成员函数
    #求面积
    def area(self):
        return  3.14 * self.radius ** 2
​
    #求周长
    def zhouChang(self):
        return 2 * 3.14 * self.radius

point.py

class Point():
    #构造函数
    def __init__(self,x,y):
        self.x = x
        self.y = y

二、析构函数

构造函数:创建对象的时候第一个被自动调用的函数    __init__
和构造函数相反,当对象被销毁的时候自动调用的函数,被称为析构函数    __del__
对象什么时候被销毁:程序执行完毕,使用del删除
使用场景:对象即将被销毁的时候需要做的一些工作,比如关闭文件,关闭数据库,关闭各种资源

代码演示:

import  time
class Pig():
    #构造函数
    def __init__(self,name,age):
        self.name = name
        self.age = age
        print("构造函数被调用")
​
    #析构函数
    def __del__(self):
        print("析构函数被调用")
​
p = Pig("小白",10)
​
#释放对象
#del p
​
#注意:对象释放以后将不能再访问【相当于该对象未被创建过】
#print(p.name)  #NameError: name 'p' is not defined
​
time.sleep(3)
​
#注意:在函数中创建的对象,其实还是一个局部变量,会在函数执行完毕之后被自动释放
def func():
    p1 = Pig("",0)
​
func()

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

扫描二维码关注公众号,回复: 2857726 查看本文章

是什么?

如何使用?

有什么样的作用?

三、封装

1.概念

广义的封装:函数和类的定义本身,就是封装的体现

狭义的封装【在面向对象中的封装】:一个类的某些属性,在使用的过程中,如果不希望被外界直接访问,就可以将该属性作为私有的【private,只有当前类持有】,然后暴露给外界一个访问的函数即可【间接的访问属性】

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

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

说明:举例:插排【不需要关心属性在类的内部做了什么样的操作,只需要关心将值传进去,获取将结果获取出来】

2.属性私有化

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

私有属性的特点:只能在类的内部被直接访问,在外界不能直接访问

代码演示:

#1.属性不私有化的时候
class Person1():
    def __init__(self,name,age):
        self.name = name
        self.age = age
​
    def myPrint(self):
        print(self.name,self.age)
​
#创建对象
p1 =  Person1("lisi",10)
#通过对象.属性  访问属性
print(p1.name,p1.age)
#通过 对象.成员函数   调用函数
p1.myPrint()
#通过对象直接访问属性,并且给属性赋值
p1.name = "jack"
print(p1.name)
​
#2.属性私有化
#写法:在需要被私有化的属性的前面添加__
class Person2():
    def __init__(self,name,age):
        self.name = name
        self.__age = age   #私有化属性
​
    def myPrint(self):
        #在类的内部可以直接访问私有化属性
        print(self.name,self.__age)
​
p2 = Person2("aaa",5)
p2.myPrint()
p2.name = "abc"
​
#注意1:属性被私有化之后,将不能再直接访问
#print(p2.age)  #ttributeError: 'Person2' object has no attribute 'age'
#在类的外部,不能通过对象直接访问属性
#print(p2.__age)   #AttributeError: 'Person2' object has no attribute '__age'
​
#属性的动态绑定,age和__age其实属于两个不同的变量
p2.age = 100
print(p2.age)
#注意2:此处的操作属于属性的动态绑定,和类中的__age不是同一个变量
p2.__age = 200
print(p2.__age)
​
#所以,重新创建一个对象,该对象仍然不能直接访问__age
p21 = Person2("",0)
#print(p21.__age)  #AttributeError: 'Person2' object has no attribute '__age'

3.get函数和set函数

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

get函数:获取值 【p1.name】

set函数:赋值 【p1.name = 值】

说明:

​ getXxx()和setXxx()中Xxx代表的是被私有化的属性的名称

语法:

get函数:

def getXxx(self):

​ return 私有化属性

set函数:

def setXxx(self,私有化属性的名称)

​ 私有化属性 = 私有化属性的名称

举例:假设一个类中有一个私有化属性age,self.__age = age

def getAge(self):

​ return self.__age

def setAge(self,age):

​ self.__age = age

代码演示:

#3.使用get函数和set函数访问私有化属性
class Person3():
    def __init__(self,name,age):
        self.__name = name
        self.__age = age   #私有化属性
​
    def myPrint(self):
        #在类的内部可以直接访问私有化属性
        print(self.__name,self.__age)
​
    #给age添加get函数和set函数
    #get函数:获取被私有化的属性的值
    #命名方式:getXxx
    #特点;需要设置返回值,将私有化属性的值返回
    def getAge(self):
        return self.__age
​
    #set函数:给私有化属性赋值
    #命名方式:setXxx
    #特点;需要设置参数,参数和被私有化的属性有关
    def setAge(self, age):
        #数据的过滤
        if age < 0:
            age = 0
        self.__age = age
​
    def getName(self):
        return self.__name
​
    def setName(self,name):
        self.__name = name
​
p3 = Person3("111",3)
p3.myPrint()   #111 3
print(p3.getAge())  #3
​
p3.setAge(10)
print(p3.getAge())
​
p3.setAge(-10)
print(p3.getAge())
​
p3.setName("222")
print(p3.getName())

4.@property装饰器

装饰器的作用:可以给函数动态的添加新的功能,对于类的成员函数,装饰器同样起作用

Python的内置装饰器@property的作用:将一个函数转换为属性进行使用【简化get函数和set函数】

使用:@property装饰器的作用相当于get函数,同时,会自动生成一个新的装饰器@属性名.setter,相当于set函数

注意:使用在类的成员函数中,可以简化代码,同时保证对参数的校验

代码演示:

#4.使用@property装饰器
class Person4():
    def __init__(self,name,age):
        self.__name = name
        self.__age = age   #私有化属性
​
    def myPrint(self):
        #在类的内部可以直接访问私有化属性
        print(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 = 0
        self.__age = age
​
    @property
    def name(self):
        return  self.__name
​
    @name.setter
    def name(self,name):
        self.__name = name
​
p4 = Person4("jack",4)
​
#@property本质:将函数在转换为属性使用
#获取值
print(p4.age)  #相当于调用了get函数【@property修饰的函数】,将被私有化的属性的值返回
#设置
p4.age = 100    #相当于调用了set函数【@age.setter修饰的函数】,将100作为参数传值
print(p4.age)
​
p4.name = "tom"
print(p4.name)

5.属性的不同形式

代码演示:

class Person5():
    def __init__(self,name,age):
        self.name = name
        self.__age = age   #私有化属性
​
    def myPrint(self):
        print(self.name,self.__age)
​
#1.属性私有化的工作原理
per = Person5("jack",55)
#per.__age:Python解释器将__age变成了_Person5__age
#可以通过对象._Person5__age去访问,但是不建议使用,不同的解释器可能存在解释的变量不一致的情况
#Python本身没有任何机制阻止你干坏事,一切全凭自觉
print(per._Person5__age)
​
#2.
class Person6():
    def __init__(self,name,age,height):
        self._name = name
        self.__age = age
        self.__height__ = height
​
​
p = Person6("tom",10,5.0)
#a.在变量的前面添加一个下划线,属于特殊变量,则认为该变量受保护的
#特点:在类的外面也可以直接访问,但是不建议使用
print(p._name)
​
#b.在变量的前后各添加两个下划线,属性特殊变量,一般认为这种变量都是系统的内置变量或者内置函数
# 【__name__、__init__、__del__   】
#特点:在类的外面也可以直接访问,但是不建议使用
print(p.__height__)
​
"""
【面试题:解释下面不同变量的含义】
xxx:普通变量
_xxx;受保护的变量,自定义变量不建议使用
__xxx:私有变量,在外界不能直接被访问
__xxx__:系统的内置变量,自定义变量不建议使用
"""

6.私有函数

类中的成员函数也可以被私有化

写法:在函数名的前面添加两个下划线【函数名就是一个变量名】,此时,该函数被称为私有函数

特点:只能在当前类中被直接调用

代码演示:

class Site():
    def __init__(self,name):
        self.name = name
​
    def func(self):
        print("这是一个普通【公共】函数")
        #在公共函数中将私有函数调用,d调用格式:self.__私有的函数名称(参数列表)
        self.__func1()
​
    def __func1(self):
        print("这是一个私有函数")
​
​
s = Site("千锋")
s.func()
#s.__func1()

四、继承

1.概念

如果两个或者两个以上的类具有相同的特征【属性】和行为【成员函数】,我们可以抽取一个类出来,在抽取出来的类中声明公共的部分

被抽取出来的类:父类,超类,基类

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

他们之间的关系:子类 继承自 父类 / 父类 派生出了 子类

作用:简化代码,提高了代码的复用性和可维护性

extends

2.单继承

一个子类只能有一个父类,被称为单继承

语法:

父类:

class 父类类名(object):

​ 类体【公共部分】

子类:

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

​ 类体【子类特有的部分】

注意:object是所有类的父类

代码演示:

测试文件

from  extends01.person import Person
from  extends01.student import Student
from  extends01.worker import Worker
​
#1.创建父类的对象
p = Person("lisi",10)
print(p.name,p.age)
#print(p.name)
p.show()
​
#2.创建子类的对象
#注意:子类可以继承父类中的公共的成员变量和成员函数
w1 = Worker("aaa",1)
#w1.age能正常使用:默认调用了父类中的被@property修饰的函数
print(w1.name,w1.age)
w1.show()
​
#3.子类除了继承父类中的成员变量和成员的函数之外,还可以有特有的成员变量和成员函数
s = Student("bob",18,"语文")
s.show()
s.test()
​
#4.子类对象可以访问父类中的公共的成员变量和成员函数,反之,父类对象无法访问子类中特有的成员变量和成员函数
p.test()

父类:

#定义父类
#注意;如果没有显式的规定父类,则这个类的父类默认为object
class Person(object):
    #成员变量
    def __init__(self,name,age):
        self.name = name
        self.__age = age
​
    #成员函数
    def show(self):
        print("父类中的show被调用")
​
    @property
    def age(self):
        return self.__age
​
    @age.setter
    def age(self, age):
        self.__age = age

子类:

from  extends01.person import Person
​
#定义子类
class Worker(Person):
    def __init__(self,name,age):
        """
        self.name = name
        self.age = age
        """
        #在子类中调用父类中的构造函数,主要是为了将父类中现有的成员变量应用到子类中
        #方式一:super(当前类,self).__init__(属性列表)
        #注意:super:和父类有关【父类的引用】
        #super(Worker,self).__init__(name,age)
        #方式二:父类名.__init__(self,属性列表)
        #Person.__init__(self,name,age)
        #方式三:super().__init__(属性列表)
        super().__init__(name,age)
​
        #说明:上述三种写法都可以使用,作用是一样的,目的都是为了调用父类的构造函数
​
​
from  extends01.person import Person
​
#定义子类
class Student(Person):
    def __init__(self,name,age,subject):
        super().__init__(name,age)
        self.subject = subject
​
​
    def test(self):
        print("testing")

总结:

继承的特点:

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

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

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

继承的优缺点:

优点:

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

​ b.提高代码的可维护性

​ c.提高代码的安全性

​ d.是多态的前提

缺点:

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

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

3.多继承

一个子类可以有多个父类

注意:不能为了使用某个类中的某些功能,而刻意去实现继承

代码演示:

#多继承
class Father1(object):
    def __init__(self,money):
        self.money  = money
    def play(self):
        print("play")
    def func(self):
        print("func~~~~1111")
​
​
class Father2(object):
    def __init__(self, faceValue):
        self.faceValue = faceValue
    def eat(self):
        print("eat")
    def func(self):
        print("func~~~~2222")
​
class Child(Father2,Father1):
    def __init__(self,money,faceValue,hobby):
        self.hobby = hobby
        #注意:子类继承多个父类中的成员变量,需要分别调用父类中的构造函数
        Father1.__init__(self,money)
        Father2.__init__(self,faceValue)
​
    def show(self):
        print("show")
​
#创建一个子类的对象
c = Child(100,100,"打麻将")
print(c.money,c.faceValue,c.hobby)
c.play()
c.eat()
c.show()
c.func()
​
#注意;如果多个父类中存在重名的函数,当子类对象调用的时候,Python在父类列表中从左到右进行搜索,
#第一个存在指定函数的父类,则子类对象调用其中的函数

猜你喜欢

转载自blog.csdn.net/weixin_42569562/article/details/81809211