python面向对象

今天开始学习第四章面向对象了

数据类型——类——存储什么数据     变量——对象——实际存储数据

变量——属性——保存哪些数据          函数——方法——一个类支持哪些操作 

 类的定义

class Student:#定义了一个类
    pass#什么也不执行
if __name__=='__main__':
    stu=Student()#定义类中一个对象
    print(stu)
#stu是Student的一个对象,这个对象所占的内存空间的首地址
<__main__.Student object at 0x000001F93F055DE0>

# 类属性定义及其访问

class Student:#定义一个类
    name='Unknown'#初始属性name为Unknown
if __name__=='__main__':
    print('第4行输出:',Student.name)#访问Student的属性并输出
    stu1=Student()#定义对象stu1
    stu2=Student()#定义对象stu2
    print('第7行输出:stu1 %s stu2 %s'%(Student.name,Student.name))#没有为对象的属性赋过值,则对象的属性与类的属性一致
    Student.name='未知'#重新定义类的属性为‘未知’
    print('第9行输出:',Student.name)
    print('第10行输出:stu1 %s stu2 %s'%(stu1.name,stu2.name))#两个对象的属性跟着类的属性变化而变化
    stu1.name='wang'#定义对象stu1的属性为‘wang’
    stu2.name='li'#定义对象stu2的属性为‘li’
    print('第13行输出:',Student.name)#对类中对象属性值更改并不会改变类的属性值
    print('第14行输出stu1 %s stu2 %s'%(stu1.name,stu2.name))#对两个对象的属性进行了重新定义,所以发生改变
    Student.name='学生'#对类的属性重新定义
    print('第16行输出:',Student.name)
    print('第17行输出:stu1 %s stu2 %s'%(stu1.name,stu2.name))#为对象的属性赋过值,则该属性与类的属性相互独立   
第4行输出: Unknown
第7行输出:stu1 Unknown stu2 Unknown
第9行输出: 未知
第10行输出:stu1 未知 stu2 未知
第13行输出: 未知
第14行输出stu1 wang stu2 li
第16行输出: 学生
第17行输出:stu1 wang stu2 li

# 为对象动态绑定新属性 

class Student:#定义类
    name='Unknown'#初始属性
if __name__=='__main__':
    stu1=Student()#定义两个对象
    stu2=Student()
    stu1.age=19#为对象stu1动态绑定新的属性age
    print('stu1姓名:%s,年龄:%d'%(stu1.name,stu1.age))#访问对象stu1的两个属性
    #print('stu2年龄:',stu2.age)没有定义stu2的age属性
    #print('使用类名访问年龄属性:'Student.age)Student的属性只有name
stu1姓名:Unknown,年龄:19

# 类中普通方法定义及调用,方法分为普通方法与内置方法,内置方法会在特定情况下由系统自动执行

class Student:#定义类
    name='Unknown'#定义name属性
    def SetName(self,newname):#定义方法SetName
        self.name=newname#把self所在实例对象中的name属性赋为newname
    def PrintName(self):
        print('姓名:%s'%self.name)
if __name__=='__main__':
    stu1=Student()#定义对象
    stu2=Student()
    stu1.SetName('li')#调用方法SetName,self在实例对象stu1中,stu1中name属性赋值为newname:li
    stu2.SetName('ma')
    stu1.PrintName()#stu1对象中调用方法PrintName
    stu2.PrintName()
    #Student.SetName('未知')报错,普通方法必须通过实例对象调用,不能通过类名调用
    #Student.PrintName()
姓名:li
姓名:ma

# 私有属性:__属性名,类外访问必须在私有属性前加‘_类名’ 

class Student:#定义类
    name='未知'
    __id='未知'#定义私有属性
    def SetInfo(self,newname,newid):#定义方法SetInfo
        self.name=newname
        self.__id=newid
    def PrintInfo(self):
        print('姓名:%s,身份证号:%s'%(self.name,self.__id))#类定义结束
