大一新生数据科学与大数据技术专业学生在校学习记录之python的类与对象(三)

作者苦恼于python中的类的学习但是经过几日的潜心学习,基本上了解差不多,

总所周知,编程语言分为两大编程思想,分别为面向过程和面向对象,面向过程的语言比如C语言,主打功能上的封装;面向对象的语言比如python,Java,主打属性和行为上的封装,而python中的类与对象便是为面对对象量身定做

面向过程: 谓(主,宾)。面向对象:主 (谓,宾)。

比如说同样是我爱你,C语言注重的是爱这个动作的设计,而python注重的是我,你这两个人的交互。这就是为什么我们常听,面向对象更符合人的思维。

再举个例子,比如说把大象关进冰箱这个问题。

C语言(面向过程)会怎么干呢?首先创建一个描述大象的结构体类型和一个描述冰箱的类型,再分别写出计算大象体重,打包大象,把大象放进冰箱,开冰箱门和关冰箱门等等函数去实现。

而python(面向对象)会怎么干这件事情?首先创建一个大象类,把大象的特征和对大象的各种操作(方法)写在一起(封装),而对于冰箱也是一样。这样写的好处是,改明我不想把大象装进冰箱了,让其他动物装进去,由于其他动物与大象一样都是动物,具有很多相同点,可以让其他动物类型直接照搬大象的处理方法,而这种操作就叫做继承。会比面向过程减少很多冗余代码,增加开发效率。

那么何为对象呢?python中一切皆对象,不同的对象具有不同的数据类型比如常见的整型(int),浮点型(float),字符串型(str),

a=10
b=9.8
s='hello'
print(type(a))
print(type(b))
print(type(s))

而类就是由N多个对象抽取出来的“像”的属性和行为从而归结出来的一种类别,也可以理解为类为汽车图纸,对象为根据图纸制作出来的汽车;自定义类的语法结构为class类名():创建对象的语法结构语法结构为:对象名=类名

自定义数据类型:

#编写一个person
class person():
    pass

#编写一个cat
class cat():
    pass

创建自定义数据对象:

#编写一个person
class person():
    pass

#编写一个cat
class cat():
    pass
#创建类的对象
#对象名=类名()

#创建一个person类型的对象
per=person()#per为person的对象
c=cat()#c为cat的对象
print(type(per))
print(type(c))

我们通过type()函数可以看出对象的数据类型与我们创建的数据类型一致

类的组成,在类中属性即为我们常说的变量,方法为我们常说的函数,而类由类属性,实例属性,实例方法,静态方法,类方法组成。

类属性与实例属性的定义:类属性为定义在类内,方法外的变量;实例属性为定义在__init__方法中,使用self打点的变量

class student:
    #类属性:定义在类中,方法外的变量
    school='北京xxx学校'

    #初始化方法的方法
    def __init__(self,xm,age):#xm,age是方法的参数,是局部变量,其作用域是整个__init__方法
        self.name=xm #=左侧为实例变量,xm是局变量,将局部变量的值xm赋值给实例属性
        self.age=age#实例属性名称和局部变量的名称可以相同

那么,三种方法,实例方法,静态方法,类方法有什么区别呢?

实例方法:实例方法是最常见的方法类型,用于操作实例的属性。它必须包含一个 self 参数,该参数代表类的实例。通过实例调用实例方法,会自动传入实例参数。

类方法:类方法是使用 @classmethod 装饰器定义的方法,用于操作类级别的属性。它必须包含一个 cls 参数,该参数代表类本身。可以通过类名或实例调用类方法。

静态方法:
静态方法是使用 @staticmethod 装饰器定义的方法,它与类和实例无关。静态方法不接受特殊的第一个参数(self 或 cls),因此无法直接访问实例变量或类变量。

类的组成:

class student:
    # 类属性:定义在类中,方法外的变量
    school = '北京xxx学校'

    # 初始化方法的方法
    def __init__(self, xm, age):  # xm,age是方法的参数,是局部变量,其作用域是整个__init__方法
        self.name = xm  # =左侧为实例变量(在整个类中使用的),xm是局变量,将局部变量的值xm赋值给,实例属性
        self.age = age  # 实例属性名称和局部变量的名称可以相同

        #定义在类中的函数,称为方法,自带一个参数self
    def show(self):
        print(f'我叫:{self.name},今年:{self.age}')

    #静态方法
    @staticmethod
    def sm():
        #print(self.name)
        #print(self.show)
        print('这是一个静态方法不能调用实例属性,也不能调用实例方法')

    #类方法
    @classmethod
    def cm(cls):#cls-->class的简写
        #print(self.name)
        #print(self.show)
        print('这是一个类方法,也不能调用实例属性,也不能调用实例方法')

