当前位置: 首页 > news >正文

Python | 第十一章 | 模块和包 | 面向对象编程_基础部分

P110 对象布尔值 2025/2/6

  • Python一切皆为对象,所有对象都有一个布尔值,通过内置函数bool()可以获取对象的布尔值
  • 下面对象的布尔值为False:

1、False
2、数值0
3、None
4、空字符串
5、空列表
6、空字典
7、空元组
8、空集合

  • 代码演示
# @Author :ZH_JC
# @File   :04_object_bool.py
# @Time   :2025/2/6 19:28

print("---下面对象的布尔值为False---")
print(bool(False))
print(bool(0))
print(bool(None))
print(bool(""))
print(bool([])) #空列表
print(bool(())) #空元组
print(bool({})) # 空字典
print(bool(set()))# 空集合

image-20250206195019833

# 因为所有对象都有一个布尔值,有些代码直接使用对象的布尔值做判断
content = ""
if content:
    print(f"hi {content}")
else:
    print("空字符串")

# 设置空列表或有内容:
lst =[]
if lst:
    print(f"lst: {lst}")
else:
    print("空列表")

image-20250206195441378

P111 成员方法 2025/2/7

一、基本介绍

  • 类除了有一些属性外,还会有一些行为,比如人类有年龄、姓名等属性,我们人类还有一些行为比如:可以说话、跑步.,通过学习,还可以做算术题。这时就要用成员方法才能完成。

定义类的基本语法:
class 类名:
属性…
行为…

  • 类中定义的行为(函数),我们称为:成员方法/方法

二、成员方法的定义和使用

  • 成员方法的定义
    • 在类中定义成员方法和前面学习过的定义函数,基本是一样的(原理和运行机制是一样),但是还是有点不同
  • 定义成员方法的基本语法:
    def 方法名(self, 形参列表):
    方法体

  • 解读

    • 在方法定义的参数列表中,有一个 self
    • self 是定义成员方法时,需要写上的
    • self 表示当前对象本身
    • 当我们通过对象调用方法时,self 会隐式的传入
    • 在方法内部,需要使用self,才能访问到成员变量
  • 案例演示

定义一个Person 类(name,age),完成如下要求:

  1. 添加hi 成员方法,输出"hi,python"
  2. 添加cal01 成员方法,可以计算从 1+…+1000的结果
  3. 添加cal02 成员方法,该方法可以接收一个数n,计算从 1+…+n 的结果
  4. 添加get_sum成员方法,可以计算两个数的和,并返回
# @Author :ZH_JC
# @File   :05_method_exemple.py
# @Time   :2025/2/7 16:07

class Person:
    # 属性(成员变量)
    name = None
    age = None

    # 成员方法:
    # 1. 添加hi 成员方法,输出"hi,python"
    def hi(self):
        print("hi,python")

    # 2. 添加cal01 成员方法,可以计算从 1+..+1000的结果
    def cal01(self):
        result = 0
        for i in range(1, 1001):
            result += i
        print(f"result={result}")

    # 3. 添加cal02 成员方法,该方法可以接收一个数n,计算从 1+..+n 的结果
    def cal02(self, n):
        result = 0
        for i in range(1, n + 1):
            result += i
        print(f"result={result}")


    # 4. 添加get_sum成员方法,可以计算两个数的和,并返回
    def get_sum(self, n1, n2):
        result = n1 + n2
        print(f"result={result}")

# 完成测试:
p = Person()

# 通过对象名.方法名 调用方法
p.hi()
p.cal01()
p.cal02(10)  # 55
p.get_sum(10,20) # 30

image-20250207162551608

三、注意事项和细节

  1. Python也支持对象动态的添加方法
# @Author :ZH_JC
# @File   :06_method_detail.py
# @Time   :2025/2/7 16:27

# 函数
def hi():
    print("hi, python")


class Person:
    name = None
    age = None

    def ok(self):
        print("hi, python")

# 创建两个对象:
p = Person()
p2 = Person()

"""
    1. 动态的给p对象添加方法,注意只是针对p对象添加方法
    2. m1是你新增加的方法名称,有程序员指定
    3. 即m1方法和函数hi关联起来,当调用m1方法时,会执行hi函数
"""
p.m1 = hi
# 调用m1(即hi)
p.m1()

# 因为没有动态的给p2添加方法,会报错
# p2.m1()

