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

Python入门3:类与面对对象

目录

一、类的概念

二、类的定义和使用

2.1  类的定义

2.2  实例化对象

三、类的属性和方法

3.1 属性

属性的类型:

补充--私有属性

属性的操作:

3.2 方法

方法的类型:

补充--私有方法

方法的操作

四、面对过程和面对对象

面对过程

面对对象编程的三大特性:封装、继承、多态

 ★★继承 

 ★封装

多态


学习路线

Python基础篇1:表达式(常用数据类型及其函数介绍)_python函数和变量常用命名-CSDN博客

Python基础篇2:语句结构(选择、循环结构)-CSDN博客

Python入门1:函数-CSDN博客

Python入门2:模块和包-CSDN博客

一、类的概念

Python是一种面向对象的编程语言,面对对象中最核心的就是类(class)。类是一种具有相同属性和方法的对象的抽象。类可以包含多个属性和方法,这些属性和方法定义了对象的状态和行为,一旦定义了类,就可以通过创建其实例来访问其属性和方法,这种根据类来创建对象的过程称为实例化。

举个例子:鸟类,鸟类共有的属性如一对翅膀,双爪。共有的行为如飞翔,进食。这样当我们创建一个鸟类的实例对象时,就自动拥有这些属性和行为。

二、类的定义和使用

2.1  类的定义

在Python中,定义一个类使用关键字class,然后在类中定义属性(数据成员)和方法(成员函数)。类的属性可以是变量,类的方法可以是函数。通过实例化一个类,可以创建对象,并调用对象的方法和访问对象的属性。类支持封装、继承和多态等面向对象编程的核心概念,有助于提高代码的复用性和可维护性。

语法:

class 类名:

属性 变量

方法 函数

2.2  实例化对象

在完成类的定义后,实际上并不会立即创建一个实例。这就像是一份汽车蓝图。蓝图可以展示汽车的外观,但本身并不是一辆汽车。你无法直接驾驶蓝图,它只能用来指导真正汽车的建造,而且可以用它来制造多个汽车实例。那么,如何创建类的实例呢?

类的实例化:实例化对象是通过类(Class)创建具体实例(Instance)的过程。类是一个抽象的模板,而实例是根据这个模板创建的具体对象创建类的实例时,需要使用类名来调用。

需要注意的是:class语句本身并不创建该类的任何实例。所以在类定义完成以后,需要我们进行创建类的实例,即实例化该类的对象。这一点跟Java中的对象或者C++的对象很像,因为都是面向对象的语言。

# 定义一个简单的类
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def greet(self):
        print(f"Hello, my name is {self.name} and I am {self.age} years old.")

# 创建一个实例化对象
person1 = Person("Alice", 30)

# 访问实例化对象的属性和方法
print(person1.name)
print(person1.age)
person1.greet()

三、类的属性和方法

3.1 属性

类中的所有变量称为属性。

属性的类型:
  • 类属性:在类中,为全局变量,类和实例都可以访问。类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用
  • 实例属性:局部变量,定义在实例方法里的,绑定实例对象的,只有实例才能直接访问。实例变量就是一个用 self 修饰的变量。【实例属性是属于类的实例对象的变量,用于存储每个实例特有的数据。在类的内部,实例属性通常通过 self.属性名 来访问和修改;在类的外部,通过 实例对象名.属性名 来访问和修改。实例属性一般在 __init__ 方法或者类的其他方法中通过 self.属性名 = 值 的形式来定义和赋值】

要获取对应的属性,可以直接使用点.操作符

class Dog:
    # 类属性(所有实例共享)
    species = "Canis familiaris"

    def __init__(self, name, age):
        # 实例属性(每个实例独立)
        self.name = name
        self.age = age

dog1=Dog('小黄',3)
print(dog1.name) #访问实例属性 输出 小黄
print(dog1.species) #访问类属性 输出 Canis familiaris
print(Dog.species) #访问类属性,输出 Canis familiaris
补充--私有属性

私有属性:__private_attrs  在属性名前+两个下划线作为开头,声明该属性为私有,不能在类的外部被使用或直接访问,只能在类的内部进行访问和修改。在类内部的方法中使用时需要 self.__private_attrs,并配置相应getter和setter方法进行访问和修改。

