两大编程思想

面向过程
功能上的封装,典型代表:C语言
面次对象
属性和行为上的封装:典型代表Java和Pathon


类和对象

类:由N多个对象抽取出‘像’的属性和行为从而归纳总结出来的一种类别

在Pathon中一切皆对象

相当于先有个表格模板,再打印出纸张,然后进行填写

点击查看代码
示例9-1查看对象的数据类型
a=10
b=9.8
s='hello'
print(type(a))
print(type(b))
print(type(s))

1、自定义数据类型的语法结构为

calss 类名():
    pass
#类名首字母大写

2、创建对象的语法格式为:
对象名=类名()

1、类的方法也可以叫做类的行为,也是在类中调用的函数
2、类中函数在调用类的属性时需要self打点调用,但可以直接调用自身参数

str方法使输入转换为字符串,直接对对象使用str得到的是内存地址
lt方法进行小于和大于比较

点击查看代码
示例9-2自定义数据类型
#编写一个Person
class Person:
    pass
#编写一个Cat类
class Cat:
    pass

#编写一个Dog类
class Dog:
    pass

#编写一个Student类
class Student():
    pass
示例9-3创建自定义类型的对象
#编写一个Person
class Person:
    pass
#编写一个Cat类
class Cat:
    pass

#编写一个Dog类
class Dog:
    pass

#编写一个Student类
class Student():
    pass

#创建类的对象
#对象名=类名()

#创建一个Person类型的对象
per=Person()#per就是Person类型的对象
c=Cat()#c就是Cat类型的对象
d=Dog()#d就是Dog类型的对象
stu=Student()#stu就是Student类型的对象

print(type(per))
print(type(c))
print(type(d))
print(type(stu))

函数和方法的形参类型注释语句:
def 函数方法名(形参名:类型,形参名:类型):
  pass
函数返回值添加注解:
def 函数方法名(形参:类型,...,形参名:类型)->返回值类型:
     pass 
点击查看代码
示例9-4类属性和实例属性的定义
class Student():
    #类属性,定义在类中,方法外的变量
    school='北京XXX教育'
     #初始化方法(类的行为)
    def __init__(self,xm,age):#xm,age是方法的参数,是局部变量,xm,age的作用域在__int__方法
        self.name=xm #=左侧是实例属性,xm是局部变量,将局部变量的值xm赋值给实例属性self.name
        self.age=age #实例对象和局部变量的名称可以相同
        
示例9-5类的组成
class Student():
    #类属性,定义在类中,方法外的变量
    school='北京XXX教育'
     #初始化方法
    def __init__(self,xm,age):#xm,age是方法的参数,是局部变量,xm,age的作用域在__int__方法
        self.name=xm #=左侧是实例属性,xm是局部变量,将局部变量的值xm赋值给实例属性self.name
        self.age=age #实例对象和局部变量的名称可以相同

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

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

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


#创建类的对象
stu=Student('ysj',18)#为什么传了两个参数,因为__int__方法中,有两个形参.self,是自带的参数,无需手动传入
#实例属性,是使用对象名打点调用的
print(stu.name,stu.age)

#类属性,直接使用类名打点调用
print(Student.school)

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

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

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

示例9-6编写学生类并创建4个学生对象
class Student():
    #类属性,定义在类中,方法外的变量
    school='北京XXX教育'
     #初始化方法
    def __init__(self,xm,age):#xm,age是方法的参数,是局部变量,xm,age的作用域在__int__方法
        self.name=xm #=左侧是实例属性,xm是局部变量,将局部变量的值xm赋值给实例属性self.name
        self.age=age #实例对象和局部变量的名称可以相同

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

#根据’图纸‘可以创建出N多个对象
stu=Student('ysj','18')
stu2=Student('陈玫玫','20')
stu3=Student('玛丽',21)
stu4=Student('Marry',23)#等号右侧都是Student()

print(type(stu))
print(type(stu2))
print(type(stu3))
print(type(stu4))

Student.school=('派森教育') #给类的类属性赋值

#将学生对象存储到列表中
lst=[stu,stu2,stu3,stu4]#列表中的元素是Student类型的对象
for item in lst:#item的hi列表中的元素,是Student类型的对象
    item.show() #对象名打点调用实例方法



动态绑定属性和方法

每个对象的属性名称相同,但属性值不同
可以为某个对象绑定独有属性和方法