# 通过函数的则是函数;在类中定义的方法则是method
print(type(p.m1)) # <class 'function'>
print(type(p.ok)) # <class 'method'>

image-20250207163758251

P112 self 2025/2/8

一、引出问题

  • 有这么一段代码
# @Author :ZH_JC
# @File   :07_self.py
# @Time   :2025/2/8 10:38

class Dog:
    name = "波斯猫"
    age = 2

    def info(self, name):
        print(f"name信息:{name}")  # 加菲猫?


dog = Dog()
dog.info("加菲猫")
  • 问题分析:如果我们希望在成员方法内,访问对象的属性/成员变量,怎么办?->self
        # 通过self.属性名 可以访问 对象的属性/成员变量
        print(f"属性name:{self.name}")  # 波斯猫

二、二说self

  • 成员方法定义的基本语法:
    def 方法名(self,形参列表):
    方法体

  • 解读

    1. 在方法定义的参数列表中,有一个 self
    1. self 是定义成员方法时,需要写上的,如果不写,则需要使用 @staticmethod标注,否则会报错
    • 参考文档:https://docs.python.org/zh-cn/3.11/library/functions.html#staticmethod

    image-20250208104941890

    class Dog:
        name = "藏獒"
        age = 2
    
        def info(self, name):
            print(f"name信息->{name}")
    
        # 静态方法
        # 解读:
        # 1. 通过@staticmethod 可以将方法转为静态方法
        # 2. 如果是一个静态方法,可以不带self
        # 3. 静态方法的调用形式有变化
        @staticmethod
        def ok():
            print("ok()...")
    
    dog = Dog()
    dog.info("德牧")
    
    # 调用静态方法
    #方式1:通过对象调用
    dog.ok()
    # 方式2:通过类名调用;注意普通方法不可以使用类名调用
    Dog.ok()
    
    1. self表示当前对象本身,简单的说,哪个对象调用,self就代表哪个对象
    class Dog:
    
        name = "藏獒"
        age = 2
    
        def hi(self):
          print(f"hi self: {id(self)}")
    
    # self表示当前对象本身
    # 创建对象dog2
    dog2 = Dog()
    print(f"dog2: {id(dog2)}")
    dog2.hi()
    
    print("------------------")
    # 创建对象dog3
    dog3 = Dog()
    print(f"dog3: {id(dog3)}")
    dog3.hi()
    

    image-20250208110502612

    1. 当我们通过对象调用方法时,self 会隐式的传入(就是不需要传入参数,不需要写,自动传)
    1. 在方法内部,要访问成员变量和成员方法,需要使用self
    class Dog:
        name = "藏獒"
        age = 2
    
        def eat(self):
            print(f"{self.name}饿了..")
    
    
        def cry(self, name):
            # 这个name就是局部变量的name
            print(f"{name} is crying")
            # 这个name就是成员变量,属性
            print(f"{self.name} is crying")
            # 调用成员方法:同样要加self()代表调用本类
            self.eat()
    
    dog =Dog()
    # 修改了dog对象的属性name = 中华田园犬
    dog.name ="中华田园犬"
    dog.cry("金毛")
    

    image-20250208111832972

三、课堂练习题

  • 定义Person类
    1. 里面有name、age属性
    2. 并提供compare to比较方法,用于判断是否和另一个人相等
    3. 名字和年龄都一样,就返回True,否则返回False
# @Author :ZH_JC
# @File   :08_self_class_exercise.py
# @Time   :2025/2/8 11:19

"""
    思路分析:
    1. 类名: Person
    2. 属性: name, age
    3. 方法: compare_to(self,other)
    4. 功能:名字和年龄都一样,就返回true,否则返回false。
"""
class Person:
    name = None
    age = None
    def compare_to(self,other):
        # 名字和年龄都一样,就返回true,否则返回false
        return self.name == other.name and self.age == other.age

# 创建对象1:
per01 = Person()
per01.name = "张三"
per01.age = 18
# 创建对象2:
per02 = Person()
per02.name = "李四"
per02.age = 20

# 调用per01,self此时就是per01,将per02传进去比较
print(per01.compare_to(per02))

