首页 > 编程语言 >带你理解Python面向对象

带你理解Python面向对象

时间:2024-11-13 21:44:45浏览次数:3  
标签:__ name Python self 面向对象 理解 print def 属性

一、面向对象编程

1.1 面向过程与面向对象

面向过程:更加注重通过函数来组织代码,适合任务明确、结构简单的程序。

面向对象:则注重通过对象和类来组织代码,适合复杂且需要长期维护和扩展的大型项目。

面向过程和面向对象都是一种编程方式,只不过再设计上有区别。

三大基本特性

封装:将数据和操作数据的代码组合在一起,并限制对外部的访问。

继承:一个类可以继承另一个类的属性和方法,避免重复代码。

多态:同一个方法可以作用于不同类型的对象,实现灵活的功能扩展。

1.2 类 和 对象

1.2.1 类的定义

类是用来创建对象的模板。类定义了对象的属性和方法。类本身并不代表一个具体的实体,而是对一类事物的抽象描述。

1.2.2 实例化对象

实例化对象是通过类创建对象的过程。每个通过类创建的对象都被称为该类的实例。实例是类的具体表现,每个实例可以有不同的属性值。

举例说明:

我们可以将学生看作一个类,在这个类中定义了学生的属性和行为,比如学号、姓名等属性,以及写作业、玩耍等行为。

那么,当我们要描述具体一个学生时,就需要创建一个该类的对象,并根据需要设置其相应的属性值或对其进行行为操作。

另外,我们可以根据同一个类创建多个不同的对象,每个对象的属性值和行为可能都不同。例如大学生肯定不止一个学生。

class Stu(object):
    id = '1001'  # 类属性
    name = '张三'  # 类属性

    def __init__(self):
        pass  # 构造函数,这里没有任何操作
    
    def fun1(self):
        pass  # 实例方法,这里没有任何操作

# 创建两个对象 s1 和 s2
s1 = Stu()
s2 = Stu()

# 打印对象的 name 属性
print(s1.name)  # 输出:张三
print(s2.name)  # 输出:张三

1.2.3 访问属性/方法

# 访问属性
对象名.属性
# 访问方法
对象名.方法名()

1.2.4 对象与类的关系

对象拥有类的所有属性和方法

对象的属性和方法可以单独添加、删除、修改

对象与对象之间的属性和方法不可共享

对象不能独自创建,必须依托于类,类可以实例化N个对象

举例说明1:

class Stu(object):
    id = '1001'  # 类属性
    name = '张三'  # 类属性

    def fun1(self):
        pass  # 方法,暂时没有实现

# 实例化对象
s1 = Stu()
s2 = Stu()

# 对象的属性可以单独修改、添加、删除
s1.name = '李四'  # 修改实例属性 'name'
s1.age = 18  # 添加实例属性 'age'

del s1.age  # 删除实例属性 'age'

print(s1.name)  # 输出:李四
print(s2.name)  # 输出:张三

类定义了共享的属性和行为,而对象则可以根据需要修改自己的属性。每个对象都有自己独立的实例属性,但它们共享类属性,除非这些类属性被对象单独修改。

举例说明2:

from types import MethodType

class Stu(object):
    id = '1001'
    name = '张三'

    def fun1(self):
        print(f"{self.name}会吃饭")

    def fun2(self):
        print(f"{self.name}会学习")

# 实例化对象
s1 = Stu()
s2 = Stu()

# 修改实例的属性
s1.name = '刘德华'
s2.name = '蔡徐坤'

# 调用类中定义的方法
s1.fun1()  # 输出:刘德华会吃饭
s2.fun1()  # 输出:蔡徐坤会吃饭

# 定义新的方法
def sing(self):
    print(f"{self.name}会唱歌")

def dance(self):
    print(f"{self.name}会跳舞")

# 使用 MethodType 动态绑定方法到对象
s1.sing = MethodType(sing, s1)
s2.dance = MethodType(dance, s2)

# 调用动态绑定的方法
s1.sing()  # 输出:刘德华会唱歌
s2.dance()  # 输出:蔡徐坤会跳舞