点击查看代码
示例9-7动态绑定属性和方法
class Student():
    #类属性,定义在类中,方法外的变量
    school='北京XXX教育'
     #初始化方法
    def __init__(self,xm,age):#xm,age是方法的参数,是局部变量,xm,age的作用域在__int__方法
        self.name=xm #=左侧是实例属性,xm是局部变量,将局部变量的值xm赋值给实例属性self.name
        self.age=age #实例对象和局部变量的名称可以相同

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

#创建两个Student类别的对象
stu=Student('ysj',18)
stu2=Student('陈玫玫',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()


面向对象的三大特征

1、封装

点击查看代码
示例9-8权限控制
class Student():
    #首尾双下划线
    def __init__(self,name,age,gender):
        self._name=name  #self.name受保护,只能本类和子类访问
        self.__age=age  # self.__age表示私有的,只能类本身去访问
        self.gender=gender #普通的实例属性,类的内部,外部及子类都可以访问

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

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

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

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

#调用受保护的实例方法
stu._fun1()#子类及本身可以访问
#私有方法
#stu.__fun2()#AttributeError: 'Student' object has no attribute '__fun2'. Did you mean: '_fun1'?
print(stu._Student__age) #为什么可以这样访问?
stu._Student__fun2()

print(dir(stu))

示例9-9属性的设置
class Student:
    def __init__(self, name,gender):
        self.name = name
        self.__gender = gender # self.__gender私有的实例属性

    #使用@property修饰方法,将方法转成属性使用
    @property
    def gender(self):
        return self.__gender

    #将gender这个属性设置为可写属性
    @gender.setter
    def gender(self,value):
        if value != '男' and value!='女':
            print('性别有误,已将性别默认设置为男')
            self.__gender = '男'
        else:
            self.__gender = value

stu=Student('陈玫玫','女')
print(stu.name,'的性别是',stu.gender)#stu.gender就会去执行stu.gender()

#尝试修改属性值
#stu.gender='男'#AttributeError: property 'gender' of 'Student' object has no setter

stu.gender='其他'
print(stu.name,'的性别是',stu.gender)

思考:在类外,私有实例属性要通过类进行调用,不可以直接调用,如果要直接调用应使用@property修饰方法,将方法转成属性使用,注意属性不能直接修改,要在类中通过setter更改(私有不可见)

2、继承

class 类名(父类1,父类2......,父类N)
          pass
点击查看代码
示例9-10继承
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)#调用父类初始化方法为name和age赋值
        self.stuno = stuno

#Doctor继承Person类
class Doctor(Person):
    def __init__(self,name,age,department):
        super().__init__(name,age)
        self.department = department



#创建第一个子类
stu=Student('陈玫玫',20,'1001')
stu.show()
doctor=Doctor('张一一',32,'外科')
doctor.show()

示例9-11多继承
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('陈玫玫',20,'女')#调用Son类的__init__执行
son.showA()
son.showB()


点击查看代码
示例9-12方法重写
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)#调用父类初始化方法为name和age赋值
        self.stuno = stuno

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

#Doctor继承Person类
class Doctor(Person):
    def __init__(self,name,age,department):
        super().__init__(name,age)
        self.department = department
    def show(self):
        #super().show()#调用父类show的方法
        print(f'大家好,我叫:{self.name},我今年{self.age}岁,我的工作科室是:{self.department}')



#创建第一个子类
stu=Student('陈玫玫',20,'1001')
stu.show()#调用子类自己的show方法
doctor=Doctor('张一一',32,'外科')
doctor.show()#调用子类自己的show方法

3、多态

点击查看代码
示例9-13多态
class Person():
    def eat(self):
        print('人,吃五谷杂粮')

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

class Dog():
    def eat(self):
        print('狗,喜欢啃骨头')

#这三个类都有一个同名方法
#编写函数
def fun(obj):#obj是函数的形式参数,在定义处知道这个形参的数据类型吗?
    obj.eat()#通过变量obj()调用eat方法

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

#调用fun函数
fun(per) #Python中的多态,不关心对象的数据类型,只关心对象是否具有同名方法
fun(cat)
fun(dog)



Union联合类型注解

from typing import Union
Union[类型,....,类型]
示例
#使用Union类型,必须先导包
from typing import Union
my_list:list[Union[int,str]]=[1,2,'itheima','itcast']
def func(data:Union[int,str])->Union[int,str]:
    pass


object类

点击查看代码
示例9-14查看指定类的属性
class Person(object):
    def __init__(self, name,age):
        self.name = name
        self.age = age
    def show(self):
        print(f'大家好,我叫{self.name},我今年{self.age}岁')


