目录
一、类与对象
类:
类是同一类对象的属性和行为的抽象和总结;
类描述同一类对象应包含的数据;
类描述同一类对象的行为特征;
类是抽象的,是一个概念模型;
一个类可以找到多个对象;
对象:
具有明确的属性和行为;
程序是对象的集合,通过消息交互。
类和对象关系:
类就是创建对象的模板;
对象就是根据类产生的一个具体实例。
1.1、类的定义
类(Class)由3部分构成:
- 类的名称 : 类名
- 类的属性 : 一组数据
- 类的方法 : 允许对进行操作的方法 (行为)
定义格式:
class 类名:
方法列表
示例:
class Hero(object):
def info(self):
print("hello world")
self 代表类的实例,而非类
- 类的方法与普通的函数只有一个特别的区别——它们必须有一个额外的第一个参数名称, 按照惯例它的名称是 self。
- 所谓的self,可以理解为自己可以把self当做C++中类里面的this指针一样理解,就是对象自身的意思。
- 某个对象调用其方法时,python解释器会把这个对象作为第一个参数传递给self,所以开发者只需要传递后面的参数即可。
1.2、对象的定义
定义格式:
对象名 = 类名()
示例:
class Hero(object):
def info(self):
"""
当对象调用方法的时候,python会把第一个参数传递到我们的self中
"""
print(self)
print("---"*20)
# 实例化对象
test1 = Hero()
# . 表示选择属性或者方法
# 调用info方法
test1.info()
print(test1)
print(id(test1))
print(Hero.info)
"""
运行结果为:
<__main__.Hero object at 0x0000000001DD8400>
------------------------------------------------------------
<__main__.Hero object at 0x0000000001DD8400>
31294464
<function Hero.info at 0x0000000001E28700>
"""
1.3、给对象添加属性
class Hero(object):
def info(self):
print("info_function")
# 实例化对象
test1 = Hero()
# 给对象添加属性以及对应的属性值,如果不添加就会报错
test1.name = "张三"
test1.age = 16
print("name = %s, age = %d" % (test1.name, test1.age))
"""
运行结果为:
name = 张三, age = 16
"""
1.4、通过self方法获取对象属性
class Hero(object):
def info(self):
print("name = %s, age = %d" % (self.name, self.age))
test1 = Hero()
# 给对象添加属性以及对应的属性值,如果不添加就会报错,这里就引入了魔法方法
test1.name = "张三"
test1.age = 16
test1.info()
"""
运行结果为:
name = 张三, age = 16
"""
二、魔法方法
创建对象后再去添加属性有点不合适,有没有简单的办法,可以在创建对象的时候,就已经拥有这些属性?——魔法方法
2.1、类的初始方法——init方法
在创建对象的时候,自动调用__init__()函数,自动完成对象属性的设置。(类似于C++中的构造函数)
语法格式一:不带参数
def __init__(self):
slef.属性1 = 属性值1
slef.属性2 = 属性值2
...
语法格式二:带参数
def __init__(self, 参数1, ..., 参数n):
slef.属性1 = 参数1
...
slef.属性n = 参数n
示例:不带参数
class Car(object): # 类名第一个字符一般大写
# 初始化方法
def __init__(self):
self.wheel = 4
self.color = "blue"
def info(self):
print("车轮数:%s, 颜色:%s" % (self.wheel, self.color))
BMW = Car()
BMW.info()
"""
运行结果为:
车轮数:4, 颜色:blue
"""
示例:带参数
class Car(object): # 类名第一个字符一般大写
# 初始化方法
def __init__(self, wheel, color):
self.wheel = wheel
self.color = color
def info(self):
print("车轮数:%s, 颜色:%s" % (self.wheel, self.color))
# 对象1
BMW = Car(4, "白色")
BMW.info()
# 对象2
BMW1 = Car(4, "黄色")
BMW1.info()
"""
运行结果为:
车轮数:4, 颜色:白色
车轮数:4, 颜色:黄色
"""
2.2、类的字符信息输出——str方法
当使用print输出对象的时候,只要自己定义了__str__(self)方法,那么就会打印从在这个方法中return的数据。(必须return 一个字符串)
当打印对象的时候,就是执行__str__()函数中的语句以及打印return的字符串。
语法格式:
def __str__(self):
msg = "xxx"
return msg
字符串赋值新用法:
wheel = str(4)
color = “blue”
a = “车轮数:%s, 颜色:%s” % (wheel, color) # 新用法
b = “车轮数:”+ wheel + ", " + “颜色:” + color # 新用法
print(a)
print(b)
示例:
class Car(object): # 类名第一个字符一般大写
# 初始化方法
def __init__(self, wheel, color):
self.wheel = wheel
self.color = color
def info(self):
print("车轮数:%s, 颜色:%s" % (self.wheel, self.color))
def __str__(self):
msg = "车轮数:%s, 颜色:%s" % (self.wheel, self.color)
return msg
BMW = Car(4, "白色")
print(BMW)
"""
运行结果为:
车轮数:4, 颜色:白色
"""
2.3、类的析构方法——del方法
在删除对象的时候,自动调用__del__()函数。(类似于C++中的析构函数)
语法格式:
def __del__(self):
pass # 占位符
示例:
class Animal(object):
def __init__(self, name): # 创建对象时自动调用
print("__init__方法被调用")
self.name = name
def __del__(self): # 脚本结束时,自动调用
print("__del__方法被调用")
print("%s对象已经被删除" % self.name)
dog = Animal("狗")
a = 1
del a
del dog # 手动删除
# 当没有del dog语句时,在脚本结束时,也会调用__del__()函数
"""
运行结果为:
__init__方法被调用
__del__方法被调用
狗对象已经被删除
"""
注意:
- 当有1个变量保存了对象的引用时,此对象的引用计数就会加1
- 当使用del删除变量指向的对象时,如果对象的引用计数不是1,比如3,那么此时只会让这个引用计数减1,即变为2,当再次调用del时,变为1,如果再调用1次del,此时会真的把对象进行删除。
示例:
class Animal(object):
def __init__(self, name): # 创建对象时自动调用
print("__init__方法被调用")
self.name = name
def __del__(self): # 脚本结束时,自动调用
print("__del__方法被调用")
print("%s对象已经被删除" % self.name)
# 情况一
dog = Animal("狗") # 变量引用了对象一次
a = dog # 变量引用了对象一次,总共引用了2次
del dog
while 1:
pass # 循环语句中,不允许空语句,所以加占位符
"""
运行结果为:(此时脚本并没有退出)
__init__方法被调用
"""
# 情况二
dog = Animal("狗") # 变量引用了对象一次
# a = dog
del dog # 对象总共被引用了一次
while 1:
pass # 循环语句中,不允许空语句,所以加占位符
"""
运行结果为:(此时脚本并没有退出)
__init__方法被调用
__del__方法被调用
狗对象已经被删除
"""
三、继承
3.1、单继承
示例:
class Master(object):
def __init__(self):
self.konfu = "古法"
def make_cake(self):
print("按照%s制作cake" % self.konfu)
# 定义Prentice类,继承自Master,就有了父类的属性和方法;Master是父类,Prentice是子类
class Prentice(Master):
pass # 占位符
cat = Prentice() # 子类的实例化对象
print(cat.konfu)
cat.make_cake()
"""
运行结果为:
古法
按照古法制作cake
"""
3.2、多继承
class Master(object):
def __init__(self):
self.kongfu = "古法"
def make_cake(self):
print("按照%s制作cake" % self.kongfu)
def master(self):
print("master")
class School(object):
def __init__(self):
self.kongfu = "现代配方"
def make_cake(self):
print("按照%s制作cake" % self.kongfu)
def school(self):
print("school")
class Prentice(Master, School): # 多继承,继承多个父类,Master在前
pass
cat = Prentice()
print(cat.kongfu)
cat.make_cake()
# 子类的魔法属性__mro__决定了属性和方法的查找顺序
print(Prentice.__mro__)
cat.master() # 不重名不受影响
cat.school()
"""
运行结果为:
古法
按照古法制作cake
(<class '__main__.Prentice'>, <class '__main__.Master'>, <class '__main__.School'>, <class 'object'>)
master
school
"""
注意:
- 当多个父类中存在相同的属性和方法时,子类调用属性和方法按继承的先后顺序进行查找。(左边优先查找)
- 子类的魔法属性__mro__决定了属性和方法的查找顺序。查看方式为print(子类.__mro__)。
- 不重名的属性和方法不受影响。