P113 对象传参机制 2025/2/8

  • 对象传参机制

    • 这里我们讨论的对象,是通过我们自定义的类创建的对象,比如 Cat 类->cat对象 Person类->person对象
    • 看一个案例,分析结果是什么?
    # @Author :ZH_JC
    # @File   :09_object_传参机制.py
    # @Time   :2025/2/8 13:41
    
    class Person:
        name = None
        age = None
    
    # 分析:对象作为参数传递到函数/方法的机制(会不会影响函数/方法外的实参)
    def f1(person):
        print(f"②person的地址:{id(person)}")
        person.name = "james"
        person.age += 1
    
    # 创建对象p1
    p1 = Person()
    
    p1.name = "jordan"
    p1.age = 21
    
    print(f"①p1的地址:{id(p1)} p1.name: {p1.name} p1.age: {p1.age}")
    f1(p1)
    print(f"③p1的地址:{id(p1)} p1.name: {p1.name} p1.age: {p1.age}")
    

image-20250208135218184

一、内存分析图

image-20250208135106016

  • 小结:会影响函数/方法外的实参,可以说是引用(地址)传递

P114 作用域 2025/2/8

一、基本介绍

  • 面向对象中,变量作用域是需要掌握的知识点,请小伙伴注意听,认真思考,要求掌握好变量作用域。
  1. 在面向对象编程中,主要的变量就是成员变量(属性)局部变量
class Cat:
	# 属性
    name = None
    age= None
    