#创建Person类的对象
per=Person('陈玫玫',20)#创建对象是会自动调用__init__方法
print(dir(per))

print(per)#自动调用了__str__方法

示例9-15__str__方法重写之前
class Person(object):
    def __init__(self, name,age):
        self.name = name
        self.age = age

#创建Person的对象
per=Person('陈玫玫',20)
print(per)
示例9-16__str__方法重写之后
class Person(object):
    def __init__(self, name,age):
        self.name = name
        self.age = age
    def __str__(self):
        return '这是一个人类,具有name和age两个实例属性' #返回值是一个字符串

#创建Person的对象
per=Person('陈玫玫',20)
print(per) #还是内存地址吗?不是,__str__方法中的内容  直接输出对象名,实际上是调用__str__方法
print(per.__str__()) #手动调用

点击查看代码
示例9-17特殊方法
a=10
b=20
print(dir(a))#Python中一切皆对象
print(a+b)#执行加法操作
print(a.__add__(b))
print(a.__sub__(b))#执行减法运算
print(f'{a}<{b}吗',a.__lt__(b))
print(f'{a}<={b}吗',a.__le__(b))
print(f'{a}={b}吗',a.__eq__(b))
print('-'*40)
print(f'{a}>{b}吗',a.__gt__(b))
print(f'{a}>={b}吗',a.__ge__(b))
print(f'{a}!={b}吗',a.__ne__(b))
print('-'*40)
print(a.__mul__(b))  #乘法
print(a.__truediv__(b))#除法
print(a.__mod__(b)) #取余
print(a.__floordiv__(b))#整除
print(a.__pow__(2))#幂运算


特殊属性

点击查看代码
示例9-18特殊属性
class A:
    pass
class B:
    pass
class C(A,B):
    def __init__(self,name,age):
        self.name = name
        self.age = age

#创建类的对象
a=A()
b=B()
#创建C类的对象
c=C('陈玫玫',20)
print('对象a的属性字典:',a.__dict__) #对象的属性字典
print('对象b的属性字典:',b.__dict__)
print('对象c的属性字典:',c.__dict__)


print('对象a所属的类:',a.__class__)
print('对象b所属的类:',b.__class__)
print('对象c所属的类:',c.__class__)

print('A类的父类元组',A.__bases__)
print('B类的父类元组',B.__bases__)
print('C类的父类元组',C.__bases__)


print('A类的父类',A.__base__)
print('B类的父类',B.__base__)
print('C类的父类',C.__base__) #A类,如果继承了N个父类,结果只显示第一个父类

print('A类的层次结构',A.__mro__)
print('B类的层次结构',B.__mro__)
print('C类的层次结构',C.__mro__) #C类继承了A类,B类,间接继承了object


#子类列表
print('A类的子类列表',A.__subclasses__())#A的子类是C类
print('B类的子类列表',B.__subclasses__())
print('C类的子类列表',C.__subclasses__()) #[]



类的深拷贝与浅拷贝‘

点击查看代码
示例9-19类的深拷贝与浅拷贝
import copy


class CPU():
    pass
class Disk():
    pass
class Computer():
    #计算机使用cpu和硬盘组成
    def __init__(self, cpu, disk):
        self.cpu = cpu
        self.disk = disk


cpu=CPU()#创建了一个CPU对象
disk=Disk()#创建了一个硬盘对象
#创建一个计算机对象
com=Computer(cpu,disk)
#变量(对象)的赋值
com1=com
print(com,'子对象的内存地址:',com.cpu,com.disk)
print(com1,'子对象的内存地址:',com1.cpu,com1.disk)


#类的浅拷贝
print('-'*40)
com2=copy.copy(com)#com2是新产生的对象,com2的子对象cpu和disk不变
print(com,'子对象的内存地址:',com.cpu,com.disk)
print(com2,'子对象的内存地址:',com2.cpu,com2.disk)


#类的深拷贝
print('-'*40)
com3=copy.deepcopy(com)#com3是新产生的对象,com3的子对象cpu和disk也会重新创建
print(com,'子对象的内存地址:',com.cpu,com.disk)
print(com3,'子对象的内存地址:',com3.cpu,com3.disk)



点击查看代码
实战一
#我的思路
class Circle():
    def __init__(self, r):
        self.r = r

    def get_area(self):
        area =3.14 * self.r ** 2
        print('圆的面积为',area)

    def get_perimeter(self):
        perimeter = 2 *3.14*self.r
        print('圆的周长为', perimeter)