if __name__=='__main__':
    stu1=Student()#定义对象
    stu1.SetInfo('li',100)#stu1调用方法SetInfo,使得stu1中name属性为li,__id属性为100
    stu1.PrintInfo()#stu1调用方法PrintInfo
    #print('身份证号%s'%stu1.__id)报错,因为类外不能用对象直接引用私有属性,改为
    print('身份证号%s'%stu1._Student__id)#在类外引用私有属性,必须在私有属性前加上  _类名
    print('姓名:',stu1.name)#类外可以直接引用普通属性
姓名:li,身份证号:100
身份证号100
姓名: li
class Student:
    name='未知'
    __id='未知'#私有属性
    def SetInfo(self,newname,newid='unknown'):#方法与函数对应,所以里面的参数可以设置默认值
        self.name=newname
        self.__id=newid
    def PrintInfo(self):
        print('姓名:%s,身份证号:%s'%(self.name,self.__id))#类中调用私有属性不用在私有属性前加‘_类名’
if __name__=='__main__':
    stu1=Student()#定义对象
    stu1.SetInfo('li')#默认newid为unknown,调用方法
    stu1.PrintInfo()
姓名:li,身份证号:unknown

# 构造方法,内置方法之一,在特定情况:创建一个类的对象时下自动执行 

class Student:#定义类
    def __init__(self):#定义构造方法
        print('构造方法被使用')
        self.name='未知'
    def PrintInfo(self):
        print('姓名:%s'%self.name)
if __name__=='__main__':
    stu=Student()#创建类时自动执行__init__(self)方法,输出构造方法被使用,self实例对象stu,即stu的name属性为未知
    stu.PrintInfo()
构造方法被使用
姓名:未知
class Student:
    def __init__(self,name='未知'):#定义有默认参数的构造方法
        print('构造方法被调用')
        self.name=name
    def PrintInfo(self):
        print('姓名:',self.name)
stu1=Student()#定义类中对象,构造方法被使用,stu1的name属性赋值为name,默认为未知
stu2=Student('li')
stu1.PrintInfo()
stu2.PrintInfo()
构造方法被调用
构造方法被调用
姓名: 未知
姓名: li

析构方法:内置方法,__del__,局部变量作用域结束、使用del删除对象、程序结束时所有对象都被销毁,这三种情况析构方法自动调用

class Student:#定义类
    def __init__(self,name):#定义构造方法
        self.name=name
        print('姓名为%s的对象被创建'%self.name)
    def __del__(self):#定义析构方法
        print('姓名为%s的对象被销毁'%self.name)#定义类结束
def func(name):#定义函数func
    stu=Student(name)#创建对象,由于这是定义函数没有调用,所以什么也不输出
if __name__=='__main__':
    stu1=Student('li')#定义对象,构造方法自动调用,stu1中name属性定义为li,输出创建
    stu2=Student('ma')#输出创建
    stu3=stu2#将stu2这个对象赋给stu3
    del stu2#删除stu2,对象Student(‘ma’)还存在与stu3中,所以不输出
    func('zhang')#一个对象,其实是函数被调用,输出创建,局部变量作用域结束了,输出销毁
    del stu3#Student(‘ma’)被删干净了,输出销毁
    stu4=Student('liu')#liu创建,程序结束,所有变量销毁

 姓名为li的对象被创建
姓名为ma的对象被创建
姓名为zhang的对象被创建
姓名为zhang的对象被销毁
姓名为ma的对象被销毁
姓名为liu的对象被创建
姓名为li的对象被销毁
姓名为liu的对象被销毁

# 常用内置方法:__str__:调用python内置函数format()、print()时自动调用,返回字符串

class Complex:#定义类
    def __init__(self,real,image):#定义构造方法
        self.real=real
        self.image=image
    def __str__(self):#定义内置方法__str__
        return str(self.real)+'+'+str(self.image)+'i'#字符串拼接