类似其他语言的private,起到如下作用

  • 控制访问:通过将属性设为私有,可以限制对其的直接访问,并通过getter和setter方法控制外部如何访问或修改数据。
  • 提高安全性:防止类的外部代码意外修改或依赖于内部实现。
  • 增强灵活性:私有属性可以随时改变其实现细节,而无需修改外部代码,从而提高代码的灵活性和可维护性。

私有属性是指以双下划线__开头的属性,它在类的外部是不可访问的,只能在类的内部进行访问和修改。下面是一个关于私有属性的Python示例:

  • 隐藏实现细节:某些属性涉及类的内部实现,外部不需要也不应该直接访问它们。例如,某个复杂算法的中间结果。
  • 控制属性修改:通过私有属性,可以确保在修改属性时执行特定的逻辑,如数据校验或格式化处理。
  • 防止冲突:在继承层次较深的类中,使用私有属性可以避免子类不经意地覆盖父类的属性。
class Person:
    def __init__(self, name, age):
        self.__name = name   # 定义私有属性__name
        self.__age = age     # 定义私有属性__age

    def get_name(self):      # 获取私有属性的值
        return self.__name

    def get_age(self):
        return self.__age

    def set_name(self, name):# 设置私有属性的值
        self.__name = name

    def set_age(self, age):
        self.__age = age

# 创建一个Person对象
person = Person("Alice", 30)

# 下面两行代码将会报错,因为__name是私有属性,无法直接访问
#print(person.__name)
#person.__name = "Bob"

# 可以通过类的方法来访问和修改私有属性
print(person.get_name())  # 输出:Alice
print(person.get_age())   # 输出:30

person.set_name("Bob")
person.set_age(25)

print(person.get_name())  # 输出:Bob
print(person.get_age())   # 输出:25
属性的操作:
  • 添加属性

添加类属性,添加的属性是共享属性,类和实例都能访问

  1. 在类的定义中直接添加类属性
  2. 使用类方法来添加类属性
  3. 在类之外直接给类对象添加属性
  4. 使用setattr()函数来添加类属性

添加实例属性,添加的属性是私有属性,只有所添加的实例能访问

  1. 在初始化方法中添加:可以在类的__init__方法中通过self关键字来添加实例属性。
  2. 直接赋值:在创建对象之后,也可以直接通过对象名来添加实例属性
  3. 使用setattr函数:可以使用内置函数setattr为对象动态添加属性
  • 修改属性

修改类属性,对实例和类都有影响

  1. 直接通过类名访问并赋值:可以直接通过类名访问类属性,并对其进行赋值修改操作
  2. 使用setattr()函数:setattr()函数可以动态地为对象设置属性的值,包括类属性
  3. 使用__dict__属性:每个类都有一个__dict__属性,它是一个字典,包含了类的命名空间中的所有属性。可以直接通过修改这个字典来修改类属性的值。

修改实例属性值,只影响所修改的实例

  1. 直接通过实例对象修改属性:可以通过点号(.)来直接访问和修改实例对象的属性
  2. 使用setattr()函数:setattr()函数可以动态地为对象设置属性的值,包括实例属性
  3. 使用__setattr__()方法:可以在类中定义__setattr__()方法来自定义属性的设置行为。当尝试设置实例属性时会自动调用__setattr__()方法。例如:

    class Person:
        def __init__(self, name):
            self.name = name
    
        def __setattr__(self, attr, value):
            if attr == "name":
                self.__dict__[attr] = value.upper()
            else:
                self.__dict__[attr] = value
    
    person = Person("Alice")
    person.name = "Bob"
    print(person.name)  # 输出 "BOB"
  4. 直接访问实例的__dict__属性:每个实例对象都有一个__dict__属性,其中存储了实例的属性和对应的值。可以直接修改__dict__来修改实例的属性。
  • 删除属性

删除类属性  对实例和类都有影响

  1. 使用 del 关键字:可以直接使用 del 关键字来删除类属性
  2. 使用 delattr() 函数:可以使用内置函数 delattr() 来删除类属性
  3. 使用 del 关键字在类内部删除属性:可以在类的方法内部使用del 关键字来删除类属性

删除实例属性 只影响所删除的实例

  1. 使用 del 关键字:可以直接使用 del 关键字来删除实例属性
  2. 使用 delattr() 函数:可以使用内置函数 delattr() 来删除实例属性
  3. 赋予None值:可以将实例属性赋值为None来删除属性

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

person = Person("Alice", 25)
print(person.name)  # 输出 "Alice"

person.name = None
print(person.name)  # 输出 None,表示name属性已被删除