r= int(input('请输入圆的半径:'))
cir=Circle(r)
cir.get_area()
cir.get_perimeter()


print('-'*50)
#老师思路
class Circle():
    def __init__(self, r):
        self.r = r
    #计算面积的方法
    def get_area(self):
      #return 3.14*self.r**2
       return 3.14*pow(self.r,2)

    #计算圆的周长
    def get_perimeter(self):
        return 2*3.14*self.r

#创建对象
r=eval(input('请输入圆的半径:'))
c=Circle(r)
#调用方法
area=c.get_area()
perimeter=c.get_perimeter()
print('圆的面积为:',area)
print('圆的周长为:',perimeter)


点击查看代码
#我的思路
class Student():
    def __init__(self, name, age,gender, score):
        self.name = name
        self.age = age
        self.gender = gender
        self.score = score


    def info(self):
        print(f'姓名为:{self.name}, 年龄为:{self.age}, 性别为:{self.gender},得分为: {self.score}')


print('请输入5位学生信息:(姓名#年龄#性别#成绩)')
lst=[]
new_lst=[]
for i in range(5):
    stu=input(f'请输入第{i+1}位学生信息:')
    lst.append(stu)
    s= lst[i].split('#')
    new_lst.append(s)

for i in range(0,len(new_lst)):
    stu1=Student(new_lst[i][0],new_lst[i][1],new_lst[i][2],new_lst[i][3])
    stu1.info()

print('-'*50)



#老师思路
class Student():
    def __init__(self, name, age,gender, score):
        self.name = name
        self.age = age
        self.gender = gender
        self.score = score


    def info(self):
        print(self.name,self.age,self.gender,self.score)


print('请输入5位学生信息:(姓名#年龄#性别#成绩)')
lst=[]#用于存储5个学生对象
for i in range(1,6):
    s=input(f'请输入第{i}位学生信息:')
    s_lst=s.split('#') #索引为0是姓名,索引为1是年龄,索引为2是性别,索引为3是成绩
    #创建学生对象
    stu=Student(s_lst[0],s_lst[1],s_lst[2],s_lst[3])
    #将学生对象添加到列表中
    lst.append(stu)

#遍历列表,调用学生对象的info方法
for item in lst: #item的数据类型是Student类型
    item.info() #对象名.方法名()


点击查看代码
实战三


class Instrument():
    def make_sound(self):
        pass


class Erhu(Instrument):
    def make_sound(self):
        print('二胡在演奏')

class Piano(Instrument):
    def make_sound(self):
        print('钢琴在演奏')

class Violin(Instrument):
    def make_sound(self):
        print('小提琴在演奏')

#编写一个函数
def play(obj):
    obj.make_sound()


#测试
er=Erhu()
piano=Piano()
vio=Violin()


#调用方法
play(piano)
play(vio)
play(er)


点击查看代码
实战四
#我的思路
class Car():
    def __init__(self,car_model,license_plate):
        self.car_model=car_model
        self.license_plate=license_plate

    def start(self):
        pass

    def stop(self):
        pass

class Taix(Car):
    def __init__(self,car_model,license_plate,company):
        self.company=company
        super().__init__(car_model, license_plate)

    def start(self):
        print('乘客您好!')
        print(f'我是{self.company}出租车公司的,我的车牌号是{self.license_plate},您要去哪里?')

    def stop(self):
        print('目的地到了,请您付款下车,欢迎下次乘坐')


class PrivateCar(Car):
    def __init__(self,car_model,license_plate,carname):
        self.carname=carname
        super().__init__(car_model, license_plate)

    def start(self):
        print(f'我是{self.carname},我的汽车我做主')

    def stop(self):
        print('目的地到了,我们去玩吧')

ta=Taix('计程车','京A88888','长城')
ta.start()
ta.stop()
print('-'*50)
pri=PrivateCar('面包车','云A4564','武大郎')
pri.start()
pri.stop()

#老师的思路
class Car():
    def __init__(self,type,no,):
        self.type = type
        self.no = no

    def start(self):
        print('我是车,我能启动')

    def stop(self):
        print('我是车,我能停止')


#出租车
class Taxi(Car):
    def __init__(self,type,no,company):
        super().__init__(type,no)
        self.company = company
    #重写父类的启动与停止
    def start(self):
        print('乘客您好!')
        print(f'我是{self.company}出租车公司的,我的车牌号是{self.no},您要去哪里?')

    def stop(self):
        print('目的地到了,请您付款下车,欢迎下次乘坐')


