python3基础18

day18

类变量
 类变量是类的属性,此属性属于类,不属于类的实例

 作用:
  通常用来存储该类创建对象的共有属性
 说明:
  类变量可以通过该类直接访问
  类变量,可以通过类的实例直接访问,无法改变
  类变量可以通过此类的对象的__class__属性间接访问

 示例见: class_variable.py
         class_variable2.py

#此实例示意变量的定义和用法

class Human:
    total_count = 0  #类变量,用来记录Human对象的个数
    pas
#  类变量可以通过该类直接访问
print(Human.total_count) #访问类变量
Human.total_count += 1   #改变类变量
print(Human.total_count)  #1
#类变量,可以通过类的实例直接访问,,无法改变
h1 = Human()     #创建一个对象
print(h1.total_count)   # 0 借助于此类的实例访问类变量(类属性)
h1.total_count = 10000    #添加实例属性(变量),
print(h1.total_count)     #10000
print(Human.total_count)   # 1
print(dir())   #打印全局变量
# 类变量可以通过此类的对象的__class__属性间接访问
h1.__class__.total_count += 1  #Human.total_count += 1 
print(Human.total_count)   #2

#此示例示意用类变量示意Human对象的个数

class Human:
    total_count = 0  #类变量,用来记录Human对象的个数

    def __init__(self,n):
        self.name = n
        self.__class__.total_count += 1  #类变量加1操作
        print(n,'对象被创建')

    def __del__(self):
        print(self.name,'对象被销毁')
        self.__class__.total_count -= 1

L = []
L.append(Human('张飞'))
L.append(Human('关羽'))
print("当前人物个数是:",Human.total_count)

del L[1]
print('当前人物个数是:',Human.total_count)

类的文档字符串
 类内第一个没有赋值给任何变量的字符串为类的文档字符串
 类的文档字符串可以通过help()函数查看
 类的文档字符串绑定在类的__doc__属性上

交互模式
class Human:
    '''地球上的主宰者'''

help(Human)
Human.__doc__
Human.__dict__  
dir(Human)  #查看Human类中的各种属性

类的 __slots__列表
 作用:
  限定一个类创建的实例只有固定的属性(实例变量)
  不允许对象添加列表以外的实例属性(实例变量)
  防止用户因写错属性名而发生程序错误
 
 说明:
 1. __slots__属性绑定一个字符串列表
 2.含有__slots__属性的类所创建的实例对象没有__dict__属性,
   即 此实例不用字典来存储对象的实例属性

 示例见:slots.py

class Human:
    # 限定一个类创建的实例只有固定的属性(实例变量)
    __slots__ = ['name','age']   #限定实例变量是能有name,age两种类型
    
    def __init__(self,n,a):
        self.name = n
        self.age = a
    def info(self):
        print(self.name,'今年',self.age,'岁')

h1 = Human('小张',8)
h1.info()  #小张今年8岁

h1.Age = 9 #此处会出错,__slots__列表限定不能有此属性
h1.info() #小张今年8岁

类方法:(描述类的行为)

 类方法是用来描述类的行为的方法,类方法属于类,不属于类的实例对象

 说明:
  类方法需要使用@classmethod装饰器定义
  类方法至少有一个形参,第一个形参用于绑定类.约定写为'cls'
  类和该类的实例都可以调用类的方法
  类方法不能访问此类创建的对象的实例属性

 注:@classmethod把实例自动看成 实例.__class__
    不要直接操作类属性,在方法内操作,制定操作规则

 示例见:
  class_method.py

class A:
    v = 0  #类变量(类属性)

    @classmethod
    def get_v(cls): # 操作类变量
        return cls.v  #用cls访问类变量v

    @classmethod
    def set_v(cls,a):
        # v = a      #方法内的变量
        cls.v = a
print('A.v=',A.get_v()) #调用类方法得到类的变量的值
A.set_v(100)
print('A.v=',A.get_v())  #100

静态方法 @staticmethod
 静态方法是定义在类的内部的函数,此函数的作用域是类的内部

 说明:
  静态方法需要使用@staticmethod装饰器定义
  静态方法与普通函数定义相同,不需要传入self实例参数和cls类参数
  静态方法只能凭借该类或类创建的实例调用
  静态方法不能访问类变量和实例变量

 示例见:
  staticmethod.py

