找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

456

积分

0

好友

56

主题
发表于 昨天 12:51 | 查看: 6| 回复: 0

Python 是一种支持多种编程范式的语言,其中面向对象编程 (OOP) 是其核心特性之一。面向对象编程以“对象”作为设计和组织软件的基本单元,通过封装数据和操作来模拟现实世界。在Python中,几乎所有元素都是对象,这使得 OOP 的应用非常直观且强大。

掌握面向对象编程的核心概念,对于构建结构清晰、易于维护的应用程序至关重要。

类 (Class)

类是创建对象的蓝图。它定义了一组属性和方法,这些属性和方法将被该类的所有实例共享。你可以将类理解为一个产品的设计图纸。

class MyClass:
    # 类变量
    class_variable = "I am shared by all instances"
    def __init__(self, instance_variable):
        # 实例变量
        self.instance_variable = instance_variable
    def method(self):
        print("This is a method of MyClass")

对象 (Object)

对象是类的具体实例。你可以通过像调用函数一样调用类来创建对象,并通过点运算符(.)来访问对象的属性和方法。

my_object = MyClass("I am unique to this instance")
print(my_object.instance_variable)  # 输出: I am unique to this instance
my_object.method()                  # 输出: This is a method of MyClass

继承 (Inheritance)

继承允许一个类(子类)获取另一个类(父类)的属性和方法。这是实现代码复用和建立层次化设计模式的重要手段。

class ChildClass(MyClass):
    def child_method(self):
        print("This is a method of ChildClass")

child_object = ChildClass(“Child instance variable”)
child_object.method()              # 输出: This is a method of MyClass
child_object.child_method()        # 输出: This is a method of ChildClass

封装 (Encapsulation)

封装是指将对象的内部状态和实现细节隐藏起来,只通过有限的接口与外部交互。Python 通过下划线约定来实现一定程度的封装。

  • 单下划线 _:通常表示属性或方法是内部使用的(受保护的),但并不严格阻止外部访问。
  • 双下划线 __:会触发名称重整,使其难以在类外部被直接访问(私有的),尽管并非绝对不可访问。

多态 (Polymorphism)

多态是指不同的子类对象可以对同一消息(方法调用)做出不同的响应。它允许我们使用统一的接口来操作不同类型的对象,提高了代码的通用性和灵活性。

class AnotherChildClass(MyClass):
    def method(self):  # 重写父类方法
        print(“This is a redefined method in AnotherChildClass”)

another_child = AnotherChildClass(“Another child instance variable”)
another_child.method()             # 输出: This is a redefined method in AnotherChildClass

理解多态特性,是编写优雅、可扩展程序的关键。

特殊方法 (Magic Methods)

Python 提供了一系列以双下划线开头和结尾的特殊方法,如 __init__, __str__, __repr__ 等。它们定义了对象在特定操作下的行为,例如初始化、字符串表示、运算符重载等。

class MyStrClass:
    def __init__(self, string):
        self.string = string
    def __str__(self):
        return f“My string is: {self.string}”
    def __repr__(self):
        return f“MyStrClass(‘{self.string}’)”

my_str = MyStrClass(“Hello, world!”)
print(str(my_str))      # 输出: My string is: Hello, world!
print(repr(my_str))     # 输出: MyStrClass(‘Hello, world!’)

代码示例

下面通过几个更贴近实际的例子,加深对上述概念的理解。

示例1:封装实践——手机类

# encoding = utf-8
“””
面向对象第一大特征:封装
基于Python3
“””
class CellPhone:
    “””
    手机类
    “””
    def __init__(self, cell_phone_number):
        self.cell_phone_number = cell_phone_number
        self.battery_percentage = 100
    def dial(self, cell_phone_number):
        print(“Calling %s” % cell_phone_number)
    def send_sms(self, cell_phone_number, message):
        print(“Sending %s to %s” % (message, cell_phone_number))
    def start_charge(self):
        print(“Charging…”)
    def stop_charge(self):
        print(“Charge Finished”)

