类变量
  类方法
  静态方法
  单继承
  封装
  多态


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

  作用:
    通常用来存储该类创建的对象的共有属性
  说明:
    类变量可以通过该类直接访问
    类变量可以通过类的实例直接访问(取值)
    类变量可以通过此类的对象的__class__属性间接访问
  示例见:

#此示例示意类变量的定义方法,和用法
class car:
    total_count=0   
#创建类变量
print(car.total_count)
car.total_count+=100

c1=car()
print(c1.total_count)   #100借助对象访问类变量
c1.total_count=999  #创建实例变量
print(c1.total_count)   #999
print(car.total_count)  100

#类变量可以通过此类的对象的___class__属性间接访问
c1.__class__.total_count=8888
print(c1.total_count)   #999
print(car.total_count)  #8888

class car:
    total_count=0
    def __init__(self,info):
        self.info=info
        self.__class__.total_count+=1
    def __del__(self):
        print('汽车',self.info,'被销毁')
        self.__class__.total_count-=1
c1=car('byd e6')
c2=car('jili c7')

print('当前有%d个汽车对象'%car.total_count) #2
del c2
print(car.total_count)

当前有2个汽车对象
汽车 jili c7 被销毁
1
汽车 byd e6 被销毁j

 

类的文档字符串:
  类内第一个没有赋值给变量的字符串为文档字符串
  类的文档字符串可以用类的 __doc__ 属性访问

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

class Human:
    #限制Human类的对象只能有'name',和'age'属性,不能有其他属性
    __slots__=['name','age']
    def __init__(self,n,a):
        self.name,self.age=n,a
    def show_info(self):
        print(self.name,self.age)
s1=Human('tarena',15)
s1.show_info()
# s1.Age=16
s1.show_info()  
print(s1.__slots__)

 


类方法 @classmethod
  类方法是用于描述类的行为的方法,类方法属于类,不属于该类创建的实例对象

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

#此示例示意类方法的定义和调用

class A:
    v=0

    @classmethod
    def get_v(cls):
        return cls.v
    @classmethod
    def set_v(cls,value):
        cls.v=value #设置类变量

print(A.v)  #直接访问类变量
value=A.get_v() #
print('value=',value)   #0

A.set_v(999)
print(A.get_v())

 


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

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

#此示例示意静态方法的定义和应用
class A:
    @staticmethod
    def myadd(a,b):
        '''这是静态方法'''
        return a+b

#用类来调用静态方法
print(A.myadd(100,200)) #300
a=A()
#用此类的实例来调用今天方法
print(a.myadd(100,200))

 

1. 用类来描述一个学生的信息(可以修改之前写的Student类)
  class Student:
      .... 以下自己实现
  学生信息有:
     姓名, 年龄, 成绩
  将这些学生对象存于列表中,可以任意添加和删除学生信息.
     1) 打印出学生的个数
     2) 打印出所有学生的平均成绩
     3) 打印出所有学生的平均年龄
      (建议用列表的长度来计算学生的个数)

继承 (inhertance) 和 派生 (derived)
  继承是从已有的类中派生出新的类,新类具有原类的属性和行为,并能扩展新的能力
  派生类就是从一个已有类中衍生出新类,在新的类上可以添加新的属性和行为

作用:
  1. 用继承派生机制,可以将一些共有功能加在基类中,实现代码的共享
  2. 在不改变基类代码的基础上改变原有类的功能
名词:
   基类(base class),超类(super class), 父类(father class)
   派生类(derived class), 子类(child class))

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

class Human:
    '''此类用于描述人类的共性'''
    def say(self,what):
        print('说:',what)
    
    def walk(self,distance):
        print('走了',distance,'公里')

h1=Human()
h1.say('您好')
h1.walk(5)

class Student(Human):
    def study(self,subject):
        print('正在学习:',subject)
s1=Student()
s1.say('学习优点类')
s1.study('python')

class Teacher(Human):
    def teach(self,subject):
        print("正在教:",subject)

s2=Teacher()
s2.teach('继承/派生')
s2.say('放假了')
                

 

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

类的 __base__属性
  作用:
    用来绑定此类的基类

python3中的内建内继承关系见:
  >>> help(__builtins__)

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

# override.py

# 此示例示意覆盖的语法
class A:
    def work(self):
        print("A.work被调用")

class B(A):
    def work(self):
        '''此方法会覆盖父类的work方法'''
        print("B.work被调用")

b = B()
b.work()  # B.work被调用

a = A()
a.work()  # A.work被调用

 

子类对象显式调用基类方法的方式:
  基类名.方法名(实例, 实际调用传参...)


super函数
  super(cls, obj)  返回绑定超类的实例(要求obj必须是cls类型的实例)
  super()    返回绑定超类的实例,等同于super(__class__, 实例方法的第一个参数) 必须在方法内调用
 
  作用:
    借助super() 返回实例间接调用父类的覆盖方法
  示例见:

# super.py

# 此示例示意用super函数显式的调用被覆盖的方法
class A:
    def work(self):
        print("A.work被调用")

class B(A):
    def work(self):
        '''此方法会覆盖父类的work方法'''
        print("B.work被调用")

    def mywork(self):
        # 调用自己(B类)的方法
        self.work()
        # 调用父类(A类)的方法 
        super(B, self).work()
        super().work()

b = B()
# b.work()  # B.work被调用
# # A.work(b)  # A.work被调用
# super(B, b).work()  # A.work被调用

b.mywork()

 


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

  示例见:
 

# super_init.py

# 此示例示意用super函数显式调用基类的初始化方法
class Human:
    def __init__(self, n, a):
        self.name = n
        self.age = a
        print("Human.__init__被调用")
    def show_info(self):
        print("姓名:", self.name)
        print("年龄:", self.age)

class Student(Human):
    def __init__(self, n, a, s=0):
        super(Student,
              self).__init__(n, a)
        self.score = s
        print("Student.__init__被调用")
    def show_info(self):
        # 此处的代码自己完成
        super().show_info()
        print("成绩:", self.score)

s = Student("小张", 20, 100)
s.show_info()