Python中神奇面向对象

devtools/2024/12/23 5:01:37/

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • 1、类(Class)与对象(Object)
    • 概念:
    • 代码示例:
  • 2.继承(Inheritance)
    • 概念:
    • 代码示例:
    • 多继承
    • 代码示例
  • 3. 方法重写(Method Overriding)
    • 概念
    • 代码展示
  • 4. 多态(Polymorphism)
    • 概念
    • 代码展示
  • 5.单例类
    • 概念
    • 代码展示
  • 6. 抽象类
    • 概念
    • 代码展示
  • 7. 动态定义实例的变量和方法
    • 使用setattr
    • 代码展示
  • 8. 动态定义类的变量和方法
    • 1.使用setattr
    • 代码展示
    • 2.直接操作__dict__
    • 代码展示
      • 说明
  • 9.定义静态方法
    • 说明staticmethod
    • 代码展示
  • 10.静态方法与类方法和实例方法的比较
  • 总结


前言

在Python中,面向对象编程(OOP)是一种非常强大的编程范式,它允许开发者以更自然的方式模拟现实世界中的复杂系统。下面,我将详细分析面向对象编程的几个核心概念,并提供相应的代码示例,最后探讨一些扩展知识点。


1、类(Class)与对象(Object)

示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。

概念:

  • :是一个模板,用于创建具有相同属性和方法的对象的蓝图。
  • 对象:是类的实例,具有类定义的属性和方法。

代码示例:

python">class Dog:  def __init__(self, name, age):  self.name = name  self.age = age  def bark(self):  print(f"{self.name} says Woof!")  # 创建Dog类的实例(对象)  
dog1 = Dog("Buddy", 3)  
dog1.bark()  # 输出: Buddy says Woof!

2.继承(Inheritance)

概念:

继承允许我们定义一个类(子类)来继承另一个类(父类)的属性和方法。子类可以添加新的属性或重写继承的方法。

代码示例:

python">class Animal:  def __init__(self, name):  self.name = name  def speak(self):  raise NotImplementedError("Subclass must implement abstract method")  class Dog(Animal):  def speak(self):  return f"{self.name} says Woof!"  dog2 = Dog("Rex")  
print(dog2.speak())  # 输出: Rex says Woof!

多继承

多继承允许一个类继承自多个基类。这意味着子类可以继承来自多个父类的属性和方法。然而,多继承也带来了所谓的“菱形问题”(或称为“钻石问题”),即当多个父类继承自同一个更上层的基类时,这个基类的属性和方法可能会在子类中被重复继承。Python通过方法解析顺序(Method Resolution Order, MRO)来解决这个问题,它确保了每个基类的方法只被调用一次。

代码示例