if __name__ == ‘__main__’:
    P30 = CellPhone(“159xxxxxxxx”)
    P40 = CellPhone(“180xxxxxxxx”)
    print(“P30 手机号是 %s” % P30.cell_phone_number)
    print(“P30 手机还剩余电量 %d” % P30.battery_percentage)
    P40.battery_percentage = 50
    print(“P40 手机号是 %s” % P40.cell_phone_number)
    print(“P40 手机还剩余电量 %d” % P40.battery_percentage)
    P30.dial(P40.cell_phone_number)
    P40.send_sms(P30.cell_phone_number, “Give u feedback later”)

示例2:继承层次——多种手机类型

# encoding = utf-8
from OOP import CellPhone

class SymbianMobilePhone(CellPhone):
    “””
    塞班手机
    “””
    pass

class SmartMobilePhone(CellPhone):
    “””
    智能手机
    “””
    def __init__(self, cell_phone_number, os=“Android”):
        super().__init__(cell_phone_number)
        self.os = os
        self.app_list = list()
    def download_app(self, app_name):
        print(“正在下载应用 %s” % app_name)
    def delete_app(self, app_name):
        print(“正在删除应用 %s” % app_name)

class FullSmartMobilePhone(SmartMobilePhone):
    “””
    全面屏智能手机
    “””
    def __init__(self, cell_phone_number, screen_size, os=“Android”):
        super().__init__(cell_phone_number, os)
        self.screen_size = screen_size

class FolderScreenSmartMobilePhone(SmartMobilePhone):
    “””
    折叠屏智能手机
    “””
    def fold(self):
        print(“The CellPhone is folded”)
    def unfold(self):
        print(“The CellPhone is unfolded”)

示例3:多态与抽象——手机解锁方式演进

# encoding = utf-8
class IPhone:
    “””
    IPhone基类,具有一个解锁功能
    “””
    def unlock(self, pass_code, **kwargs):
        print(“解锁IPhone”)
        return True

class IPhone5S(IPhone):
    “””
    IPhone5S,unlock功能增加了指纹解锁
    “””
    def finger_unlock(self, fingerprint):
        return True
    def unlock(self, pass_code, **kwargs):
        fingerprint = kwargs.get(“fingerprint”, None)
        if self.finger_unlock(fingerprint):
            print(“指纹解锁成功”)
            return True
        else:
            return super().unlock(pass_code)

class IPhoneX(IPhone):
    “””
    IPhoneX, unlock功能增加刷脸解锁
    “””
    def face_unlock(self, face_id):
        return True
    def unlock(self, pass_code, **kwargs):
        face_id = kwargs.get(“face_id”, None)
        if self.face_unlock(face_id):
            print(“通过刷脸解锁成功”)
            return True
        else:
            super().unlock(pass_code)

示例4:使用抽象基类规范接口

from abc import ABCMeta, abstractmethod

class MobilePhone(metaclass=ABCMeta):
    @abstractmethod
    def unlock(self, credential):
        pass

class IPhone(MobilePhone):
    def unlock(self, credential):
        print(“IPhone解锁”)

class IPhone5S(MobilePhone):
    def unlock(self, credential):
        print(“5S解锁”)

class IPhoneX(MobilePhone):
    def unlock(self, credential):
        print(“IPhoneX解锁”)

def test_unlock(phone):
    if isinstance(phone, IPhone):
        phone.unlock(“……”)
    else:
        print(“传入的参数必须是MobilePhone类型”)
        return False

if __name__ == ‘__main__’:
    phone = IPhone()
    test_unlock(phone)

创建和使用类

使用类可以模拟现实世界中的各种事物。我们来编写一个表示小狗的简单类 Dog。这个类定义了大多数小狗共有的属性和行为:名字、年龄,以及蹲下和打滚的动作。

