面向对象的基本概念
面向对象技术简介
- 类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
- 方法: 类中定义的函数。
- 类变量: 类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
- 数据成员: 类变量或者实例变量用于处理类及其实例对象的相关的数据。
- 方法重写: 如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。
- 局部变量: 定义在方法中的变量,只作用于当前实例的类。
- 实例变量: 在类的声明中,属性是用变量来表示的,这种变量就称为实例变量,实例变量就是一个用 self 修饰的变量。
- 继承: 即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟"是一个(is-a)"关系(例图,Dog是一个Animal)。
- 实例化: 创建一个类的实例,类的具体对象。
- 对象: 通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。
Python中的类提供了面向对象编程的所有基本功能:类的继承机制允许多个基类,派生类可以覆盖基类中的任何方法,方法中可以调用基类中的同名方法。
对象可以包含任意数量和类型的数据。
类和实例
类的定义
- class:表明这是一个类
- ClassName:类的名字
- ():父类集合的开始和结束
- object:父类的名字,定义的类继承自父类,可以不写,默认是object。object是所有类的直接或间接父类
类的创建
class Player(object): # object 基类
pass
tom = Player() # 类的实例化(创建对象)
print(type(tom))
print(isinstance(tom,object))
print(isinstance(tom,Player))
类的实例化(创建对象)
实例名 = 类() 的方式实例化对象,为类创建一个实例
实例属性
class Player(object):
def __init__(self,name,age,city): # 初始化函数(构造函数)
self.name = name
self.age = age
self.city = city
mia = Player('mia',24,'上海')
mia.city = '杭州'
tom = Player('tom',34,'重庆')
tom.height = 180
tom.age = 32
print(tom.__dict__) # 获取实例(对象)的所有属性
# 武器: 名字 攻击值 等级
class weapon(object):
def __init__(self,name,damage,level):
self.name = name
self.damage = damage
self.level = level
gun = weapon('magic',1000,3)
print(gun.__dict__)
类属性
class Player(object):
numbers = 0 # 类属性
def __init__(self,name,age,city): # 初始化函数(构造函数)
self.name = name # 实例属性
self.age = age
self.city = city
Player.numbers += 1
mia = Player('mia',24,'上海')
print(mia.__dict__)
print('欢迎荣耀王者的第 %d 个玩家注册!' % Player.numbers)
tom = Player('tom',32,'重庆')
print('欢迎荣耀王者的第 %d 个玩家注册!' % Player.numbers)
class weapon(object):
numbers = 0
max_damage = 10000
levels = ['青铜','白银','黄金','钻石','王者']
def __init__(self,name,damage,level):
self.name = name
self.damage = damage
self.level = level
weapon.numbers += 1
if damage>weapon.max_damage:
raise Exception('最大的伤害值是10000,请重试!')
if level not in weapon.levels:
raise Exception('段位设置错误!')
try:
gun = weapon('magic',10000,'王者')
print(weapon.numbers)
arrow = weapon('arrow',450,'青铜')
print(weapon.numbers)
except Exception as e:
print(e)
构造方法
- 类有一个名为 init() 的特殊方法(构造方法),该方法在类实例化时会自动调用,像下面这样:
def __init__(self):
self.data = []
类定义了 init() 方法,类的实例化操作会自动调用 init() 方法。如下实例化类 MyClass,对应的 init() 方法就会被调用:
x = MyClass()
- 当然, init() 方法可以有参数,参数通过 init() 传递到类的实例化操作上。例如:
#!/usr/bin/python3
class Complex:
def __init__(self, realpart, imagpart):
self.r = realpart
self.i = imagpart
x = Complex(3.0, -4.5)
print(x.r, x.i) # 输出结果:3.0 -4.5
self 代表类的实例,而非类
- 类的方法与普通的函数只有一个特别的区别——它们必须有一个额外的第一个参数名称, 按照惯例它的名称是 self。
class Test:
def prt(self):
print(self)
print(self.__class__)
t = Test()
t.prt()
以上实例执行结果为:
<__main__.Test instance at 0x100771878>
__main__.Test
从执行结果可以很明显的看出,self 代表的是类的实例,代表当前对象的地址,而 self.class 则指向类。 self 不是 python 关键字 在 Python中,self 是一个惯用的名称,用于表示类的实例(对象)自身。它是一个指向实例的引用,使得类的方法能够访问和操作实例的属性。
- 当你定义一个类,并在类中定义方法时,第一个参数通常被命名为 self,尽管你可以使用其他名称,但强烈建议使用 self,以保持代码的一致性和可读性。
实例
class MyClass:
def __init__(self, value):
self.value = value
def display_value(self):
print(self.value)
# 创建一个类的实例
obj = MyClass(42)
# 调用实例的方法
obj.display_value() # 输出 42
在上面的例子中,self 是一个指向类实例的引用,它在 init 构造函数中用于初始化实例的属性,也在 display_value 方法中用于访问实例的属性。通过使用 self,你可以在类的方法中访问和操作实例的属性,从而实现类的行为。
实例方法
class Player(object):
numbers = 0 # 类属性
levels = ['青铜', '白银', '黄金', '钻石', '王者']
def __init__(self,name,age,city,level): # 初始化函数(构造函数)
self.name = name # 实例属性
self.age = age
self.city = city
if level not in Player.levels:
raise Exception('段位设置错误!')
else:
self.level = level
Player.numbers += 1
def show(self): # 实例的方法
print('我是荣耀王者的第%d个玩家,我的名字是%s,我来自 %s,我的段位是%s' % (Player.numbers,self.name,self.city,self.level))
def level_up(self):
index1 = Player.levels.index(self.level)
if index1<len(Player.levels)-1:
self.level = Player.levels[index1+1]
def get_weapon(self,weapon):
self.weapon = weapon
def show_weapon(self):
return self.weapon.show_weapon()
class weapon(object):
numbers = 0
max_damage = 10000
levels = ['青铜','白银','黄金','钻石','王者']
def __init__(self,name,damage,level):
self.name = name
self.damage = damage
self.level = level
weapon.numbers += 1
if damage>weapon.max_damage:
raise Exception('最大的伤害值是10000,请重试!')
if level not in weapon.levels:
raise Exception('段位设置错误!')
def show_weapon(self):
for k,v in self.__dict__.items():
print(k,v)
mia = Player('mia',24,'大连','青铜')
mia.show()
mia.level_up()
mia.show()
mia.level_up()
mia.show()
mia.level_up()
mia.show()
mia.level_up()
mia.show()
mia.level_up()
mia.show()
gun = weapon('magic_gun',1000,'青铜')
mia.get_weapon(gun)
mia.show_weapon()
类方法
class Player(object):
numbers = 0 # 类属性
levels = ['青铜', '白银', '黄金', '钻石', '王者']
def __init__(self,name,age,city,level): # 初始化函数(构造函数)
self.name = name # 实例属性
self.age = age
self.city = city
if level not in Player.levels:
raise Exception('段位设置错误!')
else:
self.level = level
Player.numbers += 1
def show(self): # 实例的方法
print('我是荣耀王者的第%d个玩家,我的名字是%s,我来自 %s,我的段位是%s' % (Player.numbers,self.name,self.city,self.level))
def level_up(self):
index1 = Player.levels.index(self.level)
if index1<len(Player.levels)-1:
self.level = Player.levels[index1+1]
def get_weapon(self,weapon):
self.weapon = weapon
def show_weapon(self):
return self.weapon.show_weapon()
@classmethod
def get_players(cls): # 类方法
print('荣耀王者的用户数量已经达到了%d人'%cls.numbers)
mia = Player('mia',24,'湖北','青铜')
mia.show()
Player.get_players()
class weapon(object):
# 类属性
numbers = 0
max_damage = 10000
levels = ['青铜','白银','黄金','钻石','王者']
all_weapons = []
# 构造方法
def __init__(self,name,damage,level):
self.name = name
self.damage = damage
self.level = level
weapon.numbers += 1
if damage>weapon.max_damage:
raise Exception('最大的伤害值是10000,请重试!')
if level not in weapon.levels:
raise Exception('段位设置错误!')
weapon.all_weapons.append(self)
@classmethod
def get_max_damage(cls):
max_damage = 0
for w in cls.all_weapons:
if w.damage>max_damage:
max_damage = w.damage
return max_damage
def show_weapon(self):
for k,v in self.__dict__.items():
print(k,v)
gun = weapon('magic',345,'青铜')
a = weapon('a',34,'白银')
b = weapon('b',123,'白银')
print(weapon.get_max_damage())
'''
类属性
类方法
实例属性
实例方法
'''
静态方法
class Player(object):
numbers = 0 # 类属性
levels = ['青铜', '白银', '黄金', '钻石', '王者']
def __init__(self,name,age,city,level): # 初始化函数(构造函数)
self.name = name # 实例属性
self.age = age
self.city = city
if level not in Player.levels:
raise Exception('段位设置错误!')
else:
self.level = level
Player.numbers += 1
def show(self): # 实例的方法
print('我是荣耀王者的第%d个玩家,我的名字是%s,我来自 %s,我的段位是%s' % (Player.numbers,self.name,self.city,self.level))
def level_up(self):
index1 = Player.levels.index(self.level)
if index1<len(Player.levels)-1:
self.level = Player.levels[index1+1]
def get_weapon(self,weapon):
self.weapon = weapon
def show_weapon(self):
return self.weapon.show_weapon()
@classmethod
def get_players(cls): # 类方法
print('荣耀王者的用户数量已经达到了%d人'%cls.numbers)
@staticmethod
def isvalid(**kwargs):
if kwargs['age']>18:
return True
else:
return False
infos = {'name':'mia','age':13,'city':'北京','level':'白银'}
if Player.isvalid(**infos):
mia = Player('mia',24,'北京','白银')
else:
print('请检查')
class weapon(object):
# 类属性
numbers = 0
max_damage = 10000
levels = ['青铜','白银','黄金','钻石','王者']
all_weapons = []
# 构造方法
def __init__(self,name,damage,level):
self.name = name
self.damage = damage
self.level = level
weapon.numbers += 1
if damage>weapon.max_damage:
raise Exception('最大的伤害值是10000,请重试!')
if level not in weapon.levels:
raise Exception('段位设置错误!')
weapon.all_weapons.append(self)
@classmethod
def get_max_damage(cls):
max_damage = 0
for w in cls.all_weapons:
if w.damage>max_damage:
max_damage = w.damage
return max_damage
def show_weapon(self):
for k,v in self.__dict__.items():
print(k,v)
魔法方法
- Python中的魔法方法(也称为特殊方法或双下划线方法)是一种在类定义中使用的特殊命名约定的方法。
- 当Python遇到某些内置操作时,它会尝试在对象上调用这些魔法方法。
- 这些操作包括但不限于算术运算、属性访问、类型转换等。
class User(object):
def __init__(self,name): # 构造函数
print('__init__被调用')
self.name = name
def __str__(self):
return '我的名字是%s'%self.name
def __add__(self, other):
return self.name + other.name
def __eq__(self, other):
return self.name == other.name
mia = User('mia')
print(str(mia))
print(mia)
print(1+3)
print('hi '+'mia')
jack = User('mia')
print(mia+jack)
print(6==7)
print(mia==jack)
本章总结
习题
- 在Python中,哪个关键字用于定义一个类?A
A. class
B. function
C. def
D. type
- 下列关于Python类中的方法的描述,哪一个是错误的?D
A. 实例方法是与类的实例绑定的方法,需要通过实例来调用。
B. 类方法是与类本身绑定的方法,可以使用类名直接调用。
C. 静态方法既不与实例绑定,也不与类绑定,它只是一个普通的函数。
D. 所有类的方法都必须显式地定义self参数来代表类的实例。
- 在Python中,如果一个类没有显式地定义__init__方法,那么当创建该类的实例时,Python会做什么? B
A. 抛出一个错误,因为必须定义__init__方法。
B. 隐式地定义一个__init__方法,该方法什么都不做。
C. 隐式地定义一个__init__方法,该方法将实例的所有属性初始化为None。
D. 隐式地定义一个__init__方法,该方法将实例的所有属性初始化为空。
- 下列关于Python中的继承的描述,哪一个是正确的? B
A. 在Python中,一个类只能继承自一个父类。
B. Python支持多重继承,即一个类可以继承自多个父类。
C. Python中的继承是按照深度优先的顺序进行的。
D. 在Python中,子类的属性会覆盖父类的同名属性。
- 下列哪个选项不是Python中特殊方法(魔法方法)的例子?D
A. init
B. str
C. add
D. import
- 在Python中,self参数在类的方法中代表什么?A
A. 类的实例
B. 类本身
C. 父类
D. 方法的返回值
- Python中的super()函数用于什么目的?B
A. 调用父类的构造函数
B. 调用父类的任意方法
C. 获取父类实例
D. 访问父类的属性
- Python中的@property装饰器用于什么目的?C
A. 定义一个类的实例方法
B. 定义一个类的类方法
C. 将一个方法转换为属性的getter方法
D. 将一个方法转换为属性的setter方法
- Python中的@classmethod装饰器用于什么目的?C
A. 将一个方法转换为属性的getter方法
B. 将一个方法转换为属性的setter方法
C. 定义一个类的类方法
D. 定义一个类的静态方法
- Python中的@property装饰器用于什么目的?C
A. 定义一个类的实例方法
B. 定义一个类的类方法
C. 将一个方法转换为属性的getter方法
D. 将一个方法转换为属性的setter方法