if __name__=='__main__':
    c=Complex(4.2,7.5)#定义对象,__init__方法自动调用
    print(c)#__str__方法自动调用
4.2+7.5i

 比较运算的内置方法
__gt__(self,other)进行self>other时自动调用
__lt__(self,other)进行self<other时自动调用
__ge__(self,other)进行self>=other时自动调用
__le__(self,other)进行self<=other时自动调用
__eq__(self,other)进行self==other时自动调用
__ne__(self,other)进行self!=other时自动调用

class Student:
    def __init__(self,name,age):#构造方法
        self.name=name
        self.age=age
    def __le__(self,other):#self<=other
        return self.age<=other.age
if __name__=='__main__':
    stu1=Student('wang',22)#定义对象,__init__方法被调用
    stu2=Student('li',11)#定义对象,__init_-方法被调用
    print('wang的年龄小于等于li的年龄:',stu1<=stu2)#有比较<=,__le__被调用
wang的年龄小于等于li的年龄: False

# 继承:子类拥有父类的属性,方法

class Person:#定义类
    def SetName(self,name):#方法
        self.name=name#属性
class Student(Person):#person类的子类
    def SetSno(self,sno):#增加方法
        self.sno=sno#增加属性
class Teacher(Person):#person类的子类
    def SetTno(self,tno):
        self.tno=tno
class TA(Student,Teacher):#两个类student,teacher共同的子类
    def SetTeacher(self,teacher):
        self.teacher=teacher
if __name__=='__main__':
    stu=Student()#定义类Student中的对象
    stu.SetSno('1919191')#类Student中有方法SetSno,调用方法SetSno,stu的sno属性定义为sno=1919191
    stu.SetName('wang')#类Student继承父类Person中的方法SetName中的方法SetName,故可以调用
    print('学号:%s,姓名:%s'%(stu.sno,stu.name))
    t=Teacher()#定义类Teacher中的对象
    t.SetTno('90909090')#调用方法SetTno
    t.SetName('li')#Teacher是Person的子类,继承父类的方法,故可以调用
    print('教工号:%s,教师名:%s'%(t.tno,t.name))
学号:1919191,姓名:wang
教工号:90909090,教师名:li

# 方法重写和鸭子类型

class Person:#定义类
    def __init__(self,name):#构造方法
        self.name=name#属性
    def PrintInfo(self):#普通方法
        print('姓名:%s'%self.name)
class Student(Person):#子类
    def __init__(self,sno,name):#构造方法
        self.sno=sno
        self.name=name
    def PrintInfo(self):#普通方法
        print('学号:%s,姓名:%s'%(self.sno,self.name))
def PrintPersonInfo(person):#定义函数
    print('PrintPersonInfo函数中输出结果',end='#')
    person.PrintInfo()
if __name__=='__main__':
    p=Person('li')#Person类中的对象
    stu=Student('191919','li')#Student类中的对象
    p.PrintInfo()#对象p调用方法PrintInfo
    stu.PrintInfo()#对象stu调用方法PrintInfo
    PrintPersonInfo(p)#调用12行函数
    PrintPersonInfo(stu)#调用12行函数

姓名:li

学号:191919,姓名:li

PrintPersonInfo函数中输出结果#姓名:li

 PrintPersonInfo函数中输出结果#学号:191919,姓名:li

class Person:#定义类
    def CaptureImage(self):#定义方法
        print('Person类中的CaptureImage方法被调用')
class Camera:
    def CaptureImage(self):#定义方法,只是名字相同,但这是两个不相关的函数
        print('Camera类中的CaptureImage方法被调用')
def CaptureImageTest(arg):#定义了一个函数,传递实参前其参数类型不确定
    arg.CaptureImage()
if __name__=='__main__':
    p=Person()#定义对象
    c=Camera()#定义对象
    CaptureImageTest(p)#调用第7行函数
    CaptureImageTest(c)