class Dog():
    “”“一次模拟小狗的简单尝试”“”
    def __init__(self, name, age):
        “”“初始化属性name和age”“”
        self.name = name
        self.age = age
    def sit(self):
        “”“模拟小狗被命令时蹲下”“”
        print(self.name.title() + “ is now sitting.”)
    def roll_over(self):
        “”“模拟小狗被命令时打滚”“”
        print(self.name.title() + “ rolled over!”)

__init__() 是一个特殊方法,在每次根据 Dog 类创建新实例时,Python 都会自动调用它。形参 self 必不可少且必须位于首位,它指向实例本身,让实例能够访问类中的属性和方法。在方法内部,我们使用 self.name = name 这样的语句将传入的值赋给实例的属性。通过实例访问的变量称为属性

Dog 类还定义了 sit()roll_over() 两个方法。由于它们不需要额外的信息,因此只有一个形参 self。根据这个类创建的实例都可以调用这两个方法。

根据类创建实例

我们可以根据 Dog 类创建表示特定小狗的实例。

class Dog():
    --snip--
my_dog = Dog(‘willie’, 6)
print(“My dog’s name is “ + my_dog.name.title() + “.”)
print(“My dog is “ + str(my_dog.age) + “ years old.”)

my_dog = Dog(‘willie’, 6) 这行代码让 Python 创建一条名为 ‘willie’、年龄为 6 的小狗。Python 使用我们提供的实参调用 __init__() 方法,并返回这个新创建的实例。

要访问实例的属性,使用句点表示法,如 my_dog.name。要调用实例的方法,同样使用句点表示法,如 my_dog.sit()

my_dog.sit()
my_dog.roll_over()

输出为:

Willie is now sitting.
Willie rolled over!

创建多个实例

你可以根据需要,从一个类创建任意数量的实例。

class Dog():
    --snip--
my_dog = Dog(‘willie’, 6)
your_dog = Dog(‘lucy’, 3)
print(“My dog’s name is “ + my_dog.name.title() + “.”)
print(“My dog is “ + str(my_dog.age) + “ years old.”)
my_dog.sit()
print(“\nYour dog’s name is “ + your_dog.name.title() + “.”)
print(“Your dog is “ + str(your_dog.age) + “ years old.”)
your_dog.sit()

每个实例都是独立的,即使它们具有相同的名字和年龄,Python 也会创建不同的实例。

使用类和实例

创建类后,大部分工作将围绕实例展开,包括修改实例的属性。修改属性值主要有三种方式。

给属性指定默认值

__init__() 方法中,可以直接为某些属性设置初始值,这样创建实例时就不必提供这些值。

class Car():
    def __init__(self, make, model, year):
        “”“初始化描述汽车的属性”“”
        self.make = make
        self.model = model
        self.year = year
        self.odometer_reading = 0  # 默认值
    def get_descriptive_name(self):
        long_name = str(self.year) + ‘ ‘ + self.make + ‘ ‘ + self.model
        return long_name.title()
    def read_odometer(self):
        “”“打印一条指出汽车里程的消息”“”
        print(“This car has “ + str(self.odometer_reading) + “ miles on it.”)

my_new_car = Car(‘audi’, ‘a4’, 2016)
print(my_new_car.get_descriptive_name())
my_new_car.read_odometer()

输出:

2016 Audi A4
This car has 0 miles on it.

