前提紧要:

本文介绍了Python面向对象编程的核心概念,包括类与对象的定义、类的组成、特殊方法和三大特性。主要内容包括:

  1. 类与对象基础:类作为蓝图定义类型,对象是类的具体实例。通过class关键字定义类,使用类名()创建对象。

  2. 类的组成:包含成员属性(在__init__方法中定义)和成员方法(带self参数)。介绍了__init__初始化方法和__str__字符串表示方法。

  3. 封装特性:通过双下划线__实现属性/方法私有化,使用@property装饰器控制访问。

  4. 三大特性:重点讲解了封装的概念,通过隐藏内部实现细节,仅暴露必要接口(如洗衣机案例中的操作方法)。

文章通过代码示例展示了如何定义类、创建对象、访问属性和调用方法,并说明了私有化机制和封装原则在实际编程中的应用。


1. 类与对象

● 类是描述了一种类型(相当于图纸)
● 对象是这个类型的具体实现(相当于图纸具体实现)

旺财 和 狗,哪个是类,哪个是对象?

1.1. 类定义与实例化

类的定义格式:
class 类名:
pass
创建对象:
对象名 = 类名()
# 定义类
class Person:
    pass
# 创建对象
p1 = Person()

1.2. 类的组成

类可以描述世间万物,类都需要有类名,也应该具备一些属性和行为

● 类的关键字:class
● 类的名称:类名
● 类的属性:一组数据
● 类的方法:允许进行操作的方法(行为)

人(Person)类应该具备什么属性和行为呢?

1.2.1. 成员属性

成员属性的定义需要在初始化方法 init 方法下定义

def __init__(self):
  self.属性 = 属性值
#在创建对象时,属性值可以由外部传进来,也可以在初始化方法里设置为任意值
class Person:
    def __init__(self, name, age):
        # 成员属性
        self.name = name
        self.age = age

# 创建对象
p = Person('张三', 30)
# 访问成员属性
print(p.name)
print(p.age)

1.2.2. 成员方法

成员方法的定义格式为:

def 函数名(self):

成员方法都会默认有参数self,调用的时候不需要传递self

class Person:

    # 定义成员方法 say_hello
    def say_hello(self):
        print('hello')

        # 定义成员方法run
    def run(self):
        print('跑')

# 创建对象
p = Person()
# 调用成员方法
p.say_hello()

1.3. 特殊方法和参数

1.3.1. 成员方法的self参数

● 成员方法中self表示调用该方法的对象
● 对象调用方法时,python解释器会把这个对象作为第⼀个参数传递给方法
● 通过self也可以获取对象的属性,调用对象的其它成员方法

class Person:
    def __init__(self, name, age):
        # 定义成员属性
        self.name = name
        self.age = age

    def say_hello(self):
        # 通过self访问成员属性
        print(self.name)

# 对象
p = Person('张三', 30)
p.say_hello()

1.3.2. __init__方法

__init__ 是一个内置的方法
● 当对象创建的时候就会自动执行__init__方法

# 定义类
class Person:
    def __init__(self):
        print('执行了init方法')

# 创建对象
p1 = Person()
p2 = Person()

1.3.3. __str__方法

● __str__也是类的内置方法
● 用于将对象转化为适于人阅读的形式

class Person:
    def __init__(self,name,age):
        # 成员属性
        self.name = name
        self.age = age

# 创建对象
p1 = Person('张三',30)
p2 = Person('李四',40)
print(p1)
print(p2)
创建了两个对象,输出两个对象
结果:
	<__main__.Person object at 0x03769D10>
	<__main__.Person object at 0x03769FD0>

从结果中我们并不能区分出到底哪个是属于p1,哪个是属于p2
可以通过 str 提取对象的主要特征用于区分不同的对象

class Person:
    def __init__(self,name,age):
        # 成员属性
        self.name = name
        self.age = age

    def __str__(self):
        '''
        以字符串输出对象,把对象变成我们能够读懂的形式输出出来
        :return:
        '''
        return 'name:{}, age:{}'.format(self.name,self.age)