#此示例示意静态方法的定义和使用
class A:
    @staticmethod
    # 静态方法与普通函数定义相同,不需要传入self实例参数和cls类参数
    def mysdd(a,b):
        return a + b
        
# 静态方法只能凭借该类或类创建的实例调用
print(A.myadd(100,200))  #300
a = A()
print(a.myadd(300,400))  #700

练习一:
  用类来描述一个学生的信息,(可以修改之前的Student类)
  class Student:
      ....
  学生信息有:
   姓名  年龄  成绩

  将这些学生对象存于列表中,可以任意添加和删除学生
  1)打印出这些学生的个数
  2)打印出学生的平均成绩
  3)打印出学生的平均年龄
  (建议用类内的列表来存储学生信息)


class Student:
    L = []
    def __init__(self,n,a,s=0):
        self.name = n
        self.age = a
        self.score = s

    @classmethod
    def add_Student(L):
        cls.L.append(Student('小张',20,100))
        cls.L.append(Student('小照',18,90))
        cls.L.append(Student('小里',19,80))

    @classmethod
    def del_Student(cls):
        del cls.L[0]

    @classmethod
    def get_student_count(cls):
        return len(cls.L)

    @classmethod
    def get_avg_age(cls): 
        return sum(map(lambda obj:obj.age,L))/len(L)

    @classmethod
    def get_avg_score(cls):
        return sum(map(lambda obj:obj.score,L))/len(L)

Student.add_Student(L)
print('学生个数是:',Student.get_student_count(L))
print('学生的平均成绩是:',,Student.get_avg_score(L))
print('学生的平均年龄是:',,Student.get_avg_age(L))
Student.del_Student(L)
print('学生个数是:',Student.get_student_count(L))
print('学生的平均成绩是:',,Student.get_avg_score(L))
print('学生的平均年龄是:',,Student.get_avg_age(L))

继承 inheritance 和派生 derived

什么是继承/派生
  1.继承是从已有的类中派生出新的类,新类具有原类的数据属性和行 为,并能扩展新的行为
  2.派生类就是从一个已有的类中衍生出新的类,在新类的基本上添加新的属性和行为

为什么继承和派生
  继承的目的是延续旧类的功能
  派生的目的是在旧类的基础上改变原有的功能

名词:
  基类(base class)-------->原有类
  超类(super class)
  父类(father class)
  派生类(derived class)---->派生出来的新的类
  子类(child class)


单继承
  语法:
   class 类名(基类名):
      语句块
  说明:
   单继承是指派生类由一个基类衍生出来的新类
  示例见:
   inherit.py


继承派生机的作用:
  1.可以将一些共有功能加在基类中,实现代码共享
  2.在不改变基类的基础上改变原有功能

例如:
class Mylist(list):
    def say(self,what):
        print("说:",what)
L = Mylist()
print(L)   # L = []
L.append(10)
print(10)  #L = [10]
L.say("好")

练习二:
  思考:
  list类里只有append向末尾加一个元素的方法,但没有
  向列表头部添加元素的方法
  试想能否为列表在不改变原有功能的基础上添加一个
  insert_head(x),此方法能在列表的前部添加元素
class MyList(list):
    def insert_head(self,x):
        ....
myl = MyList(range(3,6))
print(myl)  #[3,4,5]
myl.insert_head(2)
print(myl)  #[2,3,4,5]
myl.append(6)
print(myl)  #[2,3,4,5,6]


class MyList(list):
    def insert_head(self,x):
        self[0:0] = [x]
        self.insert(0,x)
        

myl = MyList(range(3,6))
print(myl)  #[3,4,5]
myl.insert_head(2)
print(myl)  #[2,3,4,5]
myl.append(6)
print(myl)  #[2,3,4,5,6]


继承说明:
 python3 任何类都直接或间接的继承自object类
 object类是一切类的超类

类的__base__属性
 __base__属性用来记录此类的基类

print(object.__base__)   #None

python內建的类详见:
   >>>help(__builtins__)

覆盖 override
什么事覆盖:
  覆盖是指在有继承关系的类中,子类中实现了与基类同名的方法,
  在子类的实例调用该方法时,实际调用的是子类中的覆盖版本,
  这种现象叫覆盖