修改属性的值

  1. 直接修改:通过实例直接访问并设置属性。

    my_new_car.odometer_reading = 23
    my_new_car.read_odometer()  # 输出: This car has 23 miles on it.
  2. 通过方法修改:定义一个方法来更新属性值,可以在方法中加入逻辑控制(如数据验证)。

    class Car():
        --snip--
        def update_odometer(self, mileage):
            “”“将里程表读数设置为指定的值”“”
            if mileage >= self.odometer_reading:  # 禁止回调里程
                self.odometer_reading = mileage
            else:
                print(“You can’t roll back an odometer!”)
    
    my_new_car.update_odometer(23)
    my_new_car.read_odometer()
  3. 通过方法递增:定义一个方法来增加属性值。

    class Car():
        --snip--
        def increment_odometer(self, miles):
            “”“将里程表读数增加指定的量”“”
            self.odometer_reading += miles
    
    my_used_car = Car(‘subaru’, ‘outback’, 2013)
    my_used_car.update_odometer(23500)
    my_used_car.increment_odometer(100)
    my_used_car.read_odometer()  # 输出: This car has 23600 miles on it.

继承

当你需要编写的类是另一个现有类的特殊版本时,使用继承可以事半功倍。原有的类称为父类(或基类、超类),新类称为子类(或派生类)。子类自动获得父类的所有属性和方法,同时可以定义自己特有的属性和方法。

子类的 __init__() 方法

创建子类时,通常需要先初始化父类的属性。

class Car():
    “”“一次模拟汽车的简单尝试”“”
    def __init__(self, make, model, year):
        self.make = make
        self.model = model
        self.year = year
        self.odometer_reading = 0
    def get_descriptive_name(self):
        long_name = str(self.year) + ‘ ‘ + self.make + ‘ ‘ + self.model
        return long_name.title()
    def read_odometer(self):
        print(“This car has “ + str(self.odometer_reading) + “ miles on it.”)
    def update_odometer(self, mileage):
        if mileage >= self.odometer_reading:
            self.odometer_reading = mileage
        else:
            print(“You can’t roll back an odometer!”)
    def increment_odometer(self, miles):
        self.odometer_reading += miles

class ElectricCar(Car):  # 指定父类名称
    “”“电动汽车的独特之处”“”
    def __init__(self, make, model, year):
        “”“初始化父类的属性”“”
        super().__init__(make, model, year)  # 调用父类的__init__

my_tesla = ElectricCar(‘tesla’, ‘model s’, 2016)
print(my_tesla.get_descriptive_name())  # 输出: 2016 Tesla Model S

super() 是一个特殊函数,它帮助 Python 找到父类并调用其方法,确保子类包含所有父类的属性。

给子类定义属性和方法

让子类区别于父类,需要添加其特有的属性和方法。

class ElectricCar(Car):
    def __init__(self, make, model, year):
        super().__init__(make, model, year)
        self.battery_size = 70  # 子类特有属性
    def describe_battery(self): # 子类特有方法
        “”“打印一条描述电瓶容量的消息”“”
        print(“This car has a “ + str(self.battery_size) + “-kWh battery.”)

my_tesla = ElectricCar(‘tesla’, ‘model s’, 2016)
my_tesla.describe_battery()  # 输出: This car has a 70-kWh battery.

重写父类的方法

如果父类的方法不适合子类,可以在子类中定义一个同名方法来将其重写

class ElectricCar(Car):
    --snip--
    def fill_gas_tank():  # 父类可能有这个方法,但电动车不需要
        “”“电动汽车没有油箱”“”
        print(“This car doesn’t need a gas tank!”)

将实例用作属性

随着类变得复杂,可以考虑将相关属性和方法提取出来,作为一个独立的类,然后将这个类的实例用作原类的属性。这有助于保持代码的清晰和组织性。

class Battery():
    “”“一次模拟电动汽车电瓶的简单尝试”“”
    def __init__(self, battery_size=70):
        “”“初始化电瓶的属性”“”
        self.battery_size = battery_size
    def describe_battery(self):
        print(“This car has a “ + str(self.battery_size) + “-kWh battery.”)
    def get_range(self):
        “”“打印一条消息,指出电瓶的续航里程”“”
        if self.battery_size == 70:
            range = 240
        elif self.battery_size == 85:
            range = 270
        message = “This car can go approximately “ + str(range)
        message += “ miles on a full charge.”
        print(message)

