文章目录
- P118_119 Python_封装
- 1. 面向对象编程特征
- 2. 封装介绍
- 3. 封装的细节和好处
- 4. 私有成员
- 5. 代码演示
- 5. 注意事项和使用细节
- 5.1伪私有属性
- P120 Python_继承快速入门
- 1. 为什么需要继承
- 2. 继承的基本介绍
- 3. 继承的示意图
- 4. 继承的基本语法
- P121 Python_继承的注意事项和细节
- P123 Python_调用父类成员
- 1. 基本介绍
- 2. 注意事项和使用细节
- P125 Python_重写override
- 1.基本介绍
- 2. 课堂练习题
- P126_127 Python_类型注解 (type hint)
- 1. 基本介绍
- 2. 变量的类型注解
- 3.函数(方法)的类型注解
- 4.Union类型
vx公众号_oop
P118_119 Python_封装
1. 面向对象编程特征
2. 封装介绍
3. 封装的细节和好处
4. 私有成员
- 通过公共变量引出
私有成员
- 如何私有化
5. 代码演示
# 创建职员类(Clerk),属性有name,job,salary
# 1)不能随便查看职员Clerk的职位和工资等隐私,比如职员(“tiger",“Python工程师",20000)
# 2)提供公共方法,可以对职位和工资进行操作工
class Clerk:
# 公共属性
name = None
# 私有属性
__job = None
__salary = None
# 构造方法
def __init__(self, name, job, salary):
self.name = name
self.__job = job
self.__salary = salary
# 提供公共的方案,对私有属性操作(根据实际的业务编写即可)
def set_job(self, job):
self.__job = job
def get_job(self):
print(self.__job)
# __私有方法
def __hi(self):
print("hi() ")
# 提供公共方法.操作私有方法
def f1(self):
self.__hi()
clerk = Clerk("tiger", "Python工程师", 20000)
# 如果是公共属性,在类的外部可以直接访问
print(clerk.name)
# 如果是私有属性,在类的外部不可以直接访问
# AttributeError: 'Clerk' object has no attribute '__job'
# print(clerk.__job)
clerk.get_job()
clerk.f1()
5. 注意事项和使用细节
5.1伪私有属性
class Clerk:
# 公共属性
name = None
# 私有属性
__job = None
__salary = None
# 构造方法
def __init__(self, name, job, salary):
self.name = name
self.__job = job
self.__salary = salary
def get__job(self):
return self.__job
#创建对象
clerk = Clerk("apple", "Python工程师", 20000)
# 如果这样使用,因为Python语的动态特性,会动态的创建属性--job,但是这个属性
# 和我们在类中定义的私有属性-_job 并不是同一个变量,我们在类中定义的__job 私有属性完整的名字_Clerk__job
# 这里老师使用Debug 来观察,就非常的清楚
clerk.__job ="Go工程师"
print(f"job = {clerk.__job}") # Go工程师
print("ok")
# 获取真正的私有属性__job
print(f"{clerk.get__job()}")
- 封装练习题
# 定义Account类
# 1)Account类要求具有
# 属性:姓名(长度为2-4位)、余额(必须>20)、密码(必须是六位),
# 如果不满足,则给出提示信息,并给默认值(程序员自己定)
# 2)通过set xxx的方法给Account的属性赋值。
# 3)编写方法query_info()接收姓名和密码,如果姓名和密码正确,返回该账号信息
class Account:
__name = None
__balance = None
__pw = None
def set_name(self, name):
if 2 <= len(name) <= 4:
self.__name = name
else:
print("姓名不符合规范,长度应为2-4位,请重新输入...")
def set_balance(self, balance=20):
if balance > 20:
self.__balance = balance
else:
print("余额小于20,请重新输入...")
def set_pw(self, pw="000000"):
if len(pw) == 6:
self.__pw = pw
else:
print("密码长度不符合规范应为6位,请重新输入...")
def query_info(self, name, pw):
if name == self.__name and pw == self.__pw:
return f"返回账户信息: {self.__name},{self.__balance} "
else:
return "请输入正确的用户名字和密码"
account =Account()
account.set_name("t")
account.set_pw("000000")
account.set_balance(1000)
print(account.query_info("tim","000000"))
P120 Python_继承快速入门
1. 为什么需要继承
1、Pupil 和 Graduate 有很多相同的属性和方法
2、目前这样的做法,代码复用性差
3、同时也不利于代码的维护和管理
–>继承
# 分析问题#
# 1.Pupil和Graduate 有很多相同的属性和方法
# 2.目前这样的做法,代码复用性差
# 3.同时也不利于代码的维护和管理
# 没有使用继承前的代码
# 小学生类
class Pupil:
name = None
age = None
__score = None
def __init__(self, name, age):
self.name = name
self.age = age
def show_info(self):
print(f"name= {self.name} age = {self.age} score = {self.__score}")
def set_score(self, score):
self.__score = score
def testing(self):
print(f"..小学生在考小学数学...")
class Graduate:
name = None
age = None
__score = None
def __init__(self, name, age):
self.name = name
self.age = age
def show_info(self):
print(f"name= {self.name} age = {self.age} score = {self.__score}")
def set_score(self, score):
self.__score = score
def testing(self):
print(f"..大学生在考高等数学...")
student1 = Pupil("apple", 10)
student1.testing()
student1.set_score(70)
student1.show_info()
print("".center(12,"-"))
student2=Graduate("grape", 22)
student2.testing()
student2.set_score(80)
student2.show_info()
2. 继承的基本介绍
- 更加靠近人类思维
- 多个类具有相同的属性和方法,可以抽象出父类,然后子类再进行继承
3. 继承的示意图
4. 继承的基本语法
改进后的代码inheritance.py
# 继承给编程带来的便利
# 1)代码的复用性提高了
# 2)代码的扩展性和维护性提高了
# 编写父类Student
class Student:
name = None
age = None
__score = None
def __init__(self, name, age):
self.name = name
self.age = age
def show_info(self):
print(f"name= {self.name} age = {self.age} score = {self.__score}")
def set_score(self, score):
self.__score = score
# 小学生类
class Pupil(Student):
def testing(self):
print(f"..小学生在考小学数学...")
# 大学生类
class Graduate(Student):
def testing(self):
print(f"..大学生在考高等数学...")
student1 = Pupil("apple", 10)
student1.testing()
student1.set_score(70)
student1.show_info()
print("".center(12,"-"))
student2=Graduate("grape", 22)
student2.testing()
student2.set_score(80)
student2.show_info()
P121 Python_继承的注意事项和细节
1). 子类继承了所有的属性和方法,
非私有的属性和方法可以在子类直接访问
,但是私有属性和方法不能在子类直接访问
,要通过父类提供公共的方法
去访问
#要通过父类提供公共的方法去访问
class Base:
#公共属性
n1 = 100
#私有属性
__n2=200
def __init__(self):
print("Base 构造方法....")
def hi(self) :
print("hi()公共方法");
def __hello(self):
print("__hello()私有方法")
# 提供公共方法,访问私有的属性和方法
def test(self):
print("属性:n1/n2",self.n1,self.__n2)
self.__hello()
class Sub(Base):
#子类的构造器
def __init__(self):
print("Sub 构造方法....")
def say_ok(self):
#我们发现父类的非私有属性和方法可以访问
print("say_ok()",self.n1)
self.hi()
#我们发现父类的私有属性和方法不可以访问#
# print(self.__n2)#
# self.__hello()
# 创建子类对象
sub = Sub()
sub.say_ok()
#调用于类继承父类的公共方法,去实现访问父类的私有成员的效果
sub.test()
- debug 示意图
Evaluat Expression Alt+F8
Hierarchy(层级=>看类的继承关系): Ctrl + H
2).Python编程语言中,"object"是所有其它类的基类,通过ctrl+h可以查看类的继承关系
3).Python 支持多重继承(java是单继承)
#Python支持多重继承
class A:
n1 = 100
def singing(self) :
print("A sing...",self.n1);
class B:
n2=200
def dancing(self) :
print("A dancing...", self.n2);
#C类继承了A,和B类(多重继承)
class C(A,B):
pass
# 创建子类对象
c = C()
print("--------")
# 继承的属性信息
print(f"属性信息:{c.n1},{c.n2}")
# 调用继承的方法
c.dancing()
c.singing()
4).在多重继承中,如果有同名的成员,遵守从
左到右的继承优先级
(即:写左边的父类优先级高,写在右边的父类优先级低)
- 代码练习
# 代码分析
# class GrandPa:
# name="大头爷爷"
# hobby="旅游"
#
# class Father(GrandPa):
# name="大头爸爸"
# age=39
#
# class Son(Father):
# name ="大头儿子"
#
# son = Son()
# print("son.name",son.name, "son.age", son.age,"son.hobby",son.hobby)
# 2、编写Computer类,包含CPU、内存、硬盘等属性
# 1)get_details方法用于返回Computer的详细信息
# 2)编写PC子类,继承Computer类,添加特有属性【品牌brand】
# 3)编写NotePad子类,继承Computer类,添加特有属性【color】
# 4)完成测试,创建PC和NotePad对象,分别给对象中特有的性赋值,以及从Computer类继承的属性赋值,并使用方
# 法打印输出信息【文件:inheritance exercise 0R.py]
class Computer:
cpu = None
memory = None
disk = None
def __init__(self,cpu,memory,disk):
self.cpu = cpu
self.memory = memory
self.disk = disk
def get_detail(self):
return f"CPU:{self.cpu}\t内存: {self.memory}\t硬盘: {self.disk}"
class PC(Computer):
brand = None
def __init__(self, cpu, memory, disk,brand):
# 初始化子类的属性--方法1
# self.cpu = cpu
# self.memory = memory
# self.disk = disk
# self.brand = brand
# 初始化子类的属性--方法2
# 1.通过super().xx方式可以去调用父类的方法,注意关于 super()后面还有细节会讲到
# 2.这里,我们就通过super(). __init__(cpu,memory: disk)
# 去调用父类的构造器完成对父关属性的初始化任务
# 3.self.brand = brand表示子类特有属性,由于类的构造器完成初始化
super().__init__(cpu, memory, disk)
self.brand = brand
def print_info(self):
print(f"{self.get_detail()}\t品牌: {self.brand}")
class NotePad(Computer):
color = None
def __init__(self, cpu, memory, disk, color):
super.__init__(cpu, memory, disk)
self.color = color
pc = PC("i9-12f",32,1000,"华为")
pc.print_info()
# notepad = NotePad()
# notepad.color = "black"
# notepad.cpu = "i9-13f"
# notepad.memory = "16g"
# notepad.disk = "500g"
# print(notepad.get_detail(),notepad.color)
P123 Python_调用父类成员
1. 基本介绍
- 基本语法
- 案例演示
# 通过父类名 访问父类成员
class A:
n1 = 100
def run(self):
print("A-run()...")
class B(A):
n1 = 200
def run(self):
print("B-run()...")
# say方法通过父类名去访问父类的成员
def say(self):
print(f"父类的n1 {A.n1} 本类的n1 {self.n1}")
# 调用父类的run
A.run(self) # A-run()....
# 调用本类的run
self.run() # B-run()....
# hi方法,通过super()方式去访问父类成员
def hi(self):
print(f"父类的n1 {super().n1}") #100d
# 调用父类的run
super().run()
b = B()
# b.say()
print("-- ---")
b.hi()
2. 注意事项和使用细节
- 子类不能直接访问父类的私有成员
# 访问父类成员细节
class A :
n1 = 100
__n2 = 600
def run(self):
print("A-run()...")
def __jump(self):
print("A-__jump()...")
class B(A) :
n1 = 100
__n2 = 600
def say(self):
# 子类不能直接访问父类的私有成员
# print(A.__n2)
# print(super().__n2)
A.__jump(self)
super().__jump()
print("say()....")
b = B()
b.say()
- 访问不限于直接父类,而是建立从父类向上级父类的查找关系A->B->C…
class Base :
n3 = 800
def fly(self):
print("Base-fly()...")
class A(Base) :
n1 = 100
__n2 = 600
def run(self):
print("A-run...")
def __jump(self):
print("A-__jump...")
# B->A->Base
class B(A):
def say(self):
print("say...")
# 访问不限于直接父类,而是建立从子类向上级类的查找关系A->B->Base.
# Base.n3:表示直接访间Base类的n3属性-》800
# A.n3: 表示直接访间A类的n3-> 800
# super().n3:表示从B类的直接父类A类去访问n1->800
print(Base.n3,A.n3,super().n3)
# Base.fly(self):表示直接访间Base的fly方法->Base-fly()
# A.fly(self):表示直接访间A的fly方法->Base-fly()
# super().fly():表示直接访间直接父类A的fly方法->Base-fly()
# self.fly()表示访问本类B的fly方法->Base-fly()..
Base.fly(self)
A.fly(self)
super().fly()
self.fly()
b = B()
b.say()
- 建议使用 super()的方式,因为如果使用
父类名
方式,一旦父类变化,类名统一需要修改,比较麻烦 - 代码练习题
# 代码分析题
class A :
n1 = 300
n2 = 500
n3 = 600
def fly(self):
print("A-fly()...")
class B(A) :
n1 = 200
n2 = 400
def fly(self):
print("B-fly()...")
# C->B->A
class C(B):
n1 = 100
def fly(self):
print("C-fly()...")
def say(self):
print(self.n1) # 100
print(self.n2) # 400
print(self.n3) # 600
print(super().n1) # 200
print(B.n1) # 200
print(C.n1) # 100
self.fly() # C-fly()...
A.fly(self) # A-fly()... # A()创建A类队对象
super().fly()
b = C()
b.say()
P125 Python_重写override
1.基本介绍
2. 课堂练习题
- 思路分析+ 代码实现
class Person:
name = None
age = None
def __init__(self, name, age):
self.name = name
self.age = age
def say(self):
return f"name: {self.name},age: {self.age}"
class Student(Person):
id = None
score = None
def __init__(self,name,age ,id, score):
# self.name = name
# self.age = age
# 调用父类的构造器完成继承父类的属性的初始化
super.__init__(name,age)
# 子类特有的属性我们自己完成初始化
self.id = id
self.score = score
def say(self):
return (f"{super().say()},id: {self.id},age: {self.age}")
p = Person("John",18)
print(p.say())
s = Student("Zoran",29,1,90)
print(s.say())
P126_127 Python_类型注解 (type hint)
- 参考文档
- https://docs.python.org/zh-cn/3.12/glossary.html
1. 基本介绍
- 类型注解作用和说明
# 对字符串进行遍历
# a:str 给形参a进行类型注解,标注a的类型是str
def fun1(a: str):
for ele in a:
print(ele)
# ctrl+p 提示参数时,没有类型提示
# 如果类型传错了,就会出现异常
fun1(100)
2. 变量的类型注解
- 基本语法
变量: 类型
- 基础数据类型注解
# 基础数据类型注解
'''
1.n1:int:对n1进行类型注解,标注n1的类型为int
2.注意如果,给出的值的类型和标注的类型不一致,则PyCharm会给出黄色警告
'''
# 解读
n1: int = 10
n2: float = 10.1
is_pass: bool = True
name: str = "风陵渡"
# 实例对象类型注解
class Cat:
pass
cat: Cat = Cat()
# 容器类型注解
# 实例(variable_type_hint.py)
# 解读
# 1.my_list:list 对my_list进行类型注解,标注my_list类型为list
# 容器类型注解
my_list: list = [100, 200, 300]
my_tuple: tuple = ("run", "sing", "fly")
my_set: set = {"jack", "tim", "hsp"}
my_dict: dict = {"no1": "北京", "no2": "上海"}
#容器详细类型注解
"""
my_list2: list[int]
对 my_list2进行类型注解:标注 my_list2类型是list,而且该list元素是int...
"""
my_list2:list[int]=[100,200,300]
# 元组类型设置详细类型注解,需要把每个元素类型都标注一下
my_tuple2:tuple[str,str,str,float]=("run","sing","fly",1.1)
my_set2:set[str]={"jack","tim","hsp"}
# 字典类型设置详细类型注解,需要设置两个类型,即[key类型,value类型]
# my_dict2:dict[str,int]:对my_dict2进行类型注解,标注my_dict2类型是dict,
# 而且#key的类型是str,values的类型是int
my_dict2:dict[str,int]={"no1":100,"no2":200}
#注释中使用注解
# 在注释中使用注解基本语法 #type:类型
#解读#type: foat 用于标注 变量n3 的类型是 foat
n3=89.9 #type: foat
my_list3=[100,200,300] # type: list[int]
email ="hsp@sohu.com"# type: str
3.函数(方法)的类型注解
- 基本语法
# 对字符串进行遍历
"""
解读
1.name: str对形参name进行类型注解:标注name类型是str
2.在调用方法 / 函数时,传入的实参类型不是一样的,则给出黄色的警告
def fun1(name: str):
for ele in name:
print(ele)
# fun1("韩顺平")
fun1()
"""
#接收两个整数,返回整数
"""
分析
1.a:int,b:int :对形参a,和b进行类型注解,标注a,b的类型为int
2. -> int 对返回值进行类型注解,标注返回值的类型为int
"""
def fun2(a:int,b:int)-> int:
return a+b
print(f"结果是: {fun2(10,20)}")
- 注意
-
提示性作用, 并不是强制性的!
def fun2(a:int,b:int)-> int:
return a+b
print(f"结果是: {fun2(10.1,20)}")
4.Union类型
- 参考文档
https://docs.python.org/zh-cn/3.12/library/typing.html?highlight=union#typing.Union
-
基本介绍
-
基本语法
# 实例(union type hint.py)
# 如果要使用Union类型注解,则需要导入Union
from typing import Union
# 联合类型注解,王可以是int或者str
a: Union[int, str] = 100
# my_list是list类型,元素可以是int或者str
my_list: list[Union[int, str]] = [100, 200, 300, "tim"]
# 函数方法使用联合类型注解#接收两个数(可以是intHoat),返回数(intHoat)
def cal(num1: Union[int, float],
num2: Union[int, float]) -> Union[int, float]:
return num1 + num2