class Family(Car):
    def __init__(self,type,no,name):
        super().__init__(type,no)
        self.name = name

    def start(self):
        print(f'我是{self.name},我的汽车我做主')

    def stop(self):
         print('目的地到了,我们去玩吧')

#测试
taix=Taxi('上海大众','京A88888','长城')
taix.start()
taix.stop()
print('-'*50)
family_car=Family('广汽丰田','京B66666','武大郎')
family_car.start()
family_car.stop()

点击查看代码
练习
class Iphon:
    def __init__(self,_is_5g_enable):
       self._is_5g_enable=_is_5g_enable
    def _check_5g(self):
        _is_5g_enable=bool(self._is_5g_enable)
        if _is_5g_enable==True:
            print('开启5g')
        else:
            print('5g关闭,使用4g网')
    def call_by_5g(self):
        self._check_5g()
        print('正在通话中')

ip=Iphon(1)
ip.call_by_5g()


数据分析案例

点击查看代码
创建数据处理包
例data_define
class Record:
    def __init__(self,date, order_id, money, province):
        self.date = date
        self.order_id = order_id
        self.money = money
        self.province = province

    def __str__(self):
        return f"{self.date}, {self.order_id}, {self.money}, {self.province}"
例file_define
from data_define import Record
import json
class FileReader:

    def read_data(self) -> list[Record]:
        """读取文件的数据,读到的每一条数据都转换为Record对象,将它们都封装到list内返回即可"""
        pass

class TextFileReader(FileReader):

    def __init__(self, path):
        self.path = path            # 定义成员变量记录文件的路径

    # 复写(实现抽象方法)父类的方法
    def read_data(self) -> list[Record]:
        f = open(self.path, "r", encoding="UTF-8")

        record_list: list[Record] = []
        for line in f.readlines():
            line = line.strip()     # 消除读取到的每一行数据中的\n
            data_list = line.split(",")
            record = Record(data_list[0], data_list[1], int(data_list[2]), data_list[3])
            record_list.append(record)

        f.close()
        return record_list

class JsonFileReader(FileReader):

    def __init__(self, path):
        self.path = path            # 定义成员变量记录文件的路径


    def read_data(self) -> list[Record]:
        f = open(self.path, "r", encoding="UTF-8")

        record_list: list[Record] = []
        for line in f.readlines():
            data_dict = json.loads(line)
            record = Record(data_dict["date"], data_dict["order_id"], int(data_dict["money"]), data_dict["province"])
            record_list.append(record)

        f.close()
        return record_list



if __name__ == '__main__':
    text_file_reader = TextFileReader("D:/ruanjian/Pycharm/资料/2011年1月销售数据.txt")
    json_file_reader = JsonFileReader("D:/ruanjian/Pycharm/资料/2011年2月销售数据JSON.txt")
    list1 = text_file_reader.read_data()
    list2 = json_file_reader.read_data()

    print(list1)
    print(list2)



例main
from file_define import FileReader,TextFileReader,JsonFileReader
from data_define import Record
from pyecharts.charts import Bar, Line
from pyecharts.options import  *
from pyecharts.globals import ThemeType
text_file_reader = TextFileReader("D:/ruanjian/Pycharm/资料/2011年1月销售数据.txt")
json_file_reader = JsonFileReader("D:/ruanjian/Pycharm/资料/2011年2月销售数据JSON.txt")

jan_data:list[Record]= text_file_reader.read_data()
feb_data:list[Record]= json_file_reader.read_data()
#将两个月份的数据合并为1个list来储存
all_data:list[Record]= jan_data+feb_data

# 开始数据计算
# {'2011-01-01':1534,'2011-01-02':300,...}
data_dict={}
for record in all_data:
    if record.date in data_dict.keys():
        #当前日期已有记录,所以和老记录做累加即可
        data_dict[record.date]+=record.money
    else:
        data_dict[record.date]=record.money


#可视化图表开发
bar = Bar(init_opts=InitOpts(theme=ThemeType.LIGHT))
bar.add_xaxis(list(data_dict.keys()))
bar.add_yaxis('销售额',list(data_dict.values()),label_opts=LabelOpts(is_show=False))
bar.set_global_opts(
    title_opts=TitleOpts(title='每日销售额')

)
bar.render("2011年销售额.html")