python数据类型-7-自定义类型-class-面向对象编程,和我学习python的一点心得!

python数据类型-7-自定义类型-class-面向对象编程

一.说明

在python数据类型系列文章中已经介绍了 基础数据类型,容器类型 列表,元组,字典,集合等,今天我们一起来对自定义类型class类进行梳理,介绍class 其实就是要介绍python面向对象编程(OOP)

二.什么是面向对象

面向对象是一种思维方式,它认为万事万物皆对象,程序是由多个对象协作共同完成功能的,所以以后我们要从面向 过程转向面向对象。以面向对象的方式考虑程序的构建。面向对象的核心是:类和对象

类:类是抽象的,我们可以理解为 抽象的生产汽车工厂,比如汽车类 需要传入品牌 颜色 等 ;

对象:对象是类的实例,比如给汽车类传入初始化参数 比如 品牌 :宝马 ,颜色:金色,就给我们返回一个类的实例 金色的宝马

二.class(类)

1.定义

1.在 Python 中,类通过 class 关键字定义;

2.类的构成包含类的名称 类的属性 类的方法;

3.类名一般使用大驼峰命名 MyCar

4.类体必须进行缩进

5.在Python3中类默认继承object,所以class MyCar(object): 可以简写为class MyCar:

2.特性

1.封装:将数据(属性)和行为(方法)结合在一起,提供对外部的接口;

2.继承:允许一个类继承另一个类的属性和方法,增强代码重用性;

3.多态:允许不同类的实例以相同的方式调用方法,简化代码结构;

4.更好的组织性:通过将相关的属性和方法组织在类中,代码结构更加清晰;

5.提高可维护性:修改一个类的实现通常不会影响到使用该类的代码,降低了对其他部分代码的影响;

6.适应变化:可以轻松添加新功能,例如通过继承和多态,不需要改变现有代码的情况下扩展系统;

3.创建类
  1. 创建对象的格式为:对象名 = 类名()

    class MyCar:
        '''
        这是python中一个类的定义
        '''
        __slots__ = ('name','color')
        def __init__(self,name,color):
            self.name = name
            self.color = color
        def run(self):
            print(f'{self.name}:在跑')
    
    _bm = MyCar('宝马','金色') 
    _bm.run()
    
  2. 构造方法 __init__

    构造方法用于初始化对象的属性,它在创建对象时自动调用。

    当然也可以不定义,系统会生成一个无参构造方法

    class 类名:
    	def __init__(self):
    		pass
    

    那么我们对构造方法需要通过以下维度来学习。

    1. 语法:def init(self):

    2. 目的:构造方法用于初始化对象,可以在构造方法中添加成员属性

    3. 调用:构造函数由系统在实例化对象时自动调用,不要自己调用

    4. 参数:第一个参数必须是self,其它参数根据需要自己定义

    5. 返回值:不返回值,或者说返回None,不应该返回任何其他值

    6. 是否需要自己定义构造方法:没有定义构造方法,系统会生成一个无参构造方法

    7. 一个类只能有一个构造方法:如果定义多个,后面的会覆盖前面的

    def __init__(self,name,color):
       self.name = name
       self.color = color
    
  3. 析构方法

析构方法在 Python 中是用来清理对象的。当一个对象不再被使用并且被垃圾回收时,析构方法 __del__ 会被调用。

  1. 语法:def del(self):

  2. 调用:对象销毁时由系统自动调用

  3. 参数:除了self外,没有其他参数

  4. 返回值:不返回值,或者说返回None

class FileHandler:
    def __init__(self, filename):
        self.filename = filename
        self.file = open(self.filename, 'w')  # 打开文件进行写入
        print(f"File {self.filename} opened.")

    def write(self, content):
        self.file.write(content)  # 向文件写入内容

    def __del__(self):
        if self.file:
            self.file.close()  # 关闭文件
            print(f"File {self.filename} closed.")

# 使用示例
handler = FileHandler("example.txt")
handler.write("Hello, world!")