类提供了共享的行为和属性,而对象则可以继承这些行为,并且可以在运行时对自身的属性和方法进行扩展或修改。

二、魔方方法——构造函数 与 析构函数

1.1 __init__构造函数

构造函数是用来初始化对象的特殊方法。在 Python 中,构造函数的名称是 __init__,它会在创建对象时被自动调用,用来初始化对象的属性。

__init__ 方法在每次创建新对象时都会被调用。
self 代表当前对象本身,可以用它来初始化实例属性

class Dog:
    # 构造函数
    def __init__(self, name, age):
        self.name = name  # 初始化实例属性 name
        self.age = age    # 初始化实例属性 age

    def introduce(self):
        print(f"我的名字是 {self.name}, 我 {self.age} 岁。")

# 创建对象时,构造函数会被自动调用
dog1 = Dog("A", 3)
dog2 = Dog("B", 5)

dog1.introduce()  # 输出:我的名字是 A, 我 3 岁。
dog2.introduce()  # 输出:我的名字是 B, 我 5 岁。

1.2 __del__ 析构函数

删除对象时执行一些操作,自动执行。

class Dog:
    # 构造函数
    def __init__(self, name, age):
        self.name = name
        self.age = age

    # 析构函数
    def __del__(self):
        print(f"狗 {self.name} 已销毁")

# 创建对象
dog1 = Dog("A", 3)

# 删除对象
del dog1  # 调用析构函数,输出:狗 A 已销毁

1.3  __str__ 打印方法:输出执行信息,自动执行。

class Dog:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    # 自定义 __str__ 方法
    def __str__(self):
        return f"这是一只名叫 {self.name} 的狗,它 {self.age} 岁。"

# 创建一个 Dog 对象
dog = Dog("Buddy", 3)

# 使用 print() 打印对象,会自动调用 __str__ 方法
print(dog)  # 输出:这是一只名叫 Buddy 的狗,它 3 岁。

三、类属性/方法 与 实例对象属性/方法 与 静态方法

 1.1 类属性和实例属性

1.1.1 类属性

类属性是属于整个类的属性,而不是某个具体的实例。它被类的所有实例共享。
类属性通过类名访问,也可以通过实例访问,但修改类属性时会影响所有实例。
如果你改变了类属性的值,它会影响到所有实例。

 1.1.2 实例属性

实例属性是绑定到每个实例的属性,每个实例都有自己的属性值。
每次创建一个实例时,都会调用 __init__ 方法来初始化实例属性。
实例属性只能通过实例来访问和修改,不能通过类来访问。

举例说明:

class Car(object):
    # 类属性
    wheels = 4

    def __init__(self, name, color):
        # 实例属性
        self.name = name
        self.color = color

# 创建两个实例
car1 = Car("奥迪", "黑色")
car2 = Car("宝马", "白色")

# 访问类属性
print(Car.wheels)  # 输出: 4

# 访问实例属性
print(car1.name)   # 输出: 奥迪
print(car2.color)  # 输出: 白色

# 修改类属性
Car.wheels = 6
print(car1.wheels)  # 输出: 6
print(car2.wheels)  # 输出: 6

1.2 类方法和实例方法

1.2.1 类方法

使用@classmethod进行修饰,第一个参数传入cls参数,表示类本身,用于访问类本身的属性

类方法内,只能调用类属性和类方法

可以通过类名调用、对象名调用

class Car(object):
    wheels = 4  # 类属性

    def __init__(self, name, color):
        self.name = name
        self.color = color

    # 类方法
    @classmethod
    def change_wheels(cls, num):
        cls.wheels = num
        print(f"所有车的轮子数都改为 {cls.wheels}")

# 调用类方法
Car.change_wheels(6)  # 输出: 所有车的轮子数都改为 6
Car.change_wheels(6)  # 输出: 所有车的轮子数都改为 6

1.2.2 实例方法

第一个参数传入self参数,没有实例化前不能调用;实例化后,也多用对象调用而不是类调用

class Car(object):
    def __init__(self, name, color):
        self.name = name
        self.color = color

    # 实例方法
    def drive(self):
        print(f"{self.name}正在开动,颜色是{self.color}")