3.2 方法

类中的所有函数通常称为方法。

在类的内部,使用 def 关键字来定义一个方法,与一般函数定义不同,类方法必须包含参数 self,且为第一个参数,self 代表的是类的实例。

self 的名字并不是规定死的,也可以使用 this,但是最好还是按照约定使用 self。

要使用对应的方法,可以直接使用点.操作符

  • 实例方法必须通过实例调用

  • 类方法可通过类或实例调用

  • 静态方法可通过类或实例调用

方法的类型:
  • 类方法:

特点:类方法可以使用类属性,不能使用实例属性;类和实例都可以访问类方法

定义方式:在方法的上面添加@classmethod装饰器,方法的参数(cls),这里的cls就是代表类

class Person:
    national='中国' 
    @classmethod
    def study(cls): #类方法
        print('正在学习')
  • 构造方法:

特点:构造方法可以使用类属性和实例属性,它是一个特殊的方法,用于在实例化类的对象时初始化对象的属性。

语法:def __init__(self,参数1,参数2...)

作用:在Python中,构造方法是一个特殊的方法,用于在实例化一个类的对象时初始化对象的属性。构造方法在类的定义中使用__init__()方法来实现,构造方法通常用于为类的实例设置初始值。该方法在实例化对象时会自动调用,类不可以直接调用

一般用来定义实例的属性或者需要提前准备好的数据

class Person:
    national='中国'
    def __init__(self, name, age): #构造方法
        self.name = name   
        self.age = age
        print("构造方法")

p1=Person('zhangsan',16)
  • 实例方法

特点:实例方法可以使用类属性和实例属性。它是普通的方法,参数必须有 self,定义格式为 def 函数名 (self, [参数]),需要先实例化对象才能调用,类不能直接访问实例方法。

class Person:
    national='中国' 
    def graduate(self):   #实例方法
        print(f'{self.name}已经毕业了')
  • 静态方法

特点:它可以使用类属性,但不能使用实例属性。类和实例都可以访问静态方法

定义方式:在普通方法上添加@staticmethod装饰器,没有参数。

class Person:
    national='中国' 
    @staticmethod
    def operation():    #静态方法
        print('静态方法')
补充--私有方法

私有方法:__private_method  在方法名前+两个下划线开头,声明该方法为私有方法,只能在类的内部调用 ,不能在类的外部调用。在类的内部使用时,通过 self.__private_method 来调用。

目的是为了隐藏类的内部实现细节,只供类本身或者其子类使用

私有属性的作用和应用场景包括:

  1. 封装数据:私有属性可以将对象的数据隐藏起来,只允许通过类的方法来访问和修改,从而实现数据的封装和保护。
  2. 防止误操作:私有属性可以避免外部直接对属性进行修改,减少代码bug的可能性,确保数据的正确性。
  3. 控制访问权限:私有属性可以限制对对象的访问权限,只允许通过类的接口来操作对象,提高代码的可维护性和可扩展性。
  4. 信息隐藏:私有属性可以隐藏对象内部的实现细节,只暴露必要的接口,降低对象之间的耦合性,提高代码的灵活性。

总结:

方法类型装饰器第一个参数访问类属性访问实例属性调用方式
实例方法self可以可以必须通过实例
类方法@classmethodcls可以不可以类或实例
静态方法@staticmethod不可以不可以类或实例
构造方法无(特殊方法)self可以可以自动调用
方法的操作
  • 添加方法
  1. 在类的定义中直接添加:可以在类的定义内部直接使用 def 关键字定义新的方法
  2. 使用类方法动态添加:可以通过修改类的 __dict__ 属性或使用 setattr() 函数来动态添加方法
class MyClass:
    def __init__(self):
        pass

def new_method(self):
    print("这是通过动态添加的方法")
# 使用 setattr 动态添加方法
setattr(MyClass, 'new_method', new_method)
obj = MyClass()
obj.new_method()
  • 修改方法
  1. 直接在类的定义中修改:如果需要修改方法的实现,可以直接在类的定义中修改方法的代码
  2. 动态修改方法:可以通过修改类的 __dict__ 属性或使用 setattr() 函数来动态修改方法
class MyClass:
    def __init__(self):
        pass
    def old_method(self):
        print("这是旧的方法")

def new_implementation(self):
    print("这是新的实现")
