Python 学习笔记 day07--面向对象

Python面向对象编程学习笔记

1 面向对象

Python 是一种面向对象的编程语言。

语言的发展:机器语言(0 1)  汇编语言 高级语言(C 面向过程)→ 面向对象(python)

1.1面向过程和面向对象

 面向过程:核心思想:程序 = 算法 + 数据。关注点是"怎么做"(执行步骤)

分析解决问题的步骤,然后逐步实现
例:小白买电脑
1.网上查资料
2.根据自己预算和需求定电脑型号 华硕天选
3.去线下门店实地考察
4.找业务员砍价,要赠品, 付款成交

面向对象:核心思想:程序 = 对象 + 消息。关注点是"谁来做"(责任分配)

找出解决问题的对象,然后分配任务
例:小白买电脑
1.找一个靠谱的电脑高手
2.给钱交易

1.2 面向对象的技术点:

类 (Class)

具有相同属性和方法的对象的集合

class Car: ...

方法

类中定义的函数

def start_engine():

类变量

类中定义的共享变量

wheels = 4

数据成员

类变量与实例变量的统称

brand, price

方法重写

子类重新定义父类方法

def start_engine(): ...

局部变量

方法内部定义的临时变量

temp = 0

实例变量

对象特有的属性变量

self.color = "red"

继承

子类获取父类特性的机制

class SUV(Car):

实例化

根据类创建对象的过程

car = Car()

对象(Object)

类的具体实例

my_car = Car()

1.3 类(Class)

用来描述具有相同的属性和方法的对象的集合。类定义该集合中每个对象所共有的属性和方法。

对象是类的实例。

1.3.1 创建类

关键字 class 后边跟类名以冒号结束 (类名尽量所有的单词首字母大小)

class q:
  x = 5

类由3部分组成:类名、属性、行为

class Car:  #定义一个名为 Car 的类
    """
    记录车

    """
    num = 0  # 类属性:记录创建的汽车总数

    def __init__(self, color, price, model):
        self.color = color  # 实例属性:汽车颜色 设置当前汽车的 color 属性
        self.price = price  # 实例属性:汽车价格 设置当前汽车的 price 属性
        self.model = model  # 实例属性:汽车型号
        Car.num += 1  # 每创建一辆车,计数器加1

num变量是一个类变量,他的值会在类的所有实例之间共享,使用Car.num访问

__init__函数也叫类的构造函数,当创建了这个类的实例时,会自动调用该方法

self:是一个参数,表示实例化对象,里边存放对象自身的地址,

定义类时self必须有,但是调用时不用传递对应的参数

1.3.2 实例化对象

格式:变量名 =类名(参数)

class Car:
    """
    记录车

    """
    num = 0  # 类属性:记录创建的汽车总数

    def __init__(self, color, price, model):
        self.color = color  # 实例属性:汽车颜色
        self.price = price  # 实例属性:汽车价格
        self.model = model  # 实例属性:汽车型号
        Car.num += 1  # 每创建一辆车,计数器加1


# 实例化对象  
car1 = Car("红色", 150000, "Model S")  # 创建了Car类的第一个对象
car2 = Car("蓝色", 200000, "Model X")  # 创建了Car类的第二个对象

print(f"已创建 {Car.num} 辆车")  # 输出:已创建 2 辆车
print(car1.model)  # 输出:Model S
1.3.3 访问方法
class Car:
    """
    记录车

    """
    num = 0  # 类属性:记录创建的汽车总数

    def __init__(self, color, price, model):
        self.color = color  # 实例属性:汽车颜色
        self.price = price  # 实例属性:汽车价格
        self.model = model  # 实例属性:汽车型号
        Car.num += 1  # 每创建一辆车,计数器加1

    def its(self):  # 普通方法
        print(f"{self.color}色的小米汽车很漂亮,售价为{self.price}元,车型为{self.model}")


# 实例化对象
car1 = Car("红色", 150000, "model S")
# 调用类中的方法
car1.its()

car2 = Car("蓝色", 200000, "model X")
# 调用类中的方法
car2.its()

可以增加、删除、修改类的属性:

       添加:  直接添加
    hasattr: 判断属性是否存在
    getattr:    获取属性值
    setattr:    修改属性值;如果属性不存在,会创建新属性
    delattr:    删除属性