# 创建 Car 类的实例
car = Car("奥迪", "黑色")
Car.drive(car)  # 输出: 奥迪正在开动,颜色是黑色
car.drive()  # 输出: 奥迪正在开动,颜色是黑色

1.3 静态方法

静态方法一般实现与类和对象无关联的操作,例如:游戏说明书等

使用 @staticmethod 装饰器来定义静态方法。

class Student(object):
    """
    定义了一个学生类
    """
    grade = 'py24101'

    def __init__(self, name, age):
        self.name = name
        self.age = age

    @staticmethod
    def sta_fun(x):
        print(f"{x}静态方法一般实现与类和对象无关联的操作,例如:游戏说明书等")

s1 = Student('张三', 18)

# 如何调用静态方法
Student.sta_fun(1)
s1.sta_fun(1)

四、类的封装【私有属性与方法】

封装是类的三大特性之一。

封装指的是隐藏对象中一些不希望让外部所访问的属性或方法。

python中封装其实是通过设置访问权限来体现的,私有属性和私有方法是控制访问权限的组成部分。

1.1 私有属性和私有方法

私有属性和方法是以双下划线(__)开头的,它们只能在类的内部访问,外部无法直接访问或修改。这种封装机制确保了类的内部实现细节不会被外部直接修改,增强了数据的安全性。

class Bank(object):
    """
    定义了一个银行卡类
    属性:
        name: 客户的名字
        __pwd: 客户的密码(私有属性,不希望外部直接访问)
    """
    
    def __init__(self, name, pwd):
        """
        构造函数,初始化 Bank 对象的属性
        
        参数:
            name (str): 客户的名字
            pwd (str): 客户的密码
        """
        self.name = name          # 客户的名字,是一个公有属性
        self.__pwd = pwd          # 客户的密码,是一个私有属性(前缀加双下划线)

    def __info(self):
        """
        一个私有方法,用于显示银行卡信息,包括名字和密码
        注意:这个方法是私有的,外部不能直接调用
        """
        print(f"名字{self.name}, 密码{self.__pwd}")
    
    def get_info(self):
        """
        公有方法,提供对外接口来获取银行卡信息
        通过此方法间接调用 __info 方法
        """
        self.__info()  # 调用私有方法 __info 来显示信息

# 下面是创建 Bank 类对象并使用方法的示例:

b1 = Bank('李四', '123456')  # 创建 Bank 类的实例,传入名字和密码
# Bank.__info()  # 会报错,因为 __info 是私有方法,不能在类外直接访问
# b1.__info()    # 会报错,因为 __info 是私有方法,不能在实例外直接访问

# 通过公有方法 get_info 来间接访问和显示信息
b1.get_info()  # 输出: 名字李四, 密码123456

1.2 属性装饰器

属性装饰器是实现把方法转为属性的装饰器。

作用:

把方法转为属性,便于操作属性

实现对属性的更改(验证)、查看、删除

举例说明:

class Student(object):

    def __init__(self, name):
        self.__name = name  # 私有属性,存储学生的名字

    @property
    def name(self):
        """
        getter 方法,获取学生的名字
        通过 @property 装饰器将这个方法变为一个属性,可以像访问属性一样获取名字
        """
        return self.__name

    @name.setter
    def name(self, new_name):
        """
        setter 方法,设置学生的名字
        通过 @name.setter 装饰器提供修改名字的功能
        """
        if not isinstance(new_name, str):  # 判断传入的名字是否是字符串
            print('名字必须是一个字符串')  # 如果不是字符串,打印错误提示
        else:
            self.__name = new_name  # 如果是字符串,更新学生名字

    @name.deleter
    def name(self):
        """
        deleter 方法,删除学生的名字
        通过 @name.deleter 装饰器提供删除名字的功能
        """
        print("已删除名字")  # 删除名字时打印提示
        del self.__name  # 删除 __name 属性

# 实例化一个 Student 对象
s1 = Student('张三')

# 打印学生的名字
print(s1.name)  # 输出: 张三

# 尝试将名字设置为一个非字符串类型(数字)
s1.name = 111  # 输出: 名字必须是一个字符串

