python之多态

本文深入探讨面向对象编程的三大核心特性:封装、继承和多态。通过具体代码示例,详细解释每个特性如何增强软件的安全性、可扩展性和灵活性。同时,介绍了Python中的特殊方法如__len__,并讨论了鸭子类型的概念。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

多态


面向对象的三大特征:

  • 封装
    • 确保对象中的数据安全
  • 继承
    • 保证了对象的可扩展性
  • 多态
    • 保证了程序的灵活性
# 定义两个类
class A:
    def __init__(self,name):
        self._name = name

    @property
    def name(self):
        return self._name
        
    @name.setter
    def name(self,name):
        self._name = name  
         
    def say_hello(self):
        print('你是%s'%self._name)
        
    def say_hello2(obj):
        print('你是obj:%s' % obj._name)
        
    def say_hello3(obj):
        # 做类型检查
        if isinstance(obj , A):
            print('你是A的对象%s'%obj.name)

class B:
    def __init__(self,name):
        self._name = name

    def __len__(self):
        return 10

    @property
    def name(self):
        return self._name
        
    @name.setter
    def name(self,name):
        self._name = name   

class C:
    pass


a = A('孙悟空')
b = B('猪八戒')
c = C()

定义一个函数
对于say_hello()这个函数来说,只要对象中含有name属性,它就可以作为参数传递
这个函数并不会考虑对象的类型,只要有name属性即可

def say_hello2(obj):
    print('你好 %s'%obj.name)

在say_hello3中我们做了一个类型检查,也就是只有obj是A类型的对象时,才可以正常使用,其他类型的对象都无法使用该函数,这个函数就违反了多态。违反了多态的函数,只适用于一种类型的对象,无法处理其他类型对象,这样导致函数的适应性非常的差。
注意,向isinstance()这种函数,在开发中一般是不会使用的!

def say_hello3(obj):
    # 做类型检查
    if isinstance(obj , A):
        print('你好 %s'%obj.name)    
say_hello2(b)    
say_hello3(b)

鸭子类型
如果一个东西,走路像鸭子,叫声像鸭子,那么它就是鸭子

len()
之所以一个对象能通过len()来获取长度,是因为对象中具有一个特殊方法__len__
换句话说,只要对象中具有__len__特殊方法,就可以通过len()来获取它的长度

l = [1,2,3]
s = 'hello'

print(len(l))
print(len(s))
print(len(b))
print(len(c))

### Python 多态的实现方式与原理 Python 中的多态(Polymorphism)主要依赖于其动态类型系统和鸭子类型(Duck Typing)机制,这使得多态的实现方式与静态类型语言(如 C++ 或 Java)有所不同。Python 多态的核心在于对象的行为(方法)而非类型,只要对象具有所需的方法,就可以在多态上下文中使用。 #### 动态类型与鸭子类型 Python 是一种动态类型语言,变量的类型在运行时确定,并且对象的方法和属性在运行时解析。这种特性使得 Python 支持所谓的“鸭子类型”,即“如果它走起来像鸭子,叫起来也像鸭子,那它就是鸭子”。因此,多态Python 中并不依赖于继承关系,而是依赖于对象是否实现了特定的方法。 例如,一个 `Canvas` 类中的 `draw_pic()` 方法可以接受任何具有 `draw()` 方法的对象作为参数,而无需关心该对象的具体类型。这种灵活性使得代码更加通用和可扩展[^1]。 ```python class Circle: def draw(self): print("Drawing a circle") class Square: def draw(self): print("Drawing a square") class Canvas: def draw_pic(self, shape): shape.draw() canvas = Canvas() canvas.draw_pic(Circle()) # 输出: Drawing a circle canvas.draw_pic(Square()) # 输出: Drawing a square ``` 在上述代码中,`Canvas` 类的 `draw_pic()` 方法接受任何具有 `draw()` 方法的对象,体现了多态的灵活性[^2]。 #### 多态的实现原理 Python多态实现与 C++ 等静态类型语言不同。在 C++ 中,多态通常通过虚数表(vtable)实现,每个对象内部保存了指向其类的虚数表的指针。而在 Python 中,多态的实现更依赖于对象的类型信息和方法解析机制。 在 Python 的底层实现中,所有对象都以 `PyObject` 结构体为基础,其中包含了对象的引用计数(`ob_refcnt`)和类型信息(`ob_type`)。当一个对象(如 `PyIntObject`)被转换为 `PyObject` 指针时,可以通过 `ob_type` 字段找到该对象的实际类型,并调用相应的数。这种机制使得 Python 能够支持多态行为,即使对象的类型在运行时发生变化,也能正确调用相应的方法[^4]。 #### 继承与多态 尽管 Python多态不强制依赖于继承,但继承仍然是实现多态的一种常见方式。通过定义一个基类,并在派生类中重写其方法,可以在运行时根据对象的实际类型调用相应的方法。 ```python class Shape: def draw(self): pass class Circle(Shape): def draw(self): print("Drawing a circle") class Square(Shape): def draw(self): print("Drawing a square") def draw_shape(shape): shape.draw() draw_shape(Circle()) # 输出: Drawing a circle draw_shape(Square()) # 输出: Drawing a square ``` 在上述代码中,`draw_shape()` 数接受 `Shape` 类型的参数,并调用其 `draw()` 方法。由于 `Circle` 和 `Square` 都继承自 `Shape` 并重写了 `draw()` 方法,因此在运行时会根据对象的实际类型调用相应的方法。 #### 多态的优势 Python 多态的优势在于其灵活性和可扩展性。程序中涉及多态的方法(如 `Canvas` 类的 `draw_pic()` 方法)所需的参数非常灵活,只要传入的对象具有指定的方法即可,至于该方法呈现怎样的行为特征,则完全取决于对象本身。这种机制大大提高了代码的通用性和可维护性[^1]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值