文章目录
- 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
                


