# 创建对象
p1 = Person('张三',30)
p2 = Person('李四',40)
print(p1)
print(p2)
输出结果:
name:张三, age:30
name:李四, age:40

1.4. 私有化

将属性或者方法设置为不能在外部访问,就是私有化

1.4.1. 属性私有化

属性私有化格式,注意是两个下划线__
self.__属性名 = 属性值

class MyClass:
    def __init__(self, public_value, private_value):
        self.public_value = public_value  # 公有属性
        self.__private_value = private_value  # 私有属性

    def get_private_value(self):
        return self.__private_value  # 通过公有方法访问私有属性

    def set_private_value(self, value):
        self.__private_value = value  # 通过公有方法修改私有属性

# 创建类的实例
obj = MyClass(10, 20)

# 访问公有属性
print("公有属性:", obj.public_value)  # 输出: 公有属性: 10

# 访问私有属性(会报错)
# print("私有属性:", obj.__private_value)  # AttributeError: 'MyClass' object has no attribute '__private_value'

# 通过公有方法访问私有属性
print("私有属性:", obj.get_private_value())  # 输出: 私有属性: 20

# 通过公有方法修改私有属性
obj.set_private_value(30)
print("修改后的私有属性:", obj.get_private_value())  # 输出: 修改后的私有属性: 30

1.4.2. 方法私有化

1.4.2.1. 单下划线 (_)

单下划线前缀是一种约定,表示该方法或属性是“受保护的”或“私有的”,但实际上它仍然可以被外部访问。这只是一种约定,Python并不会阻止你访问它

class MyClass:
    def _private_method(self):
        return "This is a private method"

obj = MyClass()
print(obj._private_method())  # 仍然可以访问
双下划线 (__)
双下划线前缀会导致Python对名称进行“名称修饰”(name mangling),使得它在类外部更难被直接访问。名称修饰的规则是在名称前加上 _类名,从而使得它在外部访问时需要特定的方式
class MyClass:
    def __private_method(self):
        return "This is a private method"

obj = MyClass()
# print(obj.__private_method())  # 这行会报错
print(obj._MyClass__private_method())  # 通过名称修饰后的名称访问
1.4.2.2. 使用 @property 和私有属性

使用 @property 装饰器来实现对私有属性的访问控制

class MyClass:
    def __init__(self):
        self.__private_attribute = "This is private"

    @property
    def private_attribute(self):
        return self.__private_attribute

    @private_attribute.setter
    def private_attribute(self, value):
        self.__private_attribute = value

obj = MyClass()
print(obj.private_attribute)  # 通过property访问
obj.private_attribute = "New value"  # 通过setter修改
print(obj.private_attribute)  # 再次通过property访问

1.5. 面相对象的三大特性

● 封装 (Encapsulation)
● 继承 (Inheritance)
● 多态 (Polymorphism)

1.5.1. 封装

封装就是隐藏内部实现的细节,只保留功能接口

class WashMachine:
    def __init__(self, brand, capacity):
        """
        初始化
        :param brand: 品牌
        :param capacity:  容量
        """
        self.brand = brand
        self.capacity = capacity
        # 是否关闭
        self.is_closed = False
        # 模式 0:未设定模式 1:轻揉模式 2:狂揉模式
        self.__mode = 0
        # 马达转速
        self.motor_speed = 0

    def open_door(self):
        self.is_closed = False
        print('打开洗衣机门')

    def close_door(self):
        self.is_closed = True
        print('关闭洗衣机门')

    def set_mode(self, new_mode):
        """
        调节模式
        :param new_mode:
        :return:
        """
        if new_mode not in [1, 2]:
            print('设置模式错误')
        else:
            self.__mode = new_mode

    def __set_motor_speed(self, speed):
        """
        设置马达的转速
        :param speed:  1000: 轻揉模式  2000:狂揉模式
        :return:
        """
        self.motor_speed = speed

    def wash(self):
        if not self.is_closed:
            # 洗衣机门是否关闭 ,没有关闭  提示
            print('请关闭洗衣机门...')
            return
        elif self.__mode == 0:
            print('请设置模式')
            return
        
        # 执行下面的操作
        print('放水...')
        print('放满了...')
        if self.__mode == 1:
            print('轻揉模式')
            # 调节马达转速
            self.__set_motor_speed(1000)
            print('马达转速:{}'.format(self.motor_speed))
            print('开始洗...')
        elif self.__mode == 2:
            print('狂揉模式')
            # 调节马达转速
            self.__set_motor_speed(2000)
            print('马达转速:{}'.format(self.motor_speed))
            print('开始洗...')

        print('洗完了')