class Car:
    """
    记录车

    """
    num = 0  # 类属性:记录创建的汽车总数

    def __init__(self, color, price, model):
        self.color = color  # 实例属性:汽车颜色
        self.price = price  # 实例属性:汽车价格
        self.model = model  # 实例属性:汽车型号
        Car.num += 1  # 每创建一辆车,计数器加1

    def its(self):  # 普通方法
        print(f"{self.color}色系的小米汽车很漂亮,售价为{self.price}元,车型为{self.model}")


# 实例化对象
car1 = Car("红色", 150000, "model S")

# 1. 添加 typ 属性
car1.typ = "新能源"  # 动态添加实例属性
# 验证属性添加
print(f"类型: {car1.typ}")  # 该属性仅属于 car1 实例
# 输出: 类型: 新能源

# 2. 添加 colors 属性 (注意:不同于已有的 color 属性)
car1.colors = "渐变青"  # 添加新属性 colors
print(f"颜色新增: {car1.colors}")  # 该属性仅属于 car1 实例

# 3. 删除 price 属性 (被注释,实际不执行)
# del car1.price  # 取消注释将删除 price 属性

# 4. 使用 hasattr() 判断属性是否存在
print(hasattr(car1, "typ"))  # 输出: True (存在)
print(hasattr(car1, "engine"))  # 输出: False (不存在)

# 5. 使用 getattr() 获取属性值
print(getattr(car1, "color"))  # 输出: 红色
print(getattr(car1, "colors"))  # 输出: 渐变青

# 6. 使用 setattr() 修改/设置属性值
# 修改已存在的属性
setattr(car1, "color", "黄色")  # 修改 color 属性值
print(car1.color)  # 输出: 黄色

# 7. 创建新属性
setattr(car1, "battery", "100kWh")  # 添加新属性 如果属性不存在,会创建新属性
print(car1.battery)  # 输出: 100kWh


# 调用类中的方法
car1.its()

1.4 python内置类属性

Python 为每个类提供了一系列内置属性,用于访问类的元信息。这些属性在类定义时自动创建,无需手动声明。

__doc__:类的文档字符串
__name__:类名
__dict__:类的属性(字典,数据:类的属性)
__module__:类定义所在模块(类的全名__main__ClassName)/(定义类的模块名)
__bases__:类的所有父类构成的元素(父类元组)
__class__:实例所属的类
__mro__:方法解析顺序
__subclasses__():子类列表
python 3.n,中所有的类都有一个共同父类,叫object类(顶级父类)

print("\n===== 类内置属性 =====")
print(f"1. __name__: {Car.__name__}")  # 输出:Car
print(f"2. __doc__: {Car.__doc__}")  # 输出:车辆信息记录类
print(f"3. __module__: {Car.__module__}")  # 输出:__main__(当前模块)
print(f"4. __bases__: {Car.__bases__}")  # 输出:(<class 'object'>,)
print(f"5. __dict__ keys: {list(Car.__dict__.keys())}")  # 包含类命名空间的所有成员
print(f"6. __mro__: {Car.__mro__}")
print(f"7. __subclasses__: {Car.__subclasses__()}")  # 输出:[<class '__main__.ElectricCar'>]

# 实例的 __dict__:包含实例的所有属性
print(car1.__dict__)
# 输出:{'color': '红', 'price': 150000, 'model': 'Model S'}

1.5 类的继承

继承是面向对象编程的核心概念,允许新类(子类)获取现有类(父类)的属性和方法,并添加新的功能或修改现有行为。类可以被继承也可以继承别的继承父类继承子类继承过程中子类继承父类所有的属性行为一个父类可以多个子类一个子类可以有多个父类

1.5.1 单继承

一个只有一个父类子类存在父类相同的属性方法优先子类

格式:class 子类(父类名):       # 子类特有的属性和方法

class Parent:  # 父类(基类)
    def __init__(self):
        print("调用父类构造函数")

    def houseNum(self):
        print("父亲有两个房子")


class Child(Parent):   # 子类(派生类)
    def __init__(self):
        print("调用子类构造函数")

    def CarNum(self):
        print("字类有3辆车")