示例见:
  override.py

问题:
当覆盖发生时,子类对象如何调用父类中的覆盖方法?

调用方式:
  基类名.方法名(实例,实际调用传参,....)

b.work() #等同于B.work(b)


super函数
 super(cls,obj) 返回绑定超类的实例(要求obj必须为cls类型的实例)
 super()
 返回绑定超类的实例,等同于:super(__class__,实例方法的第一个参数,必须在方法内调用)

作用:
 借助super()返回的实例间接调用父类的覆盖方法

示例见:
 super.py

注:#方法外
   super(B,b).work()
   #B类中的实例b,当做是A类中的,来调用work
   #方法内
   super().work()#此种方式只能在实例方法内部调用
   super(B,self).work()
   super(self.__class__,self).work()

#此示例示意用super函数间接调用父类中


class A:
    def work(self):
        print("A.work被调用")

class B(A):
    '''B类继承自A类'''
    def work(self):
        print("B.work被调用!!!")
    def super_work(self):
        #调用B类自己的方法work方法
        self.work()
        #调用父类的work
        super(B,self).work()
        super(self.__class__,self).work()
        super().work()#此种方式只能在实例方法内部调用

b = B()
b.work()   #B.work被调用!!
super(B,b).work() #B类中的实例b,当做是A类中的,来调用work

显示调用基类初始化方法
 当子类中实现了__init__方法,基类的构造方法并不会被调用, 
 此时需要显示调用


示例见:
 super_init.py
#此示例示意显式调用初始化方法
#子类未改变父类的原有内容,由super在子类中调用父类方法

class Human:
    def __init__(self,n,a):
        self.name = n   #姓名
        self.age = a   #年龄
        print("Human类的初始化方法被调用")

    def infos(self):
        print("姓名:",self.name)
        print("年龄:",self.age)

class Student(Human):
    def __init__(self,n,a,s=0):
        super(Student,self).__init__(n,a)  #自己的属性自己改,父类的属性由父类自己改
        super().__init__(n,a)
        self.score = s
        print("Student的初始化方法被调用")
    def infos(self):
        super(Student,self).infos()
        print("成绩:",self.score)


s1 = Student('张飞',15,80)
s1.infos()

课后练习:
  1. 看懂学生信息管理系统的代码.理解实例方法的用法及
     实例变量封装的思想及好处
  2. 写一个类Bicycle类,有run方法,调用时显示骑行的里程(km)
    class Bicycle:
        def run(self, km):
            print("自行车骑行了", km, '公里')
  再写一个类EBicycle,在Bicycle类的基础上添加电池电量volume属性,和两个方法:
     1.fill_charge(vol) 用来充电 vol 为电量(度)
     2. run(km) 方法每骑行10km消耗电量1度, 同时显示当前电量,当电量耗尽时,则调用Bicycle的run方法继续骑行
     class EBicycle(Bicycle):
          ....
          def fill_charge(self, vol):
               '''充电'''

          def run(self, km):
              ...
    b = EBicycle(5) 新买的电动车内有5度电
    b.run(10)  # 电动骑行了10km还剩4度电
    b.run(100)  # 电动骑行了40km还剩0度电, 用脚登骑行了60km
    b.fill_charge(10)  # 充电10度
    b.run(50)  # 电动骑行了50km还剩5度电


class Bicycle:
    def run(self,km):
        print("自行车骑行了",km,'公里')
class EBicycle(Bicycle):

    def __init__(self,vol):
        self.volume = vol
        print('新电动车有',self.volume,'度电')

    def fill_charge(self,vol):
        '''充电'''
        self.volume += vol
        print('充了',vol,'度电')
        print('充电后有',self.volume,'度电') 

    def run(self,km):
        
        if km <= self.volume * 10:
            self.volume -= km//10
            print("电动车骑行了",km,"km","还剩",self.volume,'度电')
        else: 
            print("电动车骑行了",self.volume *10,"km","还剩0度电")
            km -= self.volume * 10
            super().run(km)

b = EBicycle(5)
b.run(10)
b.run(100)
b.fill_charge(10)
b.run(50)


 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值