#n1,n2,result 就是局部变量
def cal(self, h1, n2)
    result=n1 +n2
    print(f'result={result}")
  1. 我们说的局部变量,一般是指在成员方法中定义的变量
  2. 作用域的分类:属性作用域为整个类,比如 Cat类:cry eat 等方法使用属性【举例】
# @Author :ZH_JC
# @File   :10_var_scope.py
# @Time   :2025/2/8 13:59

class Cat:
    # 属性:作用域在整个类中
    name = None
    age = None

    # n1,n2,resu4tt就是局部变量
    def cal(self, n1, n2):
        result = n1 + n2
        print(f"result={result}")
        print(f"cal()使用属性 name {self.name}")


    def cry(self):
        print(f"cry()使用 属性name {self.name}")

    def eat(self):
        print(f"eat()使用 属性name {self.name}")

cat = Cat()
cat.cal(10, 20)
cat.cry()
cat.eat()

image-20250208140340560

  1. 局部变量:也就是方法中定义的变量,作用域是在它的方法中

  2. 属性和局部变量可以重名,访问时带上self,表示访问的属性,没有带self,则是访问局部变量

class Cat:
# 属性
    name = None
    age = None

    def hi(self):
        name ="皮皮"
        print(f"name={name}")       # 皮皮
        print(f"name={self.name}")  # None

cat = Cat()
# 如果改动self也会改变
cat.name = "小咪"

print("----------------")
cat.hi()

image-20250208140825633

P115 构造方法 2025/2/8

一、需求引出

  • 前面我们在创建Person类的对象时,提先把一个对象创建好后,再给他的年龄、姓名属性赋值
  • 如果现在我要求,在创建Person类的对象时,就直接指定这个对象的属性(年龄、姓名),该怎么做?-> 使用构造方法(有些文档也称为构造器)

二、基本介绍

  • 构造方法(构造器)基本语法:
    def __init__(self,参数列表)
    代码…
  • 解读构造方法

    1. 在初始化对象时,会自动执行 __init__方法
    # 在初始化对象时,会自动执行 __init__方法
    
    class Person:
        # 构造方法/构造器
        def __init__(self):
            print("__init__ 执行了")
    
    p1 = Person() #  会输出 __init__ 执行了
    
    1. 在初始化对象时,将传入的参数,自动传递给__init__方法
    class Person:
        name = None
        age = None
    
        # 构造方法/构造器
        # 构造方法是完成对象的初始化任务,
        def __init__(self,name,age):
            print(f"__init__ 执行了{name} {age}")
    
            # 解读:
            # 1. 把接收到的name和age赋值给属性(name,age)
            # 2. self 就是你当前创建的对象
            print(f"self id{id(self)}")
            self.name = name
            self.age = age
    
    # 创建对象
    p1 = Person("kobe",20)
    print(f"p1 id{id(p1)}")
    print(f"p1的信息={p1.name} {p1.age}")
    
    p2 = Person("tim",30)
    print(f"p2 id{id(p2)}")
    print(f"p2的信息={p2.name} {p2.age}")
    
    1. 构造方法是py预定义的,名称是__init__,注意__init__ 的前后都有两个__

三、快速入门

  • 现在我们就用构造方法来完成刚才提出的问题:在创建人类的对象时,就直接指定这个对象的年龄和姓名,前面老师已经讲过的,这里就整理一下代码
class Person:
    name = None
    age = None

    # 构造方法/构造器
    # 构造方法是完成对象的初始化任务,
    def __init__(self,name,age):
        print(f"__init__ 执行了{name} {age}")

        # 解读:
        # 1. 把接收到的name和age赋值给属性(name,age)
        # 2. self 就是你当前创建的对象
        print(f"self id{id(self)}")
        self.name = name
        self.age = age

# 创建对象
p1 = Person("kobe",20)

四、注意事项和使用细节

  1. __init__方法,即使你写了多个,也只有最后一个生效一个类只有一个
class Person:
    name = None
    age = None

    def __init__ (self, name, age):
        print(f"__init__执行了.. 得到了{name} {age}")
        self.name = name
        self.age = age

    def __init__ (self, name):
        print(f"__init__~~执行了…. 得到了{name}")
        self.name = name

# 0.报错,只能有一个构造方法,最后一个为准
# p1= Person("kobe",20)

# 0.后面的__init()__ 生效,是可以的
p1=Person("kobe")

print(f"p1的 name={p1.name} age={p1.age}") # kobe None

在Python实现多个构造方法,有兴趣的小伙伴可以百度,这里有一篇文章,可以百度

  1. python可以动态的生成对象属性,代码说明
class Person:

    # 此时这里是没有定义name和age

    def __init__(self, name, age):
        print(f"__init__ 执行了...得到了{name} {age}")
        # 将接受到的name和age 赋值给当前对象的name和age属性
        # Python 支持动态生成对象属性,即使前面没有创建对象属性
        self.name = name
        self.age = age

p1 = Person("tim", 30) 
print(f"p1的 name={p1.name} age={p1.age}")

image-20250208170930145

3、构造方法不能有返回值,比如,你返回字符串,会报错:TypeError: __init__() should return None, not 'str'

    def __init__(self, name, age):
        print(f"__init__ 执行了...得到了{name} {age}")
        # 将接受到的name和age 赋值给当前对象的name和age属性
        # Python 支持动态生成对象属性,即使前面没有创建对象属性
        self.name = name
        self.age = age
        return "hello"  # 会报错

P116 本章作业 2025/2/13

一、题目练习

  1. 编写类A01,定义方法max,实现求某个float 列表list =[1.1,2.9,-1.9,67.9]的最大值,并返回
"""
    思路分析:
    1. 类名:A01
    2. 方法:max(self,list),功能:返回列表的最大值
"""

class A01:
    def max(self,list1):
        return max(list1)

# 完成测试:创建对象 a = A01()
A1 = A01()

list_test = [1.1,2.9,-1.9,67.9] # 67.9
print(A1.max(list_test))
  1. 编写类Book,定义方法update price,实现更改某本书的价格,具体:如果价格>150,则更改为150,如果价格>100,更改为 100,否则不变
# 2、编写类Book,定义方法update price,实现更改某本书的价格,
# 具体:如果价格>150,则更改为150,如果价格>100,更改为 100,否则不变

"""
    类名:Book
    属性:name,price
    构造器:__init__(self,name,price)
    方法:update_price
"""
class Book:
    # python可以动态生成name,price,就可以拿掉了
    def __init__(self, name, price):
        self.name = name
        self.price = price

    def update_price(self):
        if self.price > 150:
            self.price = 150
        elif self.price > 100:
            self.price = 100

    # 增加一个输出书籍信息的方法
    def info(self):
        print(f"书的信息:{self.name} {self.price}")

# 测试
book = Book("天龙八部",50)
book.info()
book.update_price()
book.info()
  1. 定义一个圆类Circle,定义属性:半径,提供显示圆周长功能的方法, 提供显示圆面积的方法
"""
    思路分析:
    1. 类名:Circle
    2. 属性:radius 动态生成
    3. 构造器:__init__(self,radius)
    4. 方法: len(self) 显示圆周长
    5. 方法:area(self) 显示面积
"""
# 导入math模块
import math

class Circle:
    def __init__(self, radius):
        self.radius = radius

    def len(self):
        len = 2 * math.pi * self.radius
        print("圆周长:", round(len, 2))

    def area(self):
        area = math.pi * self.radius * self.radius
        print("面积", round(area, 2))

# 测试:

circle = Circle(6)
circle.len()
circle.area()

image-20250213120941747

  1. 编程创建一个Cal计算类,在其中定义2个成员变量表示两个操作数,定义四个方法实现求和、差、乘、商(要求除数为0的话,要提示)并创建对象,分别测试
"""
    思路分析:
    1. 类名:Cal
    2. 属性:num1, num2
    3. 构造器/构造方法: __init__(self,num1,num2)
    4. 定义四个方法求和sum()、差minus()、乘mul()、商div()
    5.商(要求除数为0的话,要提示)
"""

class Cal:
    def __init__(self,num1,num2):
        self.num1 = num1
        self.num2 = num2

    # 和
    def sum(self):
        return self.num1 + self.num2
    # 差
    def minus(self):
        return self.num1 - self.num2

    # 乘
    def mul(self):
        return self.num1 * self.num2
    # 除
    def div(self):
        # 商(要求除数为0的话,要提示)
        if self.num2 == 0:
            print("num不能为0")
            return None
        else:
            return self.num1 / self.num2

cal = Cal(2,0)
print("和=",cal.sum())
print("差=",cal.minus())
print("乘=",cal.mul())
print("除=",cal.div())
  1. 定义Music类,里面有音乐名name、音乐时长times属性,并有播放play功能,和返回本身属性信息的方法get_info
"""
    思路分析:
    1. 类music
    2. 属性: name,times
    3. 构造器__init__(self,name,times)
    4. 方法:play,get_info
"""

class Music:
    def __init__(self,name,times):
        self.name = name
        self.times = times

    def play(self):
        print(f"音乐名{self.name}正在播放中...时长为{self.times}")

    def get_info(self):
        return f"音乐的信息为name:{self.name} times:{self.times}"

# 测试:
music = Music("月光曲",300)

music.play()
print(music.get_info())

image-20250213125758235

  1. 程序分析:试写出运行结果

image-20250213125821343

image-20250213125914981

class Demo:
    i = 100
    def m(self):
        self.i += 1 # 101
        j = self.i # 101
        print("i=",self.i)
        print("j=", j)

d1 = Demo()
d2 = d1
d2.m()
print(d1.i)
print(d2.i)
  1. 思考题(自己做)

image-20250213130452677

image-20250213130525832

# @Author :ZH_JC
# @File   :19_homework07.py
# @Time   :2025/2/13 13:10

# 为AI编写,有点难度
import random

class RockPaperScissorsGame:
    def __init__(self):
        """
        初始化游戏状态,包括Tom的胜利次数、电脑的胜利次数和平局次数。
        """
        self.tom_wins = 0  # Tom的胜利次数
        self.computer_wins = 0  # 电脑的胜利次数
        self.ties = 0  # 平局次数

    def get_computer_choice(self):
        """
        随机生成电脑的选择(0: 石头, 1: 剪刀, 2: 布)。

        返回:
            int: 随机选择的值(0, 1, 或 2)。
        """
        return random.randint(0, 2)

    def get_result(self, tom_choice, computer_choice):
        """
        根据Tom和电脑的选择,确定游戏结果并更新相应的胜利次数或平局次数。

        参数:
            tom_choice (int): Tom的选择(0: 石头, 1: 剪刀, 2: 布)。
            computer_choice (int): 电脑的选择(0: 石头, 1: 剪刀, 2: 布)。
        """
        choices = ["Rock", "Scissors", "Paper"]  # 定义选择的名称列表

        # 打印Tom和电脑的选择
        print(f"Tom chose: {choices[tom_choice]}")
        print(f"Computer chose: {choices[computer_choice]}")

        # 判断结果并更新分数
        if tom_choice == computer_choice:
            print("It's a tie!")
            self.ties += 1
        elif (tom_choice == 0 and computer_choice == 1) or \
                (tom_choice == 1 and computer_choice == 2) or \
                (tom_choice == 2 and computer_choice == 0):
            print("Tom wins!")
            self.tom_wins += 1
        else:
            print("Computer wins!")
            self.computer_wins += 1

    def play_game(self):
        """
        游戏的主循环,处理用户的输入,执行游戏逻辑,并询问用户是否要继续游戏。
        """
        while True:
            try:
                # 获取用户输入的选择
                tom_choice = int(input("Enter your choice (0: Rock, 1: Scissors, 2: Paper): "))

                # 检查输入是否有效
                if tom_choice not in [0, 1, 2]:
                    print("Invalid choice. Please enter 0, 1, or 2.")
                    continue

                # 获取电脑的选择
                computer_choice = self.get_computer_choice()

                # 确定游戏结果
                self.get_result(tom_choice, computer_choice)

                # 询问用户是否要继续游戏
                another_round = input("Do you want to play another round? (yes/no): ").strip().lower()
                if another_round != 'yes':
                    break
            except ValueError:
                # 处理非整数输入
                print("Invalid input. Please enter a number.")

        # 游戏结束,打印最终得分
        print("\nFinal Scores:")
        print(f"Tom Wins: {self.tom_wins}")
        print(f"Computer Wins: {self.computer_wins}")
        print(f"Ties: {self.ties}")


# 示例用法:创建游戏实例并开始游戏
game = RockPaperScissorsGame()
game.play_game()

P117 小结 2025/2/13

image-20250213130801530

P118 封装快速入门 2025/2/13

一、面向对象的三大特征

  • 基本介绍

    1. 面向对象编程有三大特征:封装继承多态
  • 封装介绍

    1. 封装(encapsulation)就是把抽象出的数据[属性]和对数据的操作[方法]封装在一起,数据被保护在内部
    2. 程序只有通过被授权的操作,才能对数据进行访问

image-20250213161700237

  • 封装的理解和好处
    1. 隐藏实现细节:方法(绘制柱状图)<–调用(传入参数…)
    2. 可以对数据进行验证(比如age:1~120,password 长度要求等),保证安全合理
    3. 可以保护数据隐私(比如salary),要求授权才可以访问

二、私有成员

  • 说明公共的变量和方法
    1. 默认情况下,类中的变量和方法都是公有的,它们的名称前都没有下划线
    2. 公共的变量和方法,在类的外部、类的内部,都可以正常访问,
    3. 实例:[注释]
  • 1、如何将属性/方法进行私有化
    • 类中的变量或方法以双下划线__开头命名,则该变量或方法为私有的,私有的变量或方法,只能在本类内部使用,类的外部无法
      使用
  • 2、如何访问私有的属性/方法:提供公共的方法,用于对私有成员的操作

三、快速入门

  • 创建职员类(Clerk),属性有 name,job,salary

    1)不能随便査看职员Clerk的职位和工资等隐私,比如职员(“tiger”,“Python工程师”,20000)

    2)提供公共方法,可以对职位和工资进行操作

  • 代码演示
