类属性
类属性创建有点类似于在类中创建一个全局变量,这个变量类跟实例都可以调用它
# 定义一个模板
class Dog():
# 定义一个类属性
number_of_dogs = 0
# 构造方法 - 添加实例属性,做其他初始化工作
def __init__(self,name,height,power):
self.name = name
self.height = height
# 设置血量为默认属性,值为10
self.blood = 10
self.power = power
print '{}出生了!汪汪~'.format(self.name)
# 添加一个方法bark
def bark(self):
print '我是{},身高{},攻击力{},血量{}'.format(self.name,self.height,self.power,self.blood)
# 再添加一个attack()方法来执行攻击这个行为
def attack(self,dog):
dog.reduce_blood(self.power)
def reduce_blood(self,reduce_value):
if reduce_value > self.blood:
self.blood = 0
else:
self.blood = self.blood-reduce_value
# 创建多个实例
d1 = Dog('大黄',0.7,3)
d2 = Dog('二黑',0.5,4)
# 通过类访问类属性
print Dog.number_of_dogs
# 通过实例访问类属性
print d1.number_of_dogs
print d2.number_of_dogs
唯一不同的是,在修改属性的值的时候,变量跟实例的区别是很大的
#省略部分代码
# 创建多个实例
d1 = Dog('大黄',0.7,3)
d2 = Dog('二黑',0.5,4)
# 类修改类属性
Dog.number_of_dogs = 8
# 通过类访问类属性
print Dog.number_of_dogs
# 实例修改类属性
d1.number_of_dogs = 10
# 通过实例访问类属性
print d1.number_of_dogs
print d2.number_of_dogs
来看一下运行结果:
总结:
- 整个类只有一份,所有实例都共享这一份。
- 可以通过类名或者实例名访问类属性,访问的都是同一个。
- 修改类属性需要通过类名。
- 因为通过实例名就会创建一个同名的实例变量。
- 当实例属性与类属性同名时,通过实例访问则实例属性优先。
类方法
类方法就是定义一个属于类的方法,定义格式与实例方法相似,不过要在方法上一行加 @classmethod装饰器来声明:
class Dog():
dogs = []
# 构造类方法,返回狗的数量
@classmethod
def number_of_dogs(cls):
return len(cls.dogs)
# 构造类方法,返回最高大的狗
@classmethod
def biggest(cls):
max_height = 0
for i in cls.dogs:
if i.height > max_height:
max_height = i.height
return max_height
# 构造方法 - 添加实例属性,做其他初始化工作
def __init__(self,name,height,power):
self.name = name
self.height = height
self.blood = 10
self.power = power
print '{}出生了!汪汪~'.format(self.name)
Dog.dogs.append(self)
# 实例化类
d1 = Dog('大黄',70,10)
d2 = Dog('二黑',50,15)
# 调用类方法输出当前狗的数量
print '当前狗的数量为:{}只'.format(Dog.number_of_dogs())
# 调用类方法返回最高大的狗
print '当前狗狗最高身高为:{}公分'.format(Dog.biggest())
练习:
构造一个类方法,要求返回height大于50的狗的数量
class Dog():
dogs = []
big_dogs = []
# 构造一个类方法,要求返回height大于50的狗的数量
@classmethod
def num_of_big_dog(cls):
for i in Dog.dogs:
if i.height > 50:
Dog.big_dogs.append(i)
print '身高大于50公分的狗有{}只'.format(len(Dog.big_dogs))
# 构造方法 - 添加实例属性,做其他初始化工作
def __init__(self,name,height,power):
self.name = name
self.height = height
self.blood = 10
self.power = power
print '{}出生了!汪汪~'.format(self.name)
Dog.dogs.append(self)
# 实例化多个对象
d1 = Dog('大黄',70,10)
d2 = Dog('二黑',50,15)
d3 = Dog('三傻',45,20)
d4 = Dog('四喜',62,13)
d5 = Dog('五白',30,20)
# 调用类方法输出height大于50的狗的数量
Dog.num_of_big_dog()
静态方法
之前我们学习了两个方法:实例方法与类方法,实例方法的第一个参数是实例,只能调用实例属性,调用类属性则会创建一个与类属性同名的实例属性;类方法的第一个参数是类,只能调用类属性。
如果有一个方法它属于这个类,它既不需要使用实例属性,也不需要使用类属性,那么这个方法就是静态方法
class Dog:
# 定义静态方法
@staticmethod
def info():
print "Dog is human's best friend~"
# 实例化一个对象
d1 = Dog()
# 调用静态方法
Dog.info()
d1.info()
继承和super()
现在我们手上有3只狗,分别是警犬、牧羊犬、宠物犬,它们有各自的特性,但也有共同的属性,这时候就要用到类的继承了。
具体代码可以这样实现:
# 定义构造方法
class Dog(object):
def __init__(self,name,power,height):
self.name = name
self.height = height
self.power = power
self.blood = 10
# 构造bark方法
def bark(self):
print '我是{},汪汪~'.format(self.name)
# 定义一个SheepDog类,它是Dog的子类,继承Dog的构造方法
class SheepDog(Dog):
# 定义构造方法,这里添加了一个特性num_of_sheeps
def __init__(self,name,power,height,num_of_sheeps):
# 用super()初始化构造父类,这里的super()函数与python3中有所不同!
super(SheepDog,self).__init__(name,power,height)
# 设置方法属性
self.num_of_sheeps = num_of_sheeps
# 实例化一个对象
sd = SheepDog('牧羊犬',10,70,5)
# 调用父类方法
sd.bark()
现在我们做一个练习,把其余的两只狗也定义出来,只定义属性,先不定义它们的方法:
# 定义构造方法
class Dog(object):
def __init__(self,name,power,height):
self.name = name
self.height = height
self.power = power
self.blood = 10
# 构造bark方法
def bark(self):
print '我是{},汪汪~'.format(self.name)
# 定义牧羊犬
class SheepDog(Dog):
# 定义构造方法,这里添加了一个特性num_of_sheeps
def __init__(self,name,power,height,num_of_sheeps):
# 用super()初始化构造父类,这里的super()函数与python3中有所不同!
super(SheepDog,self).__init__(name,power,height)
# 设置方法属性
self.num_of_sheeps = num_of_sheeps
# 定义警犬
class PoliceDog(Dog):
def __init__(self,name,power,height,ability):
super(PoliceDog,self).__init__(name,power,height)
self.ability = ability
# 定义宠物犬
class PetDog(Dog):
def __init__(self,name,power,height,price):
super(PetDog, self).__init__(name,power,height)
self.price = price
# 牧羊犬
sd = SheepDog('牧羊犬',10,70,5)
print sd.blood
sd.bark()
# 警犬
pd = PoliceDog('警犬',20,65,7)
print pd.blood
pd.bark()
# 宠物犬
petd = PetDog('宠物犬',1,3,10)
print petd.blood
petd.bark()
给子类添加方法
我峨嵋你继承父类以后,可以使用它的构造方法以及它的类属性,但子类也会有自己的方法,就像上文中的三只狗,它们有一个自己的方法,这时候我们就需要给子类定义方法了。
添加方法的方式其实也很简单,就是在子类中定义一个新的方法罢了:
# 定义构造方法
class Dog(object):
def __init__(self,name,power,height):
self.name = name
self.height = height
self.power = power
self.blood = 10
# 构造bark方法
def bark(self):
print '我是{},汪汪~'.format(self.name)
# 定义一个SheepDog类,它是Dog的子类,继承Dog的构造方法
class SheepDog(Dog):
# 定义构造方法,这里添加了一个特性num_of_sheeps
def __init__(self,name,power,height,num_of_sheeps):
# 用super()初始化构造父类,这里的super()函数与python3中有所不同!
super(SheepDog,self).__init__(name,power,height)
# 设置方法属性
self.num_of_sheeps = num_of_sheeps
def protect(self):
print '我开始保护羊群了,汪汪!'
# 定义警犬
class PoliceDog(Dog):
def __init__(self,name,power,height,ability):
super(PoliceDog,self).__init__(name,power,height)
self.ability = ability
def detect(self):
print '我开始侦擦了,汪汪!'
# 定义宠物犬
class PetDog(Dog):
def __init__(self,name,power,height,price):
super(PetDog, self).__init__(name,power,height)
self.price = price
def sing(self):
print '我开始唱歌了,汪汪!'
# 牧羊犬
sd = SheepDog('牧羊犬',10,70,5)
sd.bark()
# 调用牧羊犬子方法
sd.protect()
# 警犬
pd = PoliceDog('警犬',20,65,7)
pd.bark()
# 调用警犬子方法
pd.detect()
# 宠物犬
petd = PetDog('宠物犬',1,3,10)
petd.bark()
# 调用宠物犬子方法
petd.sing()
重写父类方法
重写的格式就是在子类中定义一个与父类方法同名的子方法即可:
# 定义构造方法
class Dog(object):
def __init__(self,name,power,height):
self.name = name
self.height = height
self.power = power
self.blood = 10
# 构造bark方法
def bark(self):
print '我是{},汪汪~'.format(self.name)
# 定义一个SheepDog类,它是Dog的子类,继承Dog的构造方法
class SheepDog(Dog):
# 定义构造方法,这里添加了一个特性num_of_sheeps
def __init__(self,name,power,height,num_of_sheeps):
# 用super()初始化构造父类,这里的super()函数与python3中有所不同!
super(SheepDog,self).__init__(name,power,height)
# 设置方法属性
self.num_of_sheeps = num_of_sheeps
def protect(self):
print '我开始保护羊群了,汪汪!'
# 定义警犬
class PoliceDog(Dog):
def __init__(self,name,power,height,ability):
super(PoliceDog,self).__init__(name,power,height)
self.ability = ability
def detect(self):
print '我开始侦擦了,汪汪!'
def bark(self):
print '我是{},这是我自己的方法,我重写了父类方法~'.format(self.name)
# 定义宠物犬
class PetDog(Dog):
def __init__(self,name,power,height,price):
super(PetDog, self).__init__(name,power,height)
self.price = price
def sing(self):
print '我开始唱歌了,汪汪!'
# 警犬
pd = PoliceDog('警犬',20,65,7)
# 重写父类方法
pd.bark()
# 调用警犬子方法
pd.detect()
如果你想既重写了父类方法,又要调用原父类方法的话,我们可以用super()来实现这个功能
# 定义构造方法
class Dog(object):
def __init__(self,name,power,height):
self.name = name
self.height = height
self.power = power
self.blood = 10
# 构造bark方法
def bark(self):
print '我是{},汪汪~'.format(self.name)
# 定义一个SheepDog类,它是Dog的子类,继承Dog的构造方法
class SheepDog(Dog):
# 定义构造方法,这里添加了一个特性num_of_sheeps
def __init__(self,name,power,height,num_of_sheeps):
# 用super()初始化构造父类,这里的super()函数与python3中有所不同!
super(SheepDog,self).__init__(name,power,height)
# 设置方法属性
self.num_of_sheeps = num_of_sheeps
def protect(self):
print '我开始保护羊群了,汪汪!'
# 定义警犬
class PoliceDog(Dog):
def __init__(self,name,power,height,ability):
super(PoliceDog,self).__init__(name,power,height)
self.ability = ability
def detect(self):
print '我开始侦擦了,汪汪!'
# 调用父类方法
super(PoliceDog,self).bark()
def bark(self):
print '我是{},这是我自己的方法,我重写了父类方法~'.format(self.name)
# 定义宠物犬
class PetDog(Dog):
def __init__(self,name,power,height,price):
super(PetDog, self).__init__(name,power,height)
self.price = price
def sing(self):
print '我开始唱歌了,汪汪!'
# 警犬
pd = PoliceDog('警犬',20,65,7)
# 重写父类方法
pd.bark()
练习:
把剩下的两只狗的bark方法也进行重写
# 定义构造方法
class Dog(object):
def __init__(self,name,power,height):
self.name = name
self.height = height
self.power = power
self.blood = 10
# 构造bark方法
def bark(self):
print '我是{},汪汪~'.format(self.name)
# 定义牧羊犬
class SheepDog(Dog):
# 定义构造方法,这里添加了一个特性num_of_sheeps
def __init__(self,name,power,height,num_of_sheeps):
# 用super()初始化构造父类,这里的super()函数与python3中有所不同!
super(SheepDog,self).__init__(name,power,height)
# 设置方法属性
self.num_of_sheeps = num_of_sheeps
def protect(self):
print '我开始保护羊群了,汪汪!'
def bark(self):
print '我是{},这是我自己的方法,我重写了父类方法~'.format(self.name)
super(SheepDog, self).bark()
# 定义警犬
class PoliceDog(Dog):
def __init__(self,name,power,height,ability):
super(PoliceDog,self).__init__(name,power,height)
self.ability = ability
def detect(self):
print '我开始侦擦了,汪汪!'
def bark(self):
print '我是{},这是我自己的方法,我重写了父类方法~'.format(self.name)
# 调用父类方法
super(PoliceDog,self).bark()
# 定义宠物犬
class PetDog(Dog):
def __init__(self,name,power,height,price):
super(PetDog, self).__init__(name,power,height)
self.price = price
def sing(self):
print '我开始唱歌了,汪汪!'
def bark(self):
print '我是{},这是我自己的方法,我重写了父类方法~'.format(self.name)
super(PetDog, self).bark()
# 牧羊犬
sd = SheepDog('牧羊犬',10,70,5)
# 重写父类方法
sd.bark()
# 警犬
pd = PoliceDog('警犬',20,65,7)
# 重写父类方法
pd.bark()
# 宠物犬
petd = PetDog('宠物犬',1,3,10)
# 重写父类方法
petd.bark()
命名规则
类名:驼峰,如SheepDog、PoliceDog
方法名、变量名、参数、文件名:
全小写,多个单词下划线连接
如:get_pwd,start_attack
如果是文件名,可以变成getpwd,为了引用起来方便
私有属性:在属性前加_,例如_weight,不过依然可以访问,只是一种命名规范
Python解释器御用:方法前加__,例如:__init__
模块、类和引入
现在我们创建一个新的文件game.py,引用我们上文写好的dog.py,像这样就可以了
import dog
pet_dog = dog.PetDog('小可爱',1,30,998)
pet_dog.bark()
print pet_dog.price
标准库中的类
我们结合标准库中的类来进行一个继承,在python中有一个Turtle类,是一个绘图海龟,现在我们来写一个属于自己的小海龟
这里物品们定义一个自己的类Myturtle,并且定义一个自己的方法big_circle:
import turtle
class MyTurtle(turtle.Turtle):
def big_circle(self):
self.color('red')
self.circle(100)
s = turtle.Screen()
t = MyTurtle()
t.big_circle()
s.mainloop()
运行结果:
后续我会在另一篇文章中更新一下这个部分,本文中就先不做过多介绍了
其他实例作为属性
假设现在我们要给每条出厂的宠物狗配置一个狗窝,我们可以通过__init__方法添加参数来实现,也可以构造一个DogHost方法,把他实例化来充当宠物狗的属性:
# 定义构造方法
class Dog(object):
def __init__(self,name,power,height):
self.name = name
self.height = height
self.power = power
self.blood = 10
self._weight = 30
# 构造bark方法
def bark(self):
print '我是{},汪汪~'.format(self.name)
# 定义一个SheepDog类,它是Dog的子类,继承Dog的构造方法
class SheepDog(Dog):
# 定义构造方法,这里添加了一个特性num_of_sheeps
def __init__(self,name,power,height,num_of_sheeps):
# 用super()初始化构造父类,这里的super()函数与python3中有所不同!
super(SheepDog,self).__init__(name,power,height)
# 设置方法属性
self.num_of_sheeps = num_of_sheeps
def protect(self):
print '我开始保护羊群了,汪汪!'
def bark(self):
print '我是{},这是我自己的方法,我重写了父类方法~'.format(self.name)
super(SheepDog, self).bark()
# 定义警犬
class PoliceDog(Dog):
def __init__(self,name,power,height,ability):
super(PoliceDog,self).__init__(name,power,height)
self.ability = ability
def detect(self):
print '我开始侦擦了,汪汪!'
def bark(self):
print '我是{},这是我自己的方法,我重写了父类方法~'.format(self.name)
# 调用父类方法
super(PoliceDog,self).bark()
# 定义宠物犬
class PetDog(Dog):
def __init__(self,name,power,height,price,house):
super(PetDog, self).__init__(name,power,height)
self.price = price
self.house = house
def sing(self):
print '我开始唱歌了,汪汪!'
def bark(self):
print '我是{},这是我自己的方法,我重写了父类方法~'.format(self.name)
super(PetDog, self).bark()
# 定义狗窝
class DogHost:
def __init__(self,num):
self.num = num
print '{}号狗窝已创建'.format(self.num)
定义好了之后,我们去另一个game.py脚本中引用它:
import dog
house = dog.DogHost('9527')
pet_dog = dog.PetDog('小可爱',1,20,998,house)
运行结果:
写一个简单的英雄联盟
- 参考王者荣耀或者你喜欢的其他游戏,创建相应的类和实例。
- 要求至少有3个类。
- 要求必须有继承关系。
- 要求必须有实例属性和类属性。
- 要求必须有实例方法和类方法。
我的答案:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2020/10/27 15:51
# @Author : Shadow
# @Site :
# @File : LOL.py
# @Software: PyCharm
# 定义一个Hero类作为父类
class Hero(object):
# 定义类属性
num_of_hero = []
# 定义构造方法,并把生成的英雄追加到num_of_hero这个类属性中
def __init__(self,name,blood,mana,power):
self.name = name
self.blood = blood
self.mana = mana
self.power =power
print '英雄【{}】已生成!'.format(self.name)
self.num_of_hero.append(self)
# 定义attack方法执行攻击行为
def attack(self,hero):
hero.blood = hero.blood - self.power
if hero.blood > 0:
print '{}剩余血量为:{}'.format(hero.name,hero.blood)
else:
hero.blood = 0
print '{}已被{}击杀!'.format(hero.name,self.name)
# 定义info方法来输出英雄属性
def info(self):
print '名称:{}\n血量:{}\n法力值:{}\n攻击力:{}'.format(self.name,self.blood,self.mana,self.power)
# 定义Tank类作为Hero类的子类
class Tank(Hero):
# 定义构造方法
def __init__(self,name,blood,mana,power,armor):
# 继承父类属性
super(Tank, self).__init__(name,blood,mana,power)
# 定义实例属性
self.armor = armor
self.blood = blood+armor*0.5
# 定义info方法来输出英雄属性,这里继承了父类的info方法并进行了重写
def info(self):
super(Tank, self).info()
print '护甲:{}'.format(self.armor)
# 定义Assassin类作为Hero类的子类
class Assassin(Hero):
def __init__(self,name,blood,mana,power,critical_strike):
super(Assassin, self).__init__(name,blood,mana,power)
self.power = power+critical_strike*0.5
self.critical_strike = critical_strike
def info(self):
super(Assassin, self).info()
print '暴击率:{}%'.format(self.critical_strike)
# 定义Master类作为Hero类的子类
class Master(Hero):
def __init__(self,name,blood,mana,power,magic):
super(Master, self).__init__(name,blood,mana,power)
self.magic = magic
self.power = power*0.5+magic
def info(self):
super(Master, self).info()
print '法强:{}'.format(self.magic)
# 实例化三个类
SaiEn = Tank('塞恩',1500,100,300,200)
Jie = Assassin('劫',1200,100,220,90)
Ali = Master('阿狸',1000,500,100,300)
if __name__ == '__main__':
# 调用类属性并输出当前英雄总数
print '当已生成{}个英雄!'.format(len(Hero.num_of_hero))
# 调用attack方法进行10次攻击,直至英雄死亡为止
for i in range(10):
Jie.attack(SaiEn)
if SaiEn.blood <= 0:
break
else:
continue
# 调用子类info方法,输出当前信息
SaiEn.info()