c = Child()  # 实例化子类
c.houseNum()

1.5.2 多继承

一个类可以继承多个类(容易代码混乱)

如果子类父类相同的属性行为顺序:子类>从左向右第一个父类>第二个....
class Parent1:  # 父类(基类)
    def __init__(self):
        print("调用父类构造函数")

    def houseNum(self):
        print("父亲有1个房子")


class Parent2:  # 父类(基类)
    def __init__(self):
        print("调用父类构造函数")

    def houseNum(self):
        print("父亲有2个房子")


class Parent3:  # 父类(基类)
    def __init__(self):
        print("调用父类构造函数")

    def houseNum(self):
        print("父亲有3个房子")


class Child(Parent1,Parent2,Parent3):  # 子类(派生类)
    def __init__(self):
        print("调用子类构造函数")

    def CarNum(self):
        print("字类有3辆车")


c = Child()  # 实例化子类
c.houseNum()

# issubclass:判断一个类是否是另一个类的子类或者子孙类
# isinstance: 判断对象名是否是某个类的实例化对象

#基于上述代码命令,在上述代码后面进行判断

# issubclass:判断一个类是否是另一个类的子类或者子孙类
print(issubclass(Child, Parent1))
#----True

# isinstance: 判断对象名是否是某个类的实例化对象
print(isinstance(c, Child))
print(isinstance(c, Parent2))  #----因为字类继承了父类Parent2

#----True
#----True

1.6 封装

核心:把“数据”和“操作数据的函数”绑在一起,对外只暴露“该暴露的”,隐藏“不该碰的”。隐藏内部实现细节,通过方法暴露操作。

class BankAccount:
    def __init__(self, balance=0):  # 初始化方法,创建账户时设置初始余额
        self.__balance = balance  # 私有属性(双下划线开头),外部无法直接访问

    def deposit(self, amount):  # 存款方法,增加账户余额
        self.__balance += amount  # 只能通过类的方法修改私有属性

    def get_balance(self):  # 获取余额方法,公开接口访问私有数据
        return self.__balance  # 返回当前余额

# 双下划线前缀: 命名约定(非强制),表示"私有"属性

1.7 方法重写

当子类继承父类时,如果父类方法的功能不能满足需求,可以在子类重写父类的方法。如果子类定义了与父类同名的方法,则子类方法会"覆盖"父类方法
类比理解:就像你继承了父母的手机,但你把手机系统升级了 - 还是同一个手机,但功能更强了。

class A:
    def __init__(self, x, y):
        self.x = x  # 实例属性x
        self.y = y  # 实例属性y

    def axy(self):
        return self.x + self.y  # 返回x和y的和


class B(A):  # B继承自A
    def __init__(self, x, y, z):
        # 显式调用父类A的构造方法
        A.__init__(self, x, y)  # 初始化x和y属性
        self.z = z  # 新增子类特有属性z

    def axy(self):
        # 重写父类方法,添加新功能
        return A.axy(self) + self.z  # 调用父类方法并加上z的值


# 创建B类的实例
b = B(14, 25, 36)

# 调用重写后的axy方法
print(b.axy())  # 输出结果

# B继承自A,所以B拥有A的所有属性和方法,
# B 可以:
# 添加新属性(如 z)
# 添加新方法
# 重写父类方法(如 axy)


class Parent:        # 定义父类
   def myMethod(self):
      print ('调用父类方法')
 
class Child(Parent): # 定义子类
   def myMethod(self):
      print ('调用子类方法')
 
c = Child()          # 子类实例
c.myMethod()         # 子类调用重写方法
super(Child,c).myMethod() #用子类对象调用父类已被覆盖的方法

2 基础重载方法

重载方法(也称为魔术方法或特殊方法)是以双下划线开头和结尾的方法,用于自定义类的行为。这些方法允许你改变 Python 内置操作的行为,使你的类更自然地与 Python 语言集成。

2.1 构造与析构方法

class D:
    def __init__(self, value):  # 构造方法
        self.value = value
        print(f"对象已创建,值: {value}")

    def __del__(self):  # 析构方法
        print(f"对象被销毁,值: {self.value}")