# @Author :ZH_JC
# @File   :01_encap_quick_start.py
# @Time   :2025/2/13 16:27

class Clerk:
    # 公共属性:
    name = None

    # 私有属性:(私有方法或者属性在内部是可以调用的)
    __job = None
    __salary = None

    # 私有方法:
    def __hi(self):
        print("hi")

    # 0.0 提供公共方法,操作私有方法
    def f1(self):
        self.__hi()

    # 构造方法:
    def __init__(self, name, job, salary):
        self.name = name
        self.__job = job
        self.__salary = salary

    # 0.1 提供公共的方法,对私有属性操作(根据实际的业务编写即可)
    # 1. 设置值
    def set_job(self, job):
        self.__job = job

    # 2.获取值
    def get_job(self):
        return self.__job

clerk = Clerk("tiger", "Python工程师", 20000)

# 如果是公共属性,在类的外部可以直接访问
print(clerk.name)

# 如果是私有属性,在类的外部就不可以直接访问
# print(clerk.__job)
# AttributeError: 'Clerk' object has no attribute '__job'

# 设置公共操作后,再次获取job值
print(clerk.get_job())  # Python工程师
clerk.set_job("Java工程师")
print(clerk.get_job())  # Java工程师

# 私有方法不能再类的外部直接访问
#  'Clerk' object has no attribute '__hi'
# clerk.__hi()