machine = WashMachine('海尔', 20)
machine.open_door()
machine.close_door()
machine.set_mode(2)
machine.wash()

1.5.2. 继承

继承指的是一个对象直接使用另一个对象的属性或方法
class 子类名(父类名):

"""------------------ 定义Person类 ------------------"""
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def say_hello(self):
        print('hello from ', self.name)


"""------------------ 定义Student类继承Person ------------------"""
class Student(Person):
    def __init__(self, name, age, score):
        # 调用父类的初始化方法
        super().__init__(name, age)
        # 定义自己的属性
        self.score = score


# 创建学生类
stu = Student('小明', 15, 95)
# 访问属性
print("name: {} age: {} height: {}".format(stu.name, stu.age, stu.score))
# 调用方法
stu.say_hello()

1.5.3. 多态

● 多态指的是一类事物有多种形态(一个类有多个子类)
● 多态的概念依赖于继承

"""
多态案例
"""
# 父类
class Human:
    def eat(self):
        print('人类吃饭')

# 中国人
class ZhHuman(Human):
    def eat(self):
        print('中国人使用筷子吃饭')

# 美国人
class UsHuman(Human):
    def eat(self):
        print('美国人使用刀叉吃饭')

# 非洲人
class AfricaHuman(Human):
    def eat(self):
        print('非洲人直接用手吃饭')


# 函数
def someone_eat(someone):
    '''
    接收一个具备吃eat功能的对象
    '''
    someone.eat()


# 创建四个对象
human = Human()
zh_human = ZhHuman()
us_human = UsHuman()
africa_huamn = AfricaHuman()

# 调用方法
someone_eat(human)
someone_eat(zh_human)
someone_eat(us_human)
someone_eat(africa_huamn)

中国人、美国人、非洲人都是属于Human人类的子类,对于Human来说有多个子类就称为多态。
someone_eat 方法需要接收具备 eat 功能的对象,但是由于 ZhHuman USHuman AfricaHuman 都具备 eat 功能(继承了Human),所以也可以传递到 someone_eat 方法中

1.5.4. 多继承

当一个类从多个父类继承属性和方法时,就称为多继承
class 子类(父类1,父类2...)

class Animal:
    def __init__(self, name):
        self.name = name

    def eat(self):
        print(f"{self.name} is eating.")

    def sleep(self):
        print(f"{self.name} is sleeping.")


class Flyable:
    def fly(self):
        print(f"{self.name} is flying.")


class Swimmable:
    def swim(self):
        print(f"{self.name} is swimming.")


class Duck(Animal, Flyable, Swimmable):
    def __init__(self, name):
        super().__init__(name)


duck = Duck("Donald")
duck.eat()   # 输出: Donald is eating.
duck.sleep()   # 输出: Donald is sleeping.
duck.fly()   # 输出: Donald is flying.
duck.swim()   # 输出: Donald is swimming.

2. 异常处理

什么是异常?

● 程序在运行过程中,发生了未知的事件,影响到了程序的正常运行
● 异常是一种事件
● 异常会影响到程序正常运行

a = 10
b = 0
c = a/b
print(c)
Traceback (most recent call last):
File "c:\Users\Administrator\Desktop\测试工程\测试1.py", line 3, in <module>
c = a / b
ZeroDivisionError: division by zero

出现了 ZeroDivisionError 异常
出现异常会造成程序停止

2.1. 异常捕获

try:
 代码