class ElectricCar(Car):
    “”“电动汽车的独特之处”“”
    def __init__(self, make, model, year):
        super().__init__(make, model, year)
        self.battery = Battery()  # 将Battery实例作为属性

my_tesla = ElectricCar(‘tesla’, ‘model s’, 2016)
my_tesla.battery.describe_battery()
my_tesla.battery.get_range()

输出:

This car has a 70-kWh battery.
This car can go approximately 240 miles on a full charge.

导入类

为了让代码更整洁、易于维护,可以将类存储在独立的模块(.py 文件)中,然后在主程序中导入所需模块。

1. 导入单个类
假设我们将 Car 类保存在 car.py 文件中。

# car.py
“”“一个可用于表示汽车的类”“”
class Car():
    --snip--  # Car类的定义

在主程序中:

from car import Car
my_new_car = Car(‘audi’, ‘a4’, 2016)
print(my_new_car.get_descriptive_name())

2. 从一个模块导入多个类
如果 car.py 文件中还定义了 BatteryElectricCar 类。

from car import Car, ElectricCar
my_beetle = Car(‘volkswagen’, ‘beetle’, 2016)
my_tesla = ElectricCar(‘tesla’, ‘roadster’, 2016)

3. 导入整个模块

import car
my_beetle = car.Car(‘volkswagen’, ‘beetle’, 2016)
my_tesla = car.ElectricCar(‘tesla’, ‘roadster’, 2016)

4. 导入模块中的所有类(不推荐)
from module_name import * 这种方式不明确,容易引发名称冲突,应尽量避免。

5. 在一个模块中导入另一个模块
当类分散在不同模块且存在依赖时,可以在模块中导入其他模块的类。例如,electric_car.py 需要用到 car.py 中的 Car 类。

# electric_car.py
“”“一组用于表示电动汽车的类”“”
from car import Car  # 导入需要的类

class Battery():
    --snip--
class ElectricCar(Car):
    --snip--

Python标准库

Python 标准库包含大量实用的模块和类。例如,collections 模块中的 OrderedDict 类,它保持了键值对的添加顺序,而普通字典 dict 不记录顺序。

from collections import OrderedDict
favorite_languages = OrderedDict()  # 创建一个空的有序字典
favorite_languages[‘jen’] = ‘python’
favorite_languages[‘sarah’] = ‘c’
favorite_languages[‘edward’] = ‘ruby’
favorite_languages[‘phil’] = ‘python’

for name, language in favorite_languages.items():
    print(name.title() + “‘s favorite language is “ + language.title() + “.”)

输出将严格按照添加顺序(Jen, Sarah, Edward, Phil)进行。

编码规范

遵循良好的编码规范能使你的代码更专业、更易读。

  • 类名:采用驼峰命名法,即每个单词的首字母大写,不含下划线(如 ElectricCar)。
  • 实例名和模块名:采用小写字母加下划线的格式(如 my_tesla, electric_car.py)。
  • 文档字符串:每个类定义后都应紧跟一个文档字符串,简要描述类的功能。模块开头也应有一个模块级的文档字符串。
  • 空行使用:在类中,使用一个空行分隔方法;在模块中,使用两个空行分隔不同的类。
  • 导入顺序:先导入标准库模块,空一行,再导入自己编写的模块。
  • 代码组织:开始时可以让代码简单,一切运行正确后,再考虑将类拆分到独立的模块中。

掌握 Python 面向对象编程是成为高级开发者的重要一步。通过在 云栈社区 与其他开发者交流实践,你可以更快地将这些核心概念转化为解决实际问题的能力。




上一篇:ETF折溢价套利策略解析:无风险套利的原理、操作与量化门槛
下一篇:汇编语言入门:从寄存器、堆栈到指令执行揭秘计算机底层机制
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-1-18 13:10 , Processed in 0.227231 second(s), 40 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表