# 通过公共方法,调用私有方法
clerk.f1()

image-20250213191220883

P119 封装细节和练习 2025/2/15

一、封装细节和练习

  1. Python语言的动态特性,会出现伪私有属性的情况
# @Author :ZH_JC
# @File   :02_encap_detail.py
# @Time   :2025/2/15 11:08

class Clerk:
    # 公共属性
    name = None
    # 私有属性
    __job = None
    __salary = None

    # 构造方法
    def __init__(self, name, job, salary):
        self.name = name
        self.__salary = salary
        self.__job = job

    def get_job(self):
        return self.__job


clerk = Clerk("tiger", "Python工程师", 20000)


"""
如果这样使用,因为Python语言的动态特性,会动态的创建属性 __job,但是这个属性
和我们在类中定义的私有属性__job 并不是同一个变量,我们在类中定义的__job 私有属性完整的名字_Clerk__job
这里老师使用Debug 来观察,就非常的清楚
"""

clerk.__job = "Go工程师"
print(f"job={clerk.__job}") # Go工程师
print("ok")

print(clerk.get_job()) # Python工程师

image-20250215111952594

二、练习题

  • 定义Account类:
  1. Account类要求具有属性:姓名(长度为2-4位)、余额(必须>20)、密码(必须是六位),如果不满足,则给出提示信息,并给默认值(程序员自己定)
  2. 通过set_xxx的方法给Account 的属性赋值。
  3. 编写方法query_info()接收姓名和密码,如果姓名和密码正确,返回该账号信息