obj = D(10)  
del obj  

#----对象已创建,值: 10
#----对象被销毁,值: 10

2.2 字符串表示方法

class D:
    def __init__(self, x, y):  # 定义D类,用于表示二维坐标系中的点
        # 构造方法:创建D对象时自动调用
        self.x = x  # 设置实例属性x,存储点的横坐标
        self.y = y  # 设置实例属性y,存储点的纵坐标

    def __str__(self):
        # 重载__str__方法:提供用户友好的字符串表示
        # 当使用print()、str()或格式化输出时调用
        return f"点({self.x}, {self.y})"  # 返回中文格式的坐标表示

    def __repr__(self):
        # 重载__repr__方法:提供开发者友好的正式字符串表示
        # 在交互式环境、调试或repr()函数中调用
        return f"D(x={self.x}, y={self.y})"  # 返回精确的类构造表示


# 创建D类的实例
p = D(3, 4)     # 调用__init__方法,初始化坐标为(3, 4)

# 打印str表示
print(str(p))   # 调用__str__方法 → 输出: 点(3, 4)

# 打印repr表示
print(repr(p))  # 调用__repr__方法 → 输出: D(x=3, y=4)

#-----需要简洁易懂的信息 → __str__

#-----需要精确的技术细节 → __repr__

2.3 算术运算符重载

class E:  # 新建一个类
    def __init__(self, x, y):  # 构造函数。
        # 创建对象时自动调用,把传进来的两个数分别存到对象的属性 x 和 y 里。
        self.x = x
        self.y = y  # 把参数保存成对象的实例变量

    def __add__(self, other):  # 加法运算符重载 __add__
        return E(self.x + other.x, self.y + other.y)

    def __sub__(self, other):  # 减法运算符重载 __sub__
        return E(self.x - other.x, self.y - other.y)

    def __mul__(self, scalar):  # 乘法运算符重载 __mul__
        return E(self.x * scalar, self.y * scalar)


v1 = E(2, 3)
v2 = E(4, 5)
print((v1 + v2).__dict__)  # 输出: {'x': 6, 'y': 8}
print((v1 * 3).__dict__)  # 输出: {'x': 6, 'y': 9}

# __dict__ 返回实例属性的字典形式 {'x':6, 'y':8}
# __mul__ 仅支持 实例 * 标量(如 v1 * 3),
# 不支持 标量 * 实例(如 3 * v1 会报错)
# self.x:当前实例(调用加法运算符的第一个操作数)的x值。
# other.x:另一个实例(加法运算符的第二个操作数)的x值。
# self.y:当前实例的y值。
# other.y:另一个实例的y值。
# v1 = E(2, 3),那么v1.x=2, v1.y=3
# v2 = E(4, 5),那么v2.x=4, v2.y=5
# 当执行v1 + v2时,实际上调用的是v1.__add__(v2),即:self是v1,other是v2

2.4 比较运算符重载

class R:
    def __init__(self, name, score):
        self.name = name
        self.score = score

    def __eq__(self, other):  # 等于 ==
        return self.score == other.score

    def __lt__(self, other):  # 小于 <
        return self.score < other.score

    def __le__(self, other):  # 小于等于 <=
        return self.score <= other.score


b1 = R("ZX", 95)
b2 = R("LS", 89)
print(b1 > b2)  # 输出: True
print(b1 == b2)  # 输出: False

3 多态

核心思想:不同类的对象对同一方法调用产生不同行为。通过继承 + 方法重写实现。
在 Python 里,只要对象长得像鸭子,就能当鸭子用(“鸭子类型”)。

class Animal:  # 定义动物基类
    def __init__(self, name):  # 构造函数:初始化动物实例
        self.name = name  # 设置实例属性 name(动物名字),将传入的name参数保存为实例属性
        # self:表示当前实例对象,所有子类都会继承这个构造函数

    def shout(self):  # -定义发声方法(抽象方法))
        pass  # 由子类具体实现  -空操作,表示没有具体实现


class Dog(Animal):  # 定义 Dog 类并继承 Animal
    def shout(self):  # def shout(self): 重写父类的 shout 方法,方法名与父类相同,实现不同功能
        print(f"{self.name}: 汪汪!")
        # 使用 f-string 格式化输出
        # self.name 继承自 Animal 类