# 使用 setattr 动态修改方法
setattr(MyClass, 'old_method', new_implementation)
obj = MyClass()
obj.old_method()
  • 删除方法
  1. 使用 del 关键字:可以直接使用 del 关键字来删除类的方法
  2. 使用 delattr() 函数:可以使用内置函数 delattr() 来删除类的方法
class MyClass:
    def __init__(self):
        pass
    def method_to_delete(self):
        print("这是要删除的方法")
obj = MyClass()
delattr(MyClass, 'method_to_delete')
# 下面这行代码会报错,因为方法已经被删除
# obj.method_to_delete()

四、面对过程和面对对象

参照博主:

Python面向对象详解(非常详细)-CSDN博客

面向对象三大特性:封装、继承、多态(最全面最详细的解释)_封装继承多态是面向对象编程的三大特征描述正确的是-CSDN博客

面对过程

过程式编程是一种编程范式,其主要思想是按照一系列步骤或过程来执行任务。在过程式编程中,程序主要由一系列函数或过程组成,这些函数或过程按照顺序执行,并且可以共享全局数据。过程式编程强调的是按照步骤处理问题,强调程序的执行流程,是一种比较直线性的编程方式。

面对对象编程的三大特性:封装、继承、多态

面向对象编程(Object-Oriented Programming,OOP)是另一种编程范式,其主要思想是将数据和操作封装在一个对象中。在面向对象编程中,程序主要由对象组成,每个对象包含了数据和定义了可以对这些数据执行的操作(方法)。面向对象编程强调的是将问题看作对象之间的交互,从而更贴近现实世界的建模方式,提高了代码的可维护性和重用性。

总的来说,过程式编程更侧重于按照步骤执行任务,而面向对象编程更侧重于对数据和操作的封装和组织。在实际开发中,可以根据不同的需求和场景选择合适的编程范式进行开发。

 ★★继承 

定义:继承指的是某个对象可以继承另一个对象的特性,从而快速构建具有相似属性的对象。它可以让子类继承父类的属性和方法,并且在基础上进行扩展

特点:如果父类的某个属性或方法也在子类中定义了,那么子类会重写父类的属性或方法,这样子类可以更好地针对自己的特定要求来实现相应的功能,这样可以减少重复代码,提高代码的重用性和可维护性

子类可以继承父类的属性和方法

  • 单继承:class 子类(父类):

一个类可以继承另一个类的属性和方法,这就是简单的单继承

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

    def speak(self):
        print(f"{self.name} makes a sound")

class Dog(Animal):  #单继承
    def speak(self):
        print(f"{self.name} barks")
dog1 = Dog("Dog")
dog1.speak()  #输出Dog barks

