面向对象
类变量:
类变量是类的属性,此属性属于类,不属于此类的实例说明:
类变量,可以通过该类直接访问
类变量可以通过该类的实例直接访问
类变量可以通过此类的对象的'__class__'属性间接访问
示例:
class Human:
total_count = 0 # 类变量
print(Human.total_count)
h1 = Human()
print(h1.total_count) # 结果为0,不会出错 # 类的实例可以访问直接类变量
Human.total_count = 1 # 修改类变量
h1.total_count = 2 # 添加了自己的实例属性total_count
h1.__class__.total_count = 3 # 间接修改类变量
示例:
# 此示例示意类变量的用途和使用方法
class Human:
total_count = 0 # 类变量,用于记录对象的个数
def __init__(self, name):
self.name = name
self.__class__.total_count += 1 # 人数加一
print(name, '对象创建')
def __del__(self):
self.__class__.total_count -= 1 # 总人数减一
print('当前对象的个数是:', Human.total_count)
h1 = Human('张飞')
h2 = Human('赵云')
print('当前对象的个数是:', Human.total_count)
del h2
print('当前对象的个数是:', Human.total_count)
类的__slots__属性:
作用:限定一个类创建的实例只能有固定属性(实例变量)
说明:
__slots__属性是一个列表,列表的值是字符串
含有__slots__属性的类所创建的对象没有__dict__字典
示例:
# 此示例示意__slots__属性的用法
class Student:
# 限定此类创建的对象只能有name和age两个属性
__slots__ = ['name', 'age']
def __init__(self, n, a):
self.name = n
self.age = a
s1 = Student('小张', 20)
# s1.Age=21 # 错写了age 为 Age,会报错
# print(s1.__dict__) # 出错,因为没有__dict__字典
类方法: @classmethod
类方法是操作类的方法,类方法属于类,不属于该类创建的对象说明:
类方法需要使用@classmethod装饰器定义
类方法的第一个参数用来绑定类,约定写为cls
类和对象示例都可以调用类方法
类方法不能访问此类创建的对象的属性
示例:
class A:
v = 0 # 类变量
@classmethod
def get_v(cls): # 此方法不是实例方法,是类方法
return cls.v
示例
class A:
v = 0 # 类变量
@classmethod
def get_v(cls): # 此方法不是实例方法,是类方法
return cls.v
@classmethod
def set_v(cls, value):
cls.v = value
print(A.get_v()) # 值为0
# 修改类变量的值
A.v = 1
print(A.get_v()) # 值为1
# 修改类变量的值
A.set_v(100)
print(A.get_v()) # 值为100
# 通过实例修改类变量的值
a = A()
a.set_v(200) # 传入set_v 的实参实际为(a.__class__, 200)
print(A.get_v()) # 值为100
静态方法 @staticmathod
静态方法是定义在类的内部的函数,此函数作用域是类的内部说明:
静态方法需要使用@staticmathod装饰器定义
静态方法与普通函数的定义相同,不需要传入self和cls
静态方法只能凭借该类和实例来调用
静态方法不能访问类变量和实例变量
示例:
class A:
@staticmethod
def myadd(a, b):
return a + b
print(A.myadd(100, 200))
a = A()
print(a.myadd(300, 400))
继承 inheritance和派生 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, '公里')
示例1:
# 此示例示意单继承的语法及使用方法
class Human:
def say(self, what):
print('说:', what)
def walk(self, distance):
print('走了', distance, '公里')
h1 = Human()
h1.say('今天天气不错')
h1.walk(5)
print('-' * 20)
class Student(Human):
def study(self, subject):
print('正在学习', subject)
s1 = Student()
s1.say('今天晚饭吃什么')
s1.walk(3)
s1.study('python')
print('-' * 20)
class Teacher(Human):
def teach(self, that):
print('老师正在讲', that)
t1 = Teacher()
t1.say('今天下班早点回家')
t1.walk(1)
t1.teach('面向对象')
示例2:
# 此示例示意单继承的语法及使用方法
class Human:
def say(self, what):
print('说:', what)
def walk(self, distance):
print('走了', distance, '公里')
class Student(Human):
def study(self, subject):
print('正在学习', subject)
class Teacher(Student):
def teach(self, that):
print('老师正在讲', that)
t1 = Teacher()
t1.say('今天下班早点回家')
t1.walk(1)
t1.teach('面向对象')
t1.study('转魔方')
继承说明:
任何类都直接或间接的继承自object类object类是一切类的超类
类内的__base__属性
此属性用来记录此类的基类见:>>> help(__builtins__)
覆盖:override
什么是覆盖
覆盖是指在有继承派生关系的类中,子类中实现了与基类(超类)同名的方法,在子类实例调用方法时,实际调用的是子类中的覆盖版本,这种现象叫做覆盖
示例:
class A:
def work(self):
print('A类的work方法被调用')
class B(A):
def work(self):
print('B类的work方法被调用')
b = B()
b.work() # 子类已覆盖了父类的方法
当覆盖发生时,子类对象能否调用父类中的方法?
super 函数
super(type,obj) 返回绑定超类的实例(要求obj必须为type类型的实例)super() 返回绑定超类的实例等同于super(__class,实例的第一个参数),且必须在方法内调用
作用:
返回超类的实例,用超类的实例来调用其自身的方法
实例:
# 此示例示意用super函数访问父类的覆盖方法
class A:
def work(self):
print('A类的work方法被调用')
class B(A):
def work(self):
print('B类的work方法被调用')
def doworks(self):
# self.work() #调用b类的
super(B, self).work() # 调用超类的方法
super().work() # 一样会调用超类的方法
# super(__class__, self).work() # 也可以调用超类的方法,不建议使用
b = B()
b.work() # 子类已覆盖了父类的方法
print('-----以下用b调用覆盖版本的方法-----')
# A.work(b) # A类的方法被调用
super(B, b).work()
b.doworks()
显示调用基类的初始化方法
示例:
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().__init__(n, a) # 显式调用基类的初始化方法
self.score = s
print('Student类的__init__被调用')
def show_info(self):
super().show_info()
print('成绩:', self.score)
s1 = Student('张学友', 40)
s1.show_info()
说明:
当子类实现了__init__方法后,父类的__init__方法将被覆盖,既不在会主动调用父类的__init__方法,会引起父类的属性得不到初始化,
此时需要显示调用父类的初始化方法