class Bird(Animal):  # 定义 Bird 类(鸟),继承自 Animal
    def shout(self):  # 重写父类的 shout 方法
        print(f"{self.name}: 啾啾~")  # 实现鸟特有的叫声


# 多态实现
# 创建不同动物实例
dog = Dog("旺财")
bird = Bird("小红")

# 统一调用 shout 方法
dog.shout()  # 输出: 旺财: 汪汪!
bird.shout()  # 输出: 小红: 啾啾~

4 异常处理机制

AttributeError(属性错误)

尝试访问对象不存在的属性或方法

ValueError(值错误)

函数接收到类型正确但值不合适的参数

TypeError(类型错误)

操作或函数应用到不适当类型的对象

IndexError(索引错误)

访问序列(列表、元组、字符串)中不存在的索引

try,except,else,finally关键字组合不同异常处理方法

try:         # 可能发生异常代码

except:# 异常发生执行代码

else:       # 没有异常执行代码

finally:     # 不管是否捕获异常最后都执行代码

s1 = "scad"
try:
    print(s1[99])  # 试图访问字符串 s1 的第 100 个字符(下标 99)。
except IndexError:
    print("捕获到异常,下标越界啦")
else:
    print("没有异常")
finally:
    print("最终执行此代码")
print("hello world")
# 获取三角形边长并验证输入
try:  # 开始一个 try 块,用于捕获可能的异常
    a = float(input("请输入第一条边长: "))
    b = float(input("请输入第二条边长: "))
    c = float(input("请输入第三条边长: "))
except ValueError:  # 捕获可能发生的 ValueError 异常(当输入无法转换为数字时)
    print("错误:请输入有效数字")
    exit()  # 退出程序

# 验证边长有效性
if a <= 0 or b <= 0 or c <= 0:  # 检查任何边长是否小于或等于零
    print("错误:边长必须为正数")  # 如果边长不是正数,打印错误信息
    exit()  # 退出程序

# 检查三角形不等式定理(优化版)
sides = sorted([a, b, c])  # 创建一个包含三边的列表 [a, b, c]
# 使用 sorted() 函数对列表进行升序排序
# 将排序后的列表赋值给 sides 变量
# 排序后:sides[0] ≤ sides[1] ≤ sides[2]

if sides[0] + sides[1] <= sides[2]:  # 检查最小两边之和是否小于或等于最大边(三角形不等式)
    print("错误:不能构成三角形(两边之和需大于第三边)")
    exit()  # 退出程序

# 判断三角形类型
if a == b == c:
    print("等边三角形")
elif a == b or a == c or b == c:
    print("等腰三角形")
else:
    # 使用排序优化直角判断(仅需检查最大边)
    if abs(sides[0] ** 2 + sides[1] ** 2 - sides[2] ** 2) < 1e-6:  # 处理浮点精度
        print("直角三角形")
    else:
        print("普通三角形")

5 迭代器

迭代是python中访问集合中的元素的一种方式,迭代器迭代器是可迭代的对象,可以遍历所有值,可以记住遍历位置的对象。迭代器是一种对象,该对象包含值的可计数数字。

迭代器对象从集合的第一个元素开始访问,直到所有元素被访问完结束,迭代器只能往前不会后退

迭代器有两个基本方法:iter() next()

列表、元组、字典和集合都是可迭代的对象。它们是可迭代的容器,您可以从中获取迭代器(Iterator)。

list1 = [2.3, 3, 5.2, 6]  # 创建列表
l1 = iter(list1)  # 创建迭代器对象 iter(list1) 将列表转换为迭代器对象
print(next(l1))  # 获取第一个元素,迭代器位置:移动到下一个元素
print(next(l1))  # 获取第二个元素,迭代器位置:移动到下一个元素
for i in l1:  # 遍历剩余的元素,for 循环从当前迭代器位置继续
    print(i)
# 2.3
# 3
# 5.2
# 6

# 第一次迭代:i = 5.2 → 打印 5.2
# 第二次迭代:i = 6 → 打印 6
# 第三次迭代:迭代器耗尽,循环结束

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值