私有和公有
1.在python中定义的方法和属性可以添加访问控制权限(即在什么地方可以使用这个属性和方法)
2.访问控制权限分为两种,公有权限,是有权限
3.公有权限
> 直接书写方法和属性,都是公有的
> 共有的方法和属性,可以在任意地方访问和使用
4.私有权限
> 再属性名和方法名前面书写 加上两个下划线, 这个属性或者方法变为私有,私有的权限和属性只能在类的内部使用
5.什么时候定义私有
> 1. 不想在类的外部被访问和使用,就将其定义为私有即可
> 2. 测试中一般不怎么使用吗,直接共有即可
> 3. 开发中,会根据需求文档,确定什么作为私有
- 案例
定义一个persion类,属性name,age(私有)
继承
1. 继承描述的是类与类之间的关系
2. 继承的好处:减少代码冗余(相同的代码不需要多次重复书写)可以直接使用
语法
# class A(object):
class A: # 没有写父类,但也有父类,object,object类是python中最顶级(最原始)的类
pass
class B:
pass
1. A类,称为父类(基类)
2. B类,称为子类(派生类)
单继承: 一个类只继承一个父类
继承之后的特点:
> 子类(B)继承父类(A)之后,子类的对象可以直接使用父类定义的公有属性和方法
-
案例
1. 定义一个 动物类,吃 2. 定义一个 狗类,继承动物类,吃,叫 3. 定义一个 哮天犬类, 继承, 狗类
- 代码
# 定义一个动物类 class Animal: def eat(self): print('要吃东西') # 2. 定义一个dog类 class Dog(Animal): def bark(self): print('叫') # 定义一个哮天犬类 class XTQ(Dog): pass # 创建 动物类对象 ani = Animal() ani.eat() dog = Dog() dog.bark() dog.eat() xtq = XTQ() xtq.eat() xtq.bark()
重写
重写:在子类中定义了和父类中名字相同的方法,就是重写
原因:父类中的方法不能满足子类中的需求,所以重写
重写之后的特点:调用子类自己的方法,不再用调用父类
1.覆盖,(父类中的方法完全抛弃)
2.扩展(还可以调用父类中的方法)
覆盖
覆盖:直接书写和父类名字相同的方法
代码
class Dog:
def bark(self):
print('汪汪汪叫')
class XTQ(Dog):
# 覆盖式书写
def bark(self):
print('喵喵喵')
pass
xtq = XTQ()
xtq.bark()
扩展父类中的功能
1.直接在子类中定义父类中名字相同的方法
2.在合适的地方调用 父类中方法 super().方法
3.书写添加的新功能
代码
class Dog:
def bark(self):
print('汪汪汪叫')
class XTQ(Dog):
# 覆盖式书写
def bark(self):
print('喵喵喵')
super().bark() # print()如果父类中的代码有多行
print('喵喵喵')
pass
xtq = XTQ()
xtq.bark()
多态
1.是一种写代码,调用的技巧
2.同一个方法,传入不同的对象,执行得到不同的结果,这样的现象称为多态
练习
类属性和实例属性
练习1
定义一个Dog类,定义一个类属性count,实例对象name,用来记录创建该类对象个数,(即每创建一个对象,count的值就+1)
'''
练习一
定义一个Dog类,定义一个类属性count,实例对象name,用来记录创建该类对象个数,(即每创建一个对象,count的值就+1)
'''
class Dog:
# 定义类属性
count = 0
def __init__(self, name):
self.name = name # 实例属性
# 因为每创建一个对象,就会调用init方法,就将个数加 1 的操作,写在init方法中
Dog.count += 1
def __str__(self):
return f'小猫名字: {self.name}'
# 在外部
# 打印输出目前创建几个对象
print(Dog.count) # 0
# 创建一个对象
dog1 = Dog('小花')
print(dog1)
print(dog1.count) # 1
dog2 = Dog
print(dog2.count) # 不是创建对象,个数不变
补充
1.可以使用 实例对象.类属性名 来获取类属性的值 (原因,实例对象属性的查找顺序, 先在实例属性中找,找到直接使用)
2.没有找到回去类属性中找,,找到了可以使用,没有找到会报错
print(dog1.count) # count不变
print(dog4.count) # count不变
print(dog5.count) # count不变
方法的划分
方法,使用def关键字定义在class中的函数
实例方法(最常用)
-
定义
# 在类中直接定义的方法 就是 实例方法 class Demo: def func(self): # 参数一般写作self,表示的是实例对象 pass
-
定义时机(什么时候用)
如果在方法中需要使用实例属性(即需要self),则这个方法必须定义为 实例方法
-
调用
对象.方法名() # 不需要给self传参
类方法 (会用)
-
定义
# 在方法名字的上方书写的 @classmethod 装饰器(使用@classmethod 装饰的方法) calss Demo: @classmethod def func(cls): # 参数一般写作cls,表示类对象(即类名)calss pass
- 定义时机(什么时候用)
1.前提:方法中不需要使用 实例属性(即self)
2.用到了类属性,可以将这个方法定义为类方法,也可以定义为实例方法
-
调用
1.通过类对象调用 类名.方法名() # 也不需要给cls传参,python解释器自动传递 2. 通过实例对象调用 实例.方法名() # 也不需要给cls传参,python解释器自动传递
静态方法(一般不用)
-
定义
# 在方法的名字上方书写@classmethod 装饰器 (@staticmethod 装饰的方法) class Demo: @staticmethod def func(): # 一般没参数 pass
-
定义时机(什么时候用)
1.前提:方法中不需要使用 实例属性(即self) 2.不使用类属性属性,也不使用实例属性,可以将这个方法定义为静态方法
-
调用
# 通过对象调用 类名.方法名() # 通过实例对象调用 实例.方法名()
题目2(游戏)
- 基本版本
import random
class Game:
# 类属性,游戏的最高分
top_score = 0
def __init__(self, name):
# 定义实例属性
self.name = name
def __str__(self):
return f'{self.name}'
def show_help(self):
print('这是游戏的帮助信息:')
def show_top_score(self):
print(f'游戏最高分为:{Game.top_score}')
def start_game(self):
print('开始游戏')
score = random.randint(10, 100)
print(f'本次游戏得分为:{score}', end=' ')
if score > Game.top_score:
# 修改最高分
Game.top_score = score
xw = Game('小王')
print(xw)
xw.show_help()
xw.start_game() # 第1次游戏
xw.show_top_score()
xw.start_game() # 第2次游戏
xw.show_top_score()
xw.start_game() # 第3次游戏
xw.show_top_score()
-
优化版本(使用类方法和静态方法)
import random class Game: # 类属性,游戏的最高分 top_score = 0 def __init__(self, name): # 定义实例属性 self.name = name def __str__(self): return f'{self.name}' @staticmethod def show_help(): print('这是游戏的帮助信息:') @classmethod def show_top_score(cls): # 使用了类属性 print(f'游戏最高分为:{Game.top_score}') def start_game(self): print(f'{self.name}开始游戏') score = random.randint(10, 100) print(f'本次游戏得分为:{score}', end=' ') if score > Game.top_score: # 修改最高分 Game.top_score = score xw = Game('小王') print(xw) xw.show_help() xw.start_game() xw.show_top_score() xw.start_game() xw.show_top_score() xw.start_game() xw.show_top_score()
补充
哈希(hash):是一个算法,可以对一个数值产生一个唯一的值(指纹)
is 可以用来判断两个对象是不是同一个对象,即 两个对象的引用是否相同
a is b ==== > id(a) == id(b)
"==" 只判断数据值是否相同
"is" 是判断引用是否相同