0
点赞
收藏
分享

微信扫一扫

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

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()

  1. 构造方法 __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

  1. 析构方法

析构方法在 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!

  1. 声明实例所需要的属性
    当一个类需要创建大量实例时,可以通过 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'

  1. 私有属性(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'

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

  1. 类方法 @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

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

class Math:
    @staticmethod
    def add(a, b):  # 静态方法
        return a + b

# 调用静态方法
result = Math.add(5, 10)
print(result)  # 输出:15

  1. 一个完整的实例 实现 类的封装 多态 继承

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

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

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

  1. 多态的概念是应用于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!

  1. 将类中的方法转换为属性 @property 装饰器
    为什么是将方法转换为属性?既然是方法,那么转换为属性时,可以添加一些逻辑,作用如下
  1. 简化接口:使用 @property 可以让方法以属性的方式访问,使得调用更直观。
  2. 封装逻辑:可以在获取或设置属性时添加自定义逻辑,而不需要改变外部接口。
  3. 只读属性:可以通过定义一个只带 @property 的方法来实现只读属性,防止外部代码直接修改属性值。
  1. 使用场景:
  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我就写到这,有不足地方,欢迎大家补充,我来更新!

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

举报

相关推荐

0 条评论