#创建类的对象
st=student('wxb',18)#为啥传了两个参数,因为__init__方法中,有两个形式参数,self为自带的参数,无需手动传入
#实例属性,使用对象名进行打点调用
print(st.name,st.age)
#类属性,直接使用类名去打点调用
print(student.school)

#实例方法,使用对象名进行打点调用
st.show()

#类方法,@classmethod进行修饰的方法,直接使用类名打点调用
student.cm()

#静态方法@staticmethod进行修饰的方法,直接使用类名打点调用
student.sm()

 动态绑定属性和方法

当我们创建完成对象后想要给对象增加其他属性或者方法,因为python为动态语言因此可以十分容易的完成这一操作,上代码

class student:
    # 类属性:定义在类中,方法外的变量
    school = '北京xxx学校'

    # 初始化方法的方法
    def __init__(self, xm, age):  # xm,age是方法的参数,是局部变量,其作用域是整个__init__方法
        self.name = xm  # =左侧为实例变量,xm是局变量,将局部变量的值xm赋值给,实例属性
        self.age = age  # 实例属性名称和局部变量的名称可以相同

        #定义在类中的函数,称为方法,自带一个参数self
    def show(self):
        print(f'我叫:{self.name},今年:{self.age}')

#创建两个student类型函数
stu=student('wxb',20)
stu2=student('wmn',20)
print(stu.name,stu.age)
print(stu2.name,stu2.age)

#stu2动态绑定一个实例属性其独有的属性
stu2.gender='男'
print(stu2.name,stu2.age,stu2.gender)

#print(stu.gender)#AttributeError: 'student' object has no attribute 'gender'
#动态绑定方法
def introduce():
    print('我是一个普通的函数,我被动态绑定成了stu2对象的方法')
stu2.fun=introduce#函数的赋值
#fun就是stu2对象的方法
#调用
stu2.fun()

在代码中大家可以看到当我为stu2定义一个gender实例是如果将gende使用stu调用时会报错,因此定义实例时只能给一个对象使用,而动态绑定方法时可以同时给多个对象使用

面对对象的程序语言的三大特征

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

封装:

封装,意思就是把类的一些属性进行封装(“隐藏”),尽可能的避免直接访问对象一些属性,以保证其安全性,如果必须要访问这些属性,我们可以单独的提供一些接口(共有方法)进行访问,这样我们就可以避免因为直接访问属性信息造成的误操作。封装中的权限控制是通过属性或者方法添加下划线双下划线以及首尾双下划线来实现;

单下划线开头:以单下划线开头的属性或方法表示 protected 受保护的成员,这类成员被视为仅供内部使用,允许类本身和子类进行访问,但实际上它可以被外部代码访问。

双下划线开头:表示 private 私有的成员,这类成员只允许定义该属性或方法的类本身进行访问

首尾双下划线:一般表示特殊的方法

class Student():
    #首尾双下划线
    def __init__(self,name,age,gender):
        self._name = name#self._name受保护的,只能子类和本类访问
        self.__age = age#self.__age表示私有的,只能类本身访问
        self.gender = gender#普通的实例属性,类的内部外部,子类都能访问

    def _fun(self):#受保护的
        print('子类及本身可以访问')

    def __fun2(self):#私有的
        print('只有定义的类可以访问')

    def show(self):#普通实例方法
        self._fun()#类本身访问受保护的方法
        self.__fun2()#类本身访问私有方法
        print(self._name)#受保护的属性
        print(self.__age)#私有的实例属性

        #创建一个学生类的对象
stu=Student('wxb',20,'男')
#类的外部
print(stu._name)
#print(stu.__age)#AttributeError: 'Student' object has no attribute '__age'. Did you mean: '_name'?

#调用受保护类的实例方法
stu._fun()#子类及本身可以访问
#stu.__fun2()#AttributeError: 'Student' object has no attribute '__fun2'. Did you mean: '_fun'?


#私有实例属性和方法的访问方法
print(stu._Student__age)

stu._Student__fun2()

print(dir(stu))

 在上面的代码中我们可以看到当对一些属性的进行权限设定时非法的访问方式会报错,那么我们如何对这些属性进行访问呢?我们可以输入dir()查看对象的属性使用属性对其进行访问,但是这个方法非常不建议使用