# @Author :ZH_JC
# @File   :03_encap_exercise.py
# @Time   :2025/2/15 11:28

# 定义Account类

# 1. Account类要求具有属性:姓名(长度为2-4位)、余额(必须>20)、密码(必须是六位),如果不满足,则给出提示信息,并给默认值(程序员自己定)
# 2. 通过set_xxx的方法给Account 的属性赋值。
# 3. 编写方法query_info()接收姓名和密码,如果姓名和密码正确,返回该账号信息

"""
    思路分析:
    1. 类名: Account
    2. 私有属性:姓名(长度为2-4位)、余额(必须>20)、密码(必须是六位)
    3. 构造方法:无 ,默认是一个无参的构造器
    4. 方法:set_xxx(self, 属性名) 进行赋值,并且对各个接收到的数据进行校验
    5. 方法:query_info(self,name,pwd),而且需要验证,才返回相应信息
"""

class Account:
    __name = None
    __blance = None
    __pwd = None

    def set_name(self,name):
        # 长度2-4位
        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_pwd(self,pwd):
        # 密码必须是六位
        if len(pwd) == 6:
            self.__pwd = pwd
        else:
            print("密码必须是6位")

    def query_info(self, name, pwd):
        if name == self.__name and pwd == self.__pwd:
            return f"账户信息 {self.__name} {self.__balance}"
        else:
            return "请输入正确的名字和密码!"

# 测试
account = Account()

account.set_name("tim")
account.set_pwd("000000")
account.set_balance(100)
print(account.query_info("tim","000000"))

image-20250215120131755

http://www.dtcms.com/a/106489.html

相关文章:

  • Java安全基础-反射机制
  • 《AI大模型应知应会100篇》第2篇:大模型核心术语解析:参数、Token、推理与训练
  • 基于微信小程序的智慧乡村旅游服务平台【附源码】
  • 聊聊Spring AI的EmbeddingModel
  • 好文和技术网站记录
  • Java虚拟机面试题:引言
  • 【Zabbix技术系列文章】第⑥篇——Zabbix 高级运维与优化
  • leetcode118.杨辉三角
  • Unity注册表修改分辨率:探索幕后设置与手动调控
  • 学习笔记—数据结构—排序
  • 第十二节课:Python语言程序设计和前阶段复盘总结
  • 数字孪生技术解析:开启虚拟与现实融合新时代
  • 界面架构 - 主流架构(Qt)
  • 动态取消Spring Boot通过注解@EnableScheduling启动的定时任务
  • MySQL(1)
  • 【图像处理基石】什么是RAW格式?
  • React DndKit 实现类似slack 类别、频道拖动调整位置功能
  • # BERT架构及详解
  • C# 中实现不同程序进程间消息交互
  • 【Linux网络#18】:深入理解select多路转接:传统I/O复用的基石
  • ETCD --- lock详解
  • JAVASE(十五)正则表达式
  • 2024年最新版零基础详细Java知识笔记【反射】⑩
  • Python实现 MCP 客户端调用(高德地图 MCP 服务)查询天气工具示例
  • Linux系统
  • Oracle 23ai Vector Search 系列之3 集成嵌入生成模型(Embedding Model)到数据库示例,以及常见错误
  • 16变量命名风格
  • windows部署docker
  • electron-update + nginx热更新
  • 【深度学习:进阶篇】--2.1.多分类与TensorFlow