Person类中的CaptureImage方法被调用
Camera类中的CaptureImage方法被调用

 # super方法:super(A,self)获取A的父类代理对象,获取父类代理对象中的self绑定到当前子类A的对象self上

class Person:
    def __init__(self,name):
        print('Person类构造方法被调用')
        self.name=name
class Student(Person):
    def __init__(self,sno,name):
        print('Student类被调用')
        super().__init__(name)#调用父类构造方法
        self.sno=sno#pg的sno属性赋值为sno
class Postgraduate(Student):
    def __init__(self,sno,name,tutor):
        print('Postgraduate类构造方法被调用')
        super().__init__(sno,name)#调用父类构造方法
        self.tutor=tutor#self对应对象tutor属性值赋值为tutor
if __name__=='__main__':
    pg=Postgraduate('1919919','li','ma')#Postgraduate类中的对象
    print('学号%s,姓名%s,教师%s'%(pg.sno,pg.name,pg.tutor))
Postgraduate类构造方法被调用
Student类被调用
Person类构造方法被调用
学号1919919,姓名li,教师ma
class Person:
    def __init__(self,name):
        print('Person类构造方法被调用')
        self.name=name
class Student(Person):
    def __init__(self,sno,name):
        print('Student类被调用')
        super().__init__(name)#调用父类构造方法
        self.sno=sno#pg的sno属性赋值为sno
class Postgraduate(Student):
    def __init__(self,sno,name,tutor):
        print('Postgraduate类构造方法被调用')
        super(Postgraduate,self).__init__(sno,name)#调用父类构造方法
        self.tutor=tutor#self对应对象tutor属性值赋值为tutor
if __name__=='__main__':
    pg=Postgraduate('1919919','li','ma')#Postgraduate类中的对象
    print('学号%s,姓名%s,教师%s'%(pg.sno,pg.name,pg.tutor))
Postgraduate类构造方法被调用
Student类被调用
Person类构造方法被调用
学号1919919,姓名li,教师ma

# 内置函数isinstance(一个对象所属的类是否是指定类或其子类)、issubclass(一个类是否是另一个类的子类)、type(一个对象所属的类)

class Person:
    pass
class Student(Person):
    pass
class Flower:
    pass
if __name__=='__main__':
    stu=Student()
    f=Flower()
    print('stu是Person类或其子类对象:',isinstance(stu,Person))
    print('stu是Student类或其子类对象',isinstance(stu,Student))
    print('f是Person类或其子类对象',isinstance(f,Person))
    print('Student是Person类的子类',issubclass(Student,Person))
    print('Flower是Person类的子类',issubclass(Flower,Person))
    print('stu对象所属的类',type(stu))
    print('f对象所属的类',type(f))
    print('stu是Person类对象',type(stu)==Person)
    print('stu是Student类对象',type(stu)==Student)
stu是Person类或其子类对象: True
stu是Student类或其子类对象 True
f是Person类或其子类对象 False
Student是Person类的子类 True
Flower是Person类的子类 False
stu对象所属的类 <class '__main__.Student'>
f对象所属的类 <class '__main__.Flower'>
stu是Person类对象 False
stu是Student类对象 True

# 类方法@classmethod与静态方法@staticmethod

class Complex:
    def __init__(self,real=0,image=0):
        self.real=real
        self.image=image
    @classmethod#定义类方法add
    def add(cls,c1,c2):
        print(cls)#类方法第一个变量为类本身Complex
        c=Complex()
        c.real=c1.real+c2.real
        c.image=c1.image+c2.image
        return c
if __name__=='__main__':
    c1=Complex(1,1.2)
    c2=Complex(2.2,6.4)
    c=Complex.add(c1,c2)#直接使用类名调用类方法add,普通方法只能通过实例对象调用
    print('c1,c2的和为%.2f+%.2f'%(c.real,c.image))