继承:

继承,在我们的生活中也有很多的继承关系,比如子承父业,在Python中,我们有继承的概念,比如我们经常说的Dog类继承于Animal类,动物类Animal具有自己的一些属性,Dog属于Animal的一种,所以具有Animal的一些属性,但是Dog也有自己的一些特定属性,这时候如果我们单独在重新创建一个类Dog,就需要重新写一遍Animal类的属性,既费时又不好维护,这时候我们就可以使用继承,使用Dog类继承Animal类,这时候,Dog就包含了Animal类的一些属性,就不需要我们多次重复写这些属性了。

从上面的文字中可以看出几个关键

1.一个子类可以继承多个父类

class Person:#默认继承了object
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def show(self):
        print(f'大家好,我叫{self.name} 我今年 {self.age}岁 ')

#使用student去继承person类
class Student(Person):
    #编写初始化的方法
    def __init__(self,name,age,stuno):
        super().__init__(name,age)#调用父类的初始化方法
        self.stuno = stuno#赋值

#继承person类
class Doctor(Person):
    #编写初始化方法
    def __init__(self,name,age,department):
        super().__init__(name,age)
        self.department = department



#创建第一个子类对象
st=Student('wxb',20,5017230314)
st.show()
do=Doctor('wmn',40,'呼吸科')
do.show()

2.一个父类亦可以拥有多个子类(多继承)

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

    def showA(self):
        print('父类A中的方法')

class FatherB():
    def __init__(self,age):
        self.age = age
    def showB(self):
        print('父类B中的的方法')

#多继承
class Son(FatherA,FatherB):
    def __init__(self,name,age,gender):
        FatherA.__init__(self,name)
        FatherB.__init__(self,age)
        self.gender = gender



son=Son('wxb',20,'男')#调用Son中的__init__执行
son.showA()
son.showB()

3.如果一个类没有继承任何类,那么这个类默认继承的就是object类

方法重写:子类继承了父类就拥有了父类中公有成员和受保护的成员
父类的方法法并不能完全适合子类的需要求这个时候子类就可以重写父类的方法
子类在重新父类的方法时,要求方法的名称必须与父类方法的名称相同,在子类重写后的方法中可以通过 super (). xxx ()调用父类中的方法,可以理解为一个父亲将自己的两套房子分给自己的孩子,这就是继承,不同孩子的审美不同因此对继承的房子装修不同,这就是方法重写

class Person:#默认继承了object
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def show(self):
        print(f'大家好,我叫{self.name} 我今年 {self.age}岁 ')

#使用student去继承person类
class Student(Person):
    #编写初始化的方法
    def __init__(self,name,age,stuno):
        super().__init__(name,age)#调用父类的初始化方法
        self.stuno = stuno#赋值

    def show(self):
        #调用父类中的方法
        super().show()
        print(f'我来自xxx大学,我的学号是:{self.stuno}')


#继承person类
class Doctor(Person):
    #编写初始化方法
    def __init__(self,name,age,department):
        super().__init__(name,age)
        self.department = department

    def show(self):
        super().show()
        print(f'我来自xxx医院,我是{self.department}的医生')



#创建第一个子类对象
st=Student('wxb',20,5017230314)
st.show()#先调用子类自己的show方法
do=Doctor('wmn',40,'呼吸科')
do.show()#先调用子类自己的show方法

多态,的就是"多种形态",即便不知道一个变量所引用的对象到底是什么类型,仍然可以通过这个变量调用对象的方法。
在程序运行过程中根据变量所引用对象的数据类型,动态决定调用哪个对象中的方法。Python 语言中的多态,根本不关心对象的数据类型,也不关心类之间是否存在继承关系,只关心对象的行为(方法)。只要不同的类中有同名的方法,即可实现多态可以理解为一类事物有多种形态,比如动物类可以有猫,狗,猪等等

class Person():
    def eat (self):
        print('人吃五谷杂粮')


class Cat():
    def eat (self):
        print('小猫喜欢吃鱼')

class Dog():
    def eat (self):
        print('小狗喜欢啃骨头')
#这三个类中都有一个同名的方法,eat
#编写函数
def fun(obj):#obj是函数的形式函数,此处不知道形参的数据类型
    obj.eat()#通过变量obj(对象)调用eat方法

#创建三个类的对象
per=Person()
cat=Cat()
dog=Dog()

  • 33
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值