python">class A:  def __init__(self):  self.value = "A"  class B(A):  def __init__(self):  super().__init__()  self.value += "B"  class C(A):  def __init__(self):  super().__init__()  self.value += "C"  class D(B, C):  def __init__(self):  """ 这里会先调用B的__init__,然后是C的__init__(但C的__init__中super()调用实际上不会执行,因为A已被B初始化)"""super().__init__()   self.value += "D"  d = D()  
print(d.value)  # 输出: ABCD

3. 方法重写(Method Overriding)

概念

方法重写(Method Overriding)是一种非常关键的概念,它允许子类提供一个特定签名的方法实现,该方法在父类中已经存在。当通过子类的实例调用该方法时,将执行子类提供的实现,而不是父类中的原始实现。这提供了一种扩展或修改父类行为的方式,同时保持父类代码的可重用性。

代码展示

python">class Animal:  def speak(self):  print("This animal makes a generic sound.")  class Dog(Animal):  def speak(self):  # 重写speak方法  print("Woof!")  # 创建一个Dog对象并调用其speak方法  
dog = Dog()  
dog.speak()  # 输出: Woof!  # 如果我们创建一个Animal对象并调用其speak方法  
animal = Animal()  
animal.speak()  # 输出: This animal makes a generic sound.

4. 多态(Polymorphism)

概念

多态指的是不同类的对象对同一消息作出响应时,各对象将执行各自的方法。在Python中,由于动态类型系统和鸭子类型(duck typing),多态是隐式的。

代码展示

python">class Animal:  def make_sound(self):  pass  class Dog(Animal):  def make_sound(self):  return "Woof!"  class Cat(Animal):  def make_sound(self):  return "Meow!"  def animal_sound(animal):  print(animal.make_sound())  dog = Dog()  
cat = Cat()  
animal_sound(dog)  # 输出: Woof!  
animal_sound(cat)  # 输出: Meow!

5.单例类

概念

单例模式是一种常用的软件设计模式,其目的是确保一个类仅有一个实例,并提供一个全局访问点来获取这个实例。在Python中,可以通过多种方式实现单例模式,但最常见的是使用装饰器或模块级别的变量。

代码展示

python">def singleton(cls):  instances = {}  def get_instance(*args, **kwargs):  if cls not in instances:  instances[cls] = cls(*args, **kwargs)  return instances[cls]  return get_instance  @singleton  
class MyClass:  pass  obj1 = MyClass()  
obj2 = MyClass()  print(obj1 == obj2)  # 输出: True

6. 抽象类

概念

抽象类是一种不能被实例化的类,它通常用作基类,为子类定义接口。在Python中,abc模块提供了ABC(Abstract Base Class)和一系列装饰器(如@abstractmethod),用于定义抽象类和抽象方法。

代码展示

python">from abc import ABC, abstractmethod  class MyAbstractClass(ABC):  @abstractmethod  def my_abstract_method(self):  pass  class MyConcreteClass(MyAbstractClass):  def my_abstract_method(self):  print("实现了抽象方法")  # MyAbstractClass()  # 这会抛出TypeError,因为MyAbstractClass是抽象的  obj = MyConcreteClass()  
obj.my_abstract_method()  # 输出: 实现了抽象方法

7. 动态定义实例的变量和方法

使用setattr

setattr函数用于动态地给对象设置属性(包括方法和变量)。

代码展示

python">class MyClass:  pass  obj = MyClass()  # 动态定义实例变量  
setattr(obj, 'my_var', 'Hello, World!')  
print(obj.my_var)  # 输出: Hello, World!  # 动态定义实例方法  
def my_method(self):  print('This is a dynamically defined method.')  setattr(MyClass, 'my_method', my_method)  # 注意:这里应该修改类,以便所有实例都能访问  
obj.my_method()  # 调用动态定义的方法  # 或者只为单个实例动态添加方法  
def another_method(self):  print('This method is only for this instance.')  setattr(obj, 'another_method', types.MethodType(another_method, obj))  
obj.another_method()  # 调用

8. 动态定义类的变量和方法

1.使用setattr

和实例一样,你也可以使用setattr来动态地给类添加变量和方法

代码展示

python">class MyClass:  pass  # 动态定义类变量  
setattr(MyClass, 'class_var', 'Class Variable')  
print(MyClass.class_var)  # 输出: Class Variable  # 动态定义类方法  
def class_method(cls):  print('This is a class method.')  setattr(MyClass, 'class_method', classmethod(class_method))  
MyClass.class_method()  # 调用  # 或者直接使用赋值  
MyClass.another_class_var = 'Another Class Variable'  
def another_class_method(cls):  print('Another class method.')  
MyClass.another_class_method = classmethod(another_class_method)  
MyClass.another_class_method()  # 调用

2.直接操作__dict__

你也可以直接操作类的__dict__属性来添加或修改变量和方法。

代码展示

python">MyClass.__dict__['new_class_var'] = 'New Class Variable'  
print(MyClass.new_class_var)  # 输出: New Class Variable  def new_class_method(cls):  print('New class method.')  
MyClass.__dict__['new_class_method'] = classmethod(new_class_method)  
MyClass.new_class_method()  # 调用

说明

直接操作__dict__可能会绕过一些Python的内置检查和优化,因此通常建议使用setattr或其他更高级的API。

9.定义静态方法

说明staticmethod

在Python中,staticmethod 是一个装饰器(decorator),用于将函数绑定到类上,但不接收类或实例的隐式第一个参数(在普通实例方法中通常是 self,在类方法中通常是 cls)。这意味着 staticmethod 函数可以像普通函数一样被调用,但它被定义在类的命名空间中,因此可以通过类名来访问它,就像访问类变量或方法一样。

代码展示

python">class MathUtilities:  @staticmethod  def add(x, y):  return x + y  @staticmethod  def multiply(x, y):  return x * y  # 使用静态方法  
result_add = MathUtilities.add(5, 3)  
print(result_add)  # 输出: 8  result_multiply = MathUtilities.multiply(5, 3)  
print(result_multiply)  # 输出: 15  # 注意:静态方法也可以通过实例调用,但这样做并不常见  
math_utils = MathUtilities()  
print(math_utils.add(2, 2))  # 输出: 4

10.静态方法与类方法和实例方法的比较

  • 实例方法:需要接收类实例的引用(通常是 self)作为第一个参数,可以访问和修改实例的属性和方法。
  • 类方法:需要接收类本身的引用(通常是 cls)作为第一个参数,可以访问和修改类的属性(即类变量),但不能直接访问或修改实例的属性(除非通过实例方法或传递实例作为参数)。
  • 静态方法:不接收类或实例的隐式第一个参数,其行为更接近于普通函数,但定义在类的命名空间中,可以通过类名或实例来调用。

总结

以上就是今天要讲的内容,本文仅仅简单介绍Python中面向对象编程(OOP)的一些用法。


http://www.ppmy.cn/devtools/86555.html

相关文章

【SpringBoot】1 Gitee

本项目 Gitee 地址:https://gitee.com/Lin_DH/system idea中可能装个gitee的插件,这样操作起来比较方便。 1)登录 Gitee 官网(https://gitee.com/),新建仓库。 2)复制新建的 Gitee 仓库地址&am…

【前端面试】七、算法-节流、柯里化、数组和集合

数组常用方法 forEach:遍历数组,对数组的每个元素执行一次提供的函数。 map:创建一个新数组,其结果是该数组中的每个元素是调用一次提供的函数后的返回值。 filter:创建一个新数组,其包含通过所提供函数实…

蓝牙网关厂家推荐:北京桂花网科技有限公司

在物联网技术日新月异的今天,蓝牙网关作为连接蓝牙设备与物联网系统的关键桥梁,其重要性日益凸显。在众多蓝牙网关厂家中,北京桂花网科技有限公司(Cassia Networks)以其卓越的技术实力、丰富的产品线和广泛的应用场景&…

QUIC 协议

详解 QUIC 协议:它为何比 TCP 更优越?

深度学习的矩阵计算

切片slice 在NumPy中,切片(slicing)是一种选择数组元素子集的方法。切片操作基于索引,但允许你指定一个范围的索引,而不是单个索引。这对于处理多维数组(NumPy中的ndarray对象)特别有用。 一维数…

【AI落地应用实战】DAMODEL深度学习平台部署+本地调用ChatGLM-6B解决方案

ChatGLM-6B是由清华大学和智谱AI开源的一款对话语言模型,基于 General Language Model (GLM)架构,具有 62亿参数。该模型凭借其强大的语言理解和生成能力、轻量级的参数量以及开源的特性,已经成为在学术界和工业界引起了广泛关注。 本篇将介…

kafka详解及应用场景介绍

Kafka架构 Kafka架构,由多个组件组成,如下图所示: 主要会包含:Topic、生产者、消费者、消费组等组件。 服务代理(Broker) Broker是Kafka集群中的一个节点,每个节点都是一个独立的Kafka服务器…

【MySQL】索引 【下】{聚簇索引VS非聚簇索引/创建主键索引/全文索引的创建/索引创建原则}

文章目录 1.聚簇索引 VS 非聚簇索引经典问题 2.索引操作创建主键索引唯一索引的创建普通索引的创建全文索引的创建查询索引删除索引索引创建原则 1.聚簇索引 VS 非聚簇索引 之前介绍的将所有的数据都放在叶子节点的这种存储引擎对应的就是 InnoDB 默认存储表数据的存储结构。 …