<class '__main__.Complex'>
c1,c2的和为3.20+7.60
class Complex:
    def __init__(self,real=0,image=0):
        self.real=real
        self.image=image
    @classmethod#定义类方法add
    def add(cls,c1,c2):
        print(cls)#类方法第一个变量为类本身Complex
        c=Complex()
        c.real=c1.real+c2.real
        c.image=c1.image+c2.image
        return c
if __name__=='__main__':
    c1=Complex(1,1.2)
    c2=Complex(2.2,6.4)
    c=c1.add(c1,c2)#也可以通过实例对象调用:c=c2.add(c1,c2),c=Complex().add(c1,c2)
    print('c1,c2的和为%.2f+%.2f'%(c.real,c.image))
<class '__main__.Complex'>
c1,c2的和为3.20+7.60
class Complex:
    def __init__(self,real=0,image=0):
        self.image=image
        self.real=real
    @staticmethod#定义静态方法add
    def add(c1,c2):#与类方法不同的是静态方法不需要第一个为所在类的类参数
        c=Complex()
        c.real=c1.real+c2.real
        c.image=c1.image+c2.image
        return c
if __name__=='__main__':
    c1=Complex(1,2.5)
    c2=Complex(2.2,4.4)
    c=Complex.add(c1,c2)#通过类直接调用静态方法
    print('c1,c2的和为%.2f+%f'%(c.real,c.image))
c1,c2的和为3.20+6.900000

# 动态扩展类和__slots__变量

from types import MethodType#从types模块引方法
class Student:
    pass
def SetName(self,name):#定义函数
    self.name=name
def SetSno(self,sno):
    self.sno=sno
if __name__=='__main__':
    stu1=Student()#定义Student对象
    stu2=Student()
    stu1.SetName=MethodType(SetName,stu1)#stu1定义新方法SetName。MethodType(方法名,对象名)
    Student.SetSno=SetSno#为类定义新方法
    stu1.SetName('li')#对象stu1有SetName方法
    stu1.SetSno('191991')#类有方法SetSno,所以对象stu1可以引用方法SetSno
    #stu2.SetName('zhang'),stu2没有SetName方法
    stu2.SetSno('181818')#类有方法SetSno,所以对象stu2可以引用方法SetSno
    print(stu1.name,stu1.sno,stu2.sno)
li 191991 181818
#__slots__:限制可动态扩展的属性
class Person:
    __slots__=('name')#类Person中的对象的属性只能为name
class Student(Person):
    __slots__=('sno')
class Postgraduate(Student):
    pass
if __name__=='__main__':
    stu=Student()#stu为子类Student的对象
    stu.sno='1919191'#子类Student中属性可以为sno,也可以为其父类中属性name
    stu.name='li'
    #stu.tutor='ma'。stu在类Student中属性只能为name,sno
    pg=Postgraduate()#pg为类Postgraduate中的对象,可以随意定义新属性
    pg.sno='171717'
    pg.name='zhang'
    pg.tutor='ma'

# @property装饰器

import datetime#后面用到datetime包
class Student:
    @property#定义一个获取(getter)属性score值的方法
    def score(self):
        return self._score#在getter和setter中访问一个属性,需要在属性前加下划线
    @score.setter#对属性score设置(setter)一个值,@属性名.setter
    def score(self,score):
        if score<0 or score>100:
            print('成绩必须在0~100')
        else:
            self._score=score#为属性score赋值为score
    @property#定义一个获取属性age值的方法,没有setter设置值得方法,所以该属性是只读属性,不能设置该属性的值
    def age(self):
        return datetime.datetime.now().year-self.birthday
if __name__=='__main__':
    stu=Student()#stu为类Student的一个对象
    stu.score=80#stu在类Student中,有属性score,且可以赋值
    stu.birthday=2000#为对象stu定义属性值
    print('年龄%d,成绩%.2f'%(stu.age,stu.score))
    #stu.age=19。age属性只读,不能赋值
    stu.score=105
    print('年龄%d,成绩%.2f'%(stu.age,stu.score))

年龄23,成绩80.00
成绩必须在0~100
年龄23,成绩80.00

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值