# 正常修改名字为 '李四'
s1.name = '李四'
print(s1.name)  # 输出: 李四

# 删除名字
del s1.name  # 输出: 已删除名字

 五、类的继承

面向对象的编程带来的主要好处之一就是代码的重用,实现这种重用的方法之一就是通过继承机制。

1.1 类的继承的基本概念

父类(基类):被继承的类,包含一些共有的属性和方法。
子类(派生类、超类):继承父类的类,可以复用父类的属性和方法,并可以增加或修改一些新的属性和方法。

举例说明1:

class Parent(object):
    """
    定义父类
    """
    par_attr = 100

    def __init__(self):
        print("初始化父类")

    def par_fun1(self):
        print("父类方法1")

    def par_fun2(self):
        print("父类方法2")

class Child(Parent):
    """
    定义子类
    """
    child_attr = 666
    def __init__(self):
        print("初始化子类")

    def child_fun1(self):
        print("子类方法1")

# 创建一个 Child 类的实例 c1
c1 = Child()  # 输出:初始化子类
              # 输出:初始化父类 (自动调用父类的 __init__ 方法)

# 访问并打印子类的属性 child_attr
print(c1.child_attr)  # 输出:666

# 调用并执行子类的方法 child_fun1
c1.child_fun1()  # 输出:子类方法1

# 访问并打印父类的属性 par_attr
print(c1.par_attr)  # 输出:100

# 调用并执行父类的方法 par_fun1
c1.par_fun1()  # 输出:父类方法1

# 调用并执行父类的方法 par_fun2
c1.par_fun2()  # 输出:父类方法2

 1.2 多继承语法

如果在继承的元组()里面有一个以上的类,就称之为多继承。

class A:
    pass

class B:
    pass

class C:
    pass

class D(A, B, C):
    pass

d1 = D()
print(D.mro())
# python中提供了一个函数mro()用于查看继承的顺序。

1.3 继承重写父类方法

如果你的父类方法不能满足你得要求,你可以在子类中重写父类的方法。

# 定义父类 Animal
class Animal:
    def speak(self):
        print("Animal makes a sound")  # 父类方法,所有动物都会发出这种声音

# 定义子类 Dog 继承 Animal
class Dog(Animal):
    def speak(self):
        print("狗 汪汪")  # 重写父类方法,狗发出 "汪汪" 声音

# 定义子类 Cat 继承 Animal
class Cat(Animal):
    def speak(self):
        print("猫 喵喵")  # 重写父类方法,猫发出 "喵喵" 声音

# 创建 Dog 和 Cat 类的实例
dog = Dog()
cat = Cat()

# 调用它们的 speak 方法
dog.speak()  # 输出: Dog barks
cat.speak()  # 输出: Cat meows

 1.4 python继承特点

在子类中如果需要父类的构造方法,需要显式调用父类的构造方法,或者不重写父类的构造方法。__init__()

在子类中调用父类的方法,需要显式调用,且第一个参数self不能省略。

六、类的多态

python中的多态也可以通过方法重写进行。

同一个方法,不同对象显式的结果不同。

# 定义父类 Animal
class Animal:
    def speak(self):
        print("Animal makes a sound")  # 父类方法,所有动物都会发出这种声音

# 定义子类 Dog 继承 Animal
class Dog(Animal):
    def speak(self):
        print("狗 汪汪")  # 重写父类方法,狗发出 "汪汪" 声音

# 定义子类 Cat 继承 Animal
class Cat(Animal):
    def speak(self):
        print("猫 喵喵")  # 重写父类方法,猫发出 "喵喵" 声音

# 创建 Dog 和 Cat 类的实例
dog = Dog()
cat = Cat()

# 调用它们的 speak 方法
dog.speak()  # 输出: Dog barks
cat.speak()  # 输出: Cat meows

 结尾:

面向对象编程是现代编程的核心思想之一,无论是小型项目还是大型系统,理解并应用 OOP 都是开发者的必备技能。希望本文能够帮助你加深对 OOP 的理解,提升你的编程水平。

如果你对 Python 面向对象编程有任何问题或想法,欢迎在评论区交流讨论。愿你在编程的道路上越走越远,继续探索更多的技术与工具!