# 当 handler 变量超出作用域或被删除时,__del__ 方法会被调用
del handler  # 手动删除对象,触发析构方法
  1. 实例方法 def run(self):

    实例方法是与对象相关的方法,第一个参数通常是 self

    class Dog:
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        def bark(self):  # 实例方法
            return f"{self.name} says Woof!"
    
    # 创建一个 Dog 实例
    my_dog = Dog("Buddy", 3)
    
    # 调用实例方法
    print(my_dog.bark())  # 输出:Buddy says Woof!
    
  2. 声明实例所需要的属性

    当一个类需要创建大量实例时,可以通过 slots 声明实例所需要的属性,如果超过了此属性范围进行对象属性 赋值,就会限制,起到保护数据作用。

    当不用__slots__声明 可对实例动态添加属性

    那么问题来了为什么要用? slots = (‘name’,‘color’) 来限制属性,我们在接触其他语言时也会发现类的属性时被强制限定的,那么为什么要这么做?除了保证实例结构安全还有哪些优点呢?

    这样做带来以下优点:

    1. 更快的属性访问速度
    2. 通过取消 dict 的使用减少内存消耗
    3. 保护数据安全性
    # __slots__ = ('name','color')
    class MyCar:
        def __init__(self,name,color):
            self.name = name
            self.color = color
        def run(self):
            print(f'{self.name}:在跑')
    
    _bm = MyCar('宝马','金色')
    _bm.max_speed=400
    _bm.run() # 宝马:在跑
    print(_bm.max_speed) # 400
    
    
    ##########################
    class MyCar:
        '''
        这是python中一个类的定义
        '''
        __slots__ = ('name','color')
        def __init__(self,name,color):
            self.name = name
            self.color = color
        def run(self):
            print(f'{self.name}:在跑')
    
    _bm = MyCar('宝马','金色')
    _bm.max_speed=400  #报错 AttributeError: 'MyCar' object has no attribute 'max_speed'
    
    
  3. 私有属性(Private Attributes)

    私有属性是类内部的属性,通常以双下划线 (__) 开头,以指示该属性不应从类的外部访问。这是 Python 中一种约定,用于实现封装和数据保护。

    class Example:
        def __init__(self, value):
            self.name = value  # 私有属性
    
        def get_private_attribute(self):
            return self.__private_attribute  # 通过方法访问私有属性
        def set_private_attribute(self,value):
            self.__private_attribute = value
    obj = Example(10)
    obj.set_private_attribute(600)
    print(obj.get_private_attribute())  # 输出:10
    print(obj.__private_attribute)  # 报错: AttributeError: 'Example' object has no attribute '__private_attribute'
    
  4. 专有属性(Protected Attributes)

    专有属性是用单下划线 (_) 开头的属性,通常表示这些属性是受保护的,应该在类及其子类中访问,而不是在外部直接访问。这是 Python 的一种约定,而不是严格的访问控制,但仍然可以访问。

    class Example:
        def __init__(self, value):
            self._protected_attribute = value  # 专有属性
    
        def get_protected_attribute(self):
            return self._protected_attribute  # 通过方法访问专有属性
    class SubClass(Example):
        def display(self):
            print(self._protected_attribute)  # 子类可以访问专有属性
    
    obj = SubClass(20)
    obj.display()  # 输出:20
    print(obj.get_protected_attribute())  # 输出:20
    

    总结:

    1.私有属性(以 __ 开头)是用于封装和保护数据的,不能从类外部直接访问。

    2.专有属性(以 _ 开头)是受保护的,应该在类及其子类中使用,外部代码不应直接访问,但仍然可以访问。

  5. 类方法 @classmethod

    类方法是与类本身相关的方法,而不是与特定实例相关。它使用 @classmethod 装饰器。

    注意:第一个参数通常是 cls,表示类本身。

    1.类方法的第一个参数是类对象cls,那么通过cls引用的 必定是类对象的属性和方法;

    2.实例方法的第一个参数是实例对象self,那么通过self引用的可能是类属性、也有可 能是实例属性;

    3.存在相同名称的类属性和实例属性的情况下,实例属性优先级更高。

    class Dog:
        species = "Canine"  # 类属性
    
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        @classmethod
        def get_species(cls):  # 类方法
            return cls.species
    
    # 调用类方法
    print(Dog.get_species())  # 输出:Canine
    
  6. 静态方法

    静态方法是与类本身相关的方法,而不是与类的实例相关。静态方法不需要访问或修改类的属性,因此不需要 self 参数。静态方法使用 @staticmethod 装饰器定义。

    class Math:
        @staticmethod
        def add(a, b):  # 静态方法
            return a + b
    
    # 调用静态方法
    result = Math.add(5, 10)
    print(result)  # 输出:15
    
  7. 一个完整的实例 实现 类的封装 多态 继承

    封装确保了对象的内部状态被保护,用户只能通过方法来与之交互。

    继承允许子类重用父类的代码,并且强制子类实现某些方法。

    多态使得可以通过统一的接口来处理不同类型的对象,增强了代码的灵活性和可扩展性。

    多态的概念是应用于Java和C#这一类强类型语言中,而Python崇尚“鸭子类型”。 所谓多态:定义时的类型和运行时的类型不一样,此时就成为多态 Python “鸭子类型”

    class Animal:
        def __init__(self, name):
            self.name = name # 封装了动物的名字
    
        def speak(self):
            raise NotImplementedError("Subclass must implement abstract method")
    
    '''
    Dog 和 Cat 类都继承自 Animal 类。它们都拥有 Animal 的属性 name,并且可以使用 Animal 的构造函数来初始化这些属性。
    '''
    class Dog(Animal):
        def speak(self):  #重写父类方法
            return "Woof!" # 具体实现
    '''
    Dog 和 Cat 类实现了 speak 方法,这是 Animal 类中的一个抽象方法(通过抛出 NotImplementedError 实现)。这意味着任何继承自 Animal 的类都必须实现 speak 方法。
    '''
    
    class Cat(Animal):
        def speak(self):  #重写父类方法
            return "Meow!" # 具体实现
    
    '''
    多态是指不同类的对象可以使用相同的接口调用各自的方法,而具体的实现可以不同。在这段代码中,多态的体现主要在 animal_sound 函数中
    '''
    def animal_sound(animal):
        print(f"{animal.name} says: {animal.speak()}")
    
    
    # 使用示例
    dog = Dog("Buddy")
    cat = Cat("Whiskers")
    '''
    在这两个调用中,dog 和 cat 是 Dog 和 Cat 的实例。尽管它们调用的是同一个 animal_sound 函数,但它们各自的 speak 方法提供了不同的实现,展现了多态的特性。
    '''
    animal_sound(dog)  # 输出:Buddy says: Woof!
    animal_sound(cat)  # 输出:Whiskers says: Meow!
    
    
  8. 将类中的方法转换为属性 @property 装饰器

    为什么是将方法转换为属性?既然是方法,那么转换为属性时,可以添加一些逻辑,作用如下

    1. 简化接口:使用 @property 可以让方法以属性的方式访问,使得调用更直观。

    2. 封装逻辑:可以在获取或设置属性时添加自定义逻辑,而不需要改变外部接口。

    3. 只读属性:可以通过定义一个只带 @property 的方法来实现只读属性,防止外部代码直接修改属性值。

    使用场景:

    1. 计算属性:有时某个属性的值是基于其他属性计算得出的,使用 @property 可以在访问该属性时动态计算其值。

    2. 数据验证:在设置属性值时,可以进行验证,确保赋值符合特定规则。

    3. 只读属性:当需要对属性提供只读访问时,可以使用 @property 而不定义 setter 方法。

    class Circle:
        def __init__(self, radius):
            self._radius = radius  # 使用下划线表示内部属性
    
        @property
        def radius(self):
            return self._radius  # 只读属性
    
        @radius.setter
        def radius(self, value):
            if value < 0:
                raise ValueError("Radius cannot be negative")
            self._radius = value  # 设置值时进行验证
    
        @property
        def area(self):
            return 3.14 * (self._radius ** 2)  # 动态计算面积
    
    # 使用示例
    circle = Circle(5)
    print(circle.radius)  # 输出:5
    print(circle.area)    # 输出:78.5
    
    circle.radius = 10    # 修改半径
    print(circle.area)    # 输出:314.0
    
    # circle.radius = -5  # 会抛出 ValueError: Radius cannot be negative
    

三.总结

Python中数据类型 自定义类型class 在开发中有大量的应用,不管怎样都得掌握他,虽然class中的概念很多,但是我们初学习的时候有个印象就行了,后面实际开发多用,就掌握了;

这里要提一下学习方法:

第一要系统学习,系统学习不是要都掌握 是要有印象;

第二不要急于学习新知识,而是你已经掌握多少知识,有一句谚语!江里的大鲫鱼永远比不上手里的小泥鳅!

第三复习很重要,我在开始学习编程的时候就是拿本子记,不是应为我不会啥云文档 博客 markdown文档语法,而是因为我需要复习,而拿笔记本复习更实在更具体!!永远提醒我 要开始复习了!!云文档能提示我个啥!!

关于class我就写到这,有不足地方,欢迎大家补充,我来更新!

创作不易,喜欢的话点点关注 点点赞,再次_感谢!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SEEONTIME

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值