except:
 出现异常的代码
# 捕获异常
try:
    result = a / b
    print('没有异常',result)
except:# 如果代码有异常会执行 ,没有异常并不会执行
    print('出现了异常')
# 捕获异常的类型
try:
    a = 10
    b = 0
    result = a / b
    print('没有异常',result)
except Exception as error:# 如果代码有异常会执行 ,没有异常并不会执行
    print('出现了异常',error)

2.2. finally

try:
  逻辑代码
finally:
  无论是否出现异常,都会执行
try:
    a = 1 / 0
    print("异常之后的代码", a)
finally:
    print("finally里的代码")

2.3. try except finally语法

try:
  逻辑代码
except Exception as error:
  print(error)
finally:
  无论是否出现异常,都会执行
f = open('a.txt','w')

try:
    f.write('hello')
    # 出现异常
    a = 10
    b = 0
    re = a/b
except:
    print('出现异常')
finally: # 即使程序出现异常  finally里面的代码也可以继续执行
    # 必须要关闭 内存泄漏
    # 无论文件是否操作失败,最终都需要关闭文件
    # 所以把文件关闭的方法放到finally中
    f.close()
    print('文件已经关闭了')

2.4. try except else finally 语法

try:
  逻辑代码
except Exception as error:
  print(error)
else:
  没有出现异常的逻辑
finally:
  无论是否出现异常,都会执行
a = 10
b = 0
try:
    result = a / b
    print(result)
except:
    print('出异常')
else:
    print('没有出异常')
finally:
    print('最终执行的代码')

2.5. 多重捕获

# 可以通过多个except捕获不同的异常分别处理
try:
    a = 1 / 0
    b = [1, 2]
    c = b[4]
except IndexError as error:
    print("indexerror 错误逻辑")
except ZeroDivisionError as error:
    print(error)

2.6. 常见的异常类型

2.6.1. IndexError

# 角标越界异常
lst = [10, 20, 30]
print(lst[6])

2.6.2. KeyError

# KeyError 字典中 的键不存在
d = {'name':'张三','age':30}
print(d['phone'])

2.6.3. ValueError

# ValueError 数据转换时出错
str = 'abc'
print(int(str))

2.6.4. AttributeError

class Person:
    def __init__(self):
        self.name = '张三'
        self.age = 30
p = Person()
print(p.id)

3. 实战练习

'''
需求:
实现银行账户管理系统
BankAccount类:这是银行账户的类,包含账户持有人姓名和余额两个属性。
__init__:构造函数,用于初始化账户持有人和余额。
deposit:存款方法,允许用户向账户存入金额。
withdraw:取款方法,允许用户从账户取出金额。
get_balance:获取当前余额的方法。
__str__:返回账户信息的字符串表示。
'''

class BankAccount:
    def __init__(self, account_holder, balance=0.0):
        self.account_holder = account_holder
        self.balance = balance

    def deposit(self, amount):
        if amount > 0:
            self.balance += amount
            print(f"存款成功!当前余额为: {self.balance}")
        else:
            print("存款金额必须大于0")

    def withdraw(self, amount):
        if amount > 0:
            if self.balance >= amount:
                self.balance -= amount
                print(f"取款成功!当前余额为: {self.balance}")
            else:
                print("余额不足,无法取款")
        else:
            print("取款金额必须大于0")

    def get_balance(self):
        print(f"账户 {self.account_holder} 的当前余额为: {self.balance}")
        return self.balance

    def __str__(self):
        return f"账户持有人: {self.account_holder}, 余额: {self.balance}"

# 示例使用
if __name__ == "__main__":
    # 创建一个账户
    account = BankAccount("张三", 1000.0)
    # 存款
    account.deposit(500.0)
    # 取款
    account.withdraw(200.0)
    # 查看余额
    account.get_balance()
    # 打印账户信息
    print(account)

以上,欢迎有从事同行业的电子信息工程、互联网通信、嵌入式开发的朋友共同探讨与提问,我可以提供实战演示或模板库。希望内容能够对你产生帮助!

更多推荐