标签:__,name,Python,self,面向对象,理解,print,def,属性
From: https://blog.csdn.net/qq_65009672/article/details/143749704

相关文章

  • 深入理解Java的类加载与卸载机制
    在Java中,类加载和卸载是Java虚拟机(JVM)管理类生命周期的重要环节。类加载是Java动态链接机制的核心,通过它,JVM可以在运行时加载类文件。而类的卸载则是为了节省内存,将无用的类从JVM中移除。要理解类的加载和卸载,不仅有助于解决类加载异常、内存泄漏等问题,也能帮助我们更好地优......
  • 【Python教程】python如何把数据导出生成excel
    博主介绍:✌全网粉丝21W+,CSDN博客专家、Java领域优质创作者,掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌技术范围:SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物联网、机器学习等设计与开发。感兴趣的可以先......
  • Python——专栏:跳动的心跳(橘粉爱心)——完整代码
    运行展示完整代码importrandomfrommathimportsin,cos,pi,logfromtkinterimport*CANVAS_WIDTH=980#画布的宽CANVAS_HEIGHT=720#画布的高CANVAS_CENTER_X=CANVAS_WIDTH/2#画布中心的X轴坐标CANVAS_CENTER_Y=CANVAS_HEIGHT/2#画布中......
  • Python 面向对象编程
    一、面向对象编程1.1面向过程与面向对象在理解面向对象编程(OOP)之前,我们先要了解 面向过程(POP) 和 面向对象(OOP) 的区别。1.1.1面向过程(POP)-面向过程的编程思想将一个功能分解为一个一个小的步骤,我们通过完成一个一个的小的步骤来完成一个程序-这种编程方式,符合我们......
  • 【进阶系列】带你看懂python的面向对象编程#类 #对象 #继承 #封装 #多态
    进阶系列一、面向对象编程1.1面向过程与面向对象1.1.1面向过程pop:1.1.2面向对象oop:1.2类、对象1.2.1类的定义与实例化对象1.2.2访问属性/方法1.2.3对象与类的关系1.2.5⭐魔方——构造函数与析构函数1.2.6⭐类属性/方法与实例对象属性/方法与静态方法小练习1......
  • [20241112]无法理解sqlplus的输出.txt
    [20241112]无法理解sqlplus的输出.txt--//昨天遇到的问题,执行10tox.sql脚本出现一些状况。分析认为oracle把8d当作数字。--//但是还是遇到我无法理解的情况:1.环境:SCOTT@book>@ver1PORT_STRING                   VERSION       BANNER-------------......
  • python用selenium打开浏览器后浏览器关闭---解决办法
    脚本成功打开浏览器后,代码执行完毕浏览器又关闭了,解决办法:1、检查代码,代码中没有写driver.quit()或driver.close()方法,也没有其它错误提示;2、检查版本号,浏览器版本号,驱动版本号,确认版本号没有问题;3、加代码:fromseleniumimportwebdriveroptions=webdriver.ChromeOptions()......
  • Python语法:循环语句,掌握程序运行的节奏
    引言在当今数字化飞速发展的时代,编程已经成为一项不可或缺的技能,而Python作为一门简洁、高效且应用广泛的编程语言,备受开发者青睐。循环语句是Python编程中的基础结构之一,它在数据处理、算法实现、自动化任务等众多场景中都发挥着至关重要的作用。无论是专业的软件开发人员......
  • more Layer Architecture in Python and postgreSQL17.0
    postgreSQLscript:createtableSchool--創建表(SchoolIdchar(5)NOTNULLPRIMARYKEY,SchoolNamevarchar(500)NOTNULLDEFAULT'',SchoolTelNovarchar(8)NULLDEFAULT'');model:#encoding:utf-8#版权所有20......
  • canny 算法 python实现, 双边滤波--自适应阈值改进--形态学操作
    #-*-coding:utf-8-*-importnumpyasnpimportcv2importosimportcsv#高斯滤波defsmooth(image,sigma=1.4,length=5):#Computegaussianfilterk=length//2gaussian=np.zeros([length,length])foriinrange(length):for......