多继承:class  子类(父类1, 父类2...)

    可以继承多个父类,调用方法按顺序查找,先查询自身有无,再从左往右查询各个父类有无

    class A:
        def method_a(self):
            print("Method A")
    
    class B:
        def method_b(self):
            print("Method B")
    
    class C(A, B):
        def method_c(self):
            print("Method C")
    
    obj = C()
    obj.method_a()  #输出Method A
    obj.method_b()  #输出Method B
    obj.method_c()  #输出Method C
    • 超类:super(类名,实例)

    在Python中,父类也被称为超类(superclass),子类也称为派生类(subclass)。子类可以直接访问父类的方法和属性,并可以调用父类的构造函数来初始化父类的属性.

    super() 是一个内建函数,通常用于调用父类的方法。它的作用是返回一个代理对象,通过该对象可以调用父类中的方法。使用 super() 的一个常见场景是在子类的方法中调用父类的同名方法,可以继承父类的行为并添加一些特定的功能。

    class ParentClass:
        def __init__(self, name):
            self.name = name
    
        def greet(self):
            print(f"Hello, my name is {self.name}")
    
    
    class ChildClass(ParentClass):
        def __init__(self, name, age):
            super().__init__(name)
            self.age = age
    
        def greet(self):
            super().greet()
            print(f"I am {self.age} years old")
    
    childClass = ChildClass(name="John", age=20)
    childClass.greet() 
    #输出:Hello, my name is John
    #     I am 20 years old

    在上面的例子中,ChildClass 继承自 ParentClass,子类重写了 greet 方法来增加年龄信息。在子类的构造函数中,使用 super().__init__(name) 调用父类的构造函数,确保父类中的初始化逻辑也被执行。在子类的 greet 方法中,通过 super().greet() 调用父类的 greet 方法,然后再添加额外的信息。

     ★封装

    定义:封装意味着将对象的状态和行为进行封装,它将数据和方法封装在一个单独的单元中,使其对外只暴露必要的接口,从而提高了安全性和可维护性

    特点:可以利用访问控制修饰符来实现封装,包括公有、私有、受保护和包访问等四种级别

    上述设置私有属性和私有方法可以完全屏蔽该属性和方法不被子类继承。但有时候我们希望属性和方法能够局部开放,某些子类也可以继承和使用相关属性方法,这时候就需要用到封装的技术,将原本的私有属性和方法名用另一种表现形式对外提供接口。

    使用方式:在Python中,可以使用属性来封装类的数据。通过定义属性,可以限制对于属性的直接访问,并提供对属性的访问和修改方法。这些属性成为私有属性 ,私有属性可以通过装饰器@property@属性名.setter实现封装。

    可读:@property

    #封装
    class student:
        def __init__(self,sno,sname):
            self.sno=sno
            self.__sname=sname
        @property
        def name(self):
            return self.__sname
        def study(self):
            print(f'{self.__sname}在学校学习')
    s1=student(1,'tester01')
    print(s1.name)

    可写:@可读属性名.setter

    #封装
    class student:
        def __init__(self,sno,sname):
            self.sno=sno
            self.__sname=sname
        @property
        def name(self):
            return self.__sname
        @name.setter
        def name(self,name):
            self.__sname=name
        def study(self):
            print(f'{self.__sname}在学校学习')
    s1=student(1,'tester01')
    s1.name='tester02'
    print(s1.name) #输出tester02
      多态

      定义:多态是指同一种行为在不同的对象上具有不同的表现形式,即在不同的情境下,同一个方法可以被不同的对象进行调用。它让不同类的对象对同一消息做出不同的响应

      特点:多态是一种通过继承、重写和接口实现的机制;基于继承的实现,在这种实现中,父类定义一些通用的方法,子类则可以重写这些方法并实现不同的功能;基于接口的实现,在这种实现中,可以让不同的类实现同一个接口,从而实现多态

      #多态
      class Duck:
          def fly(self):
              print("Duck fly")
      
      class Swan:
          def fly(self):
              print("Swan fly")
      
      class Plane:
          def fly(self):
              print("Plan fly")
      def fly(obj):
          obj.fly()
      duck = Duck()
      swan = Swan()
      plane = Plane()
      fly(duck)   #Duck fly
      fly(swan)   #Swan fly
      fly(plane)  #Plan fly

      相关文章:

    • LeetCode 376. 摆动序列 java题解
    • 从 “12.3” 的崩溃到完美的解决方案:一场类型选择的冒险之旅
    • 蓝桥杯备赛-差分-重新排序
    • hive面试题--left join的坑
    • k8s集群中部署dcgm-exporter收集GPU指标
    • 机器学习 Day01人工智能概述
    • 串口数据记录仪DIY,体积小,全开源
    • 华为Mate 60 Pro+ 等机型适配支持运营商北斗卫星短信功能
    • 代码随想录算法训练营第六十一天 | 108. 冗余连接 109. 冗余连接II
    • 前端(AJAX)学习笔记(CLASS 4):进阶
    • 图库 | 基于图增强的智慧审计系统革新
    • Pika 技术浅析(三):生成对抗网络
    • C++编程:进阶阶段—4.2对象
    • 【十四】Golang 接口
    • 一学就会的深度学习基础指令及操作步骤(5)使用预训练模型
    • Vue3实战学习(Element-Plus常用组件的使用(输入框、下拉框、单选框多选框、el-image图片))(上)(5)
    • linux centos 安装源码nginx,开放端口
    • 【数据挖掘】知识蒸馏(Knowledge Distillation, KD)
    • 解决 Java/Kotlin 资源加载问题
    • 开源!速度100Kb/s的有线和无线双模ESP32S3芯片的DAP-Link调试器
    • 吉利汽车一季度净利润大增264%,称整合极氪后实现整体效益超5%
    • 习近平向多哥新任领导人致贺电
    • 美国务院批准向土耳其出售导弹及相关部件,价值3.04亿美元
    • 万科再获深铁集团借款,今年已累计获股东借款近120亿元
    • 商人运作亿元“茅台酒庞氏骗局”,俩客户自认受害人不服“从犯”判决提申诉
    • 奥迪车加油时频繁“跳枪”维修两年未解决,4S店拒退换:可延长质保