Python进阶知识2

python类和对象

3.属性和方法

        3.6初始化方法/构造方法

         在Python中,构造方法(也称为初始化方法)是一个特殊的方法,用于在创建对象时初 始化对象的属性。这个方法在类定义中使用__init__来表示。当你创建类的新实例时,__init__方法会自动被调用,从而允许你为对象设置初始状态或执行其他必要的启动任务。

以下是一个简单的Python类示例,该类包含一个构造方法

class Person:  
    def __init__(self, name, age):  
        self.name = name  # 设置对象的name属性  
        self.age = age    # 设置对象的age属性  
  
# 创建Person类的一个实例  
person1 = Person("Alice", 30)  
  
# 访问对象的属性  
print(person1.name)  # 输出: Alice  
print(person1.age)   # 输出: 30

3.7魔法方法 

        在Python中,魔术方法(也称为特殊方法或双下划线方法)是一类具有特殊意义的方法,它们的名称前后都包含两个下划线(例如,__init____str____add__等)。这些方法为Python对象提供了丰富的功能,允许对象以特定的方式响应内置函数和操作符。

以下是一些常见的Python魔术方法及其用途:

  1. 初始化与表示
    • __init__(self, ...):构造器,在对象创建时调用,用于初始化对象的属性。
    • __new__(cls, ...):是一个静态方法,用于创建并返回类的实例。在__init__之前被调用,通常用于继承不可变类型(如int、str、tuple)时自定义实例化过程。
    • __del__(self):析构器,在对象被销毁时调用,用于执行清理操作。
    • __str__(self):定义对象的“非正式”字符串表示,通常用于print()函数。
    • __repr__(self):定义对象的“正式”字符串表示,通常用于调试,repr()函数会调用它。
  2. 数值运算
    • __add__(self, other):定义加法操作。
    • __sub__(self, other):定义减法操作。
    • __mul__(self, other):定义乘法操作。
    • __truediv__(self, other):定义真除法操作。
    • __floordiv__(self, other):定义整数除法操作。
    • __mod__(self, other):定义取模操作。
    • __pow__(self, other[, modulo]):定义幂运算操作。
    • __radd__(self, other):定义右侧加法操作(用于加法反射)。
    • 类似地,还有__rsub____rmul__等,用于定义其他算术运算的反射操作。
  3. 比较操作
    • __lt__(self, other):定义小于操作。
    • __le__(self, other):定义小于等于操作。
    • __eq__(self, other):定义等于操作。
    • __ne__(self, other):定义不等于操作。
    • __gt__(self, other):定义大于操作。
    • __ge__(self, other):定义大于等于操作。
  4. 容器类型
    • __len__(self):定义获取容器长度的操作(如len())。
    • __getitem__(self, key):定义获取容器中元素的操作(如self[key])。
    • __setitem__(self, key, value):定义设置容器中元素的操作。
    • __delitem__(self, key):定义删除容器中元素的操作。
    • __contains__(self, item):定义成员关系测试操作(如item in self)。
  5. 可迭代与迭代器
    • __iter__(self):定义创建迭代器对象的操作。
    • __next__(self):定义迭代器返回下一个项目的操作。

下面是一些例子帮助理解:

  • __str__:返回对象的字符串表示,通常用于打印输出。
class Point:  
    def __init__(self, x, y):  
        self.x = x  
        self.y = y  
    def __str__(self):  
        return f"({self.x}, {self.y})"
  • __len__:返回对象的长度,通常与内置函数len()一起使用。
class MyList:  
    def __init__(self, items):  
        self.items = items  
    def __len__(self):  
        return len(self.items)
  • 自定义迭代器类:通过定义__iter____next__方法,赋予对象迭代能力
class CustomIterator:  
    def __init__(self, limit):  
        self.current = 0  
        self.limit = limit  
    def __iter__(self):  
        return self  
    def __next__(self):  
        if self.current >= self.limit:  
            raise StopIteration  
        else:  
            current_value = self.current  
            self.current += 1  
            return current_value

 4.继承/派生

        在Python中,继承是一种面向对象编程(OOP)的特性,它允许一个类(称为子类或派生类)继承另一个类(称为父类或基类)的属性和方法。通过继承,子类可以重用父类的代码,同时还可以添加或覆盖父类的功能。

4.1基本用法

        要创建一个子类,你需要使用class关键字,并在类名后面的括号中指定父类。如果父类在当前模块或内置模块中,你可以直接写类名。如果父类在另一个模块中,你需要使用模块名加点号再加类名的方式。

# 定义父类  
class Animal:  
    def __init__(self, name):  
        self.name = name  
  
    def speak(self):  
        raise NotImplementedError("Subclass must implement abstract method")  
  
# 定义子类,继承自Animal  
class Dog(Animal):  
    def speak(self):  
        return f"{self.name} says Woof!"  
  
# 创建Dog类的实例  
d = Dog("Rex")  
print(d.speak())  # 输出: Rex says Woof!

        在这个例子中,Dog类继承了Animal类,并覆盖了speak方法。当我们调用d.speak()时,Python会查找Dog类中定义的speak方法,并调用它。

4.2多重继承

        Python支持多重继承,即一个子类可以继承多个父类。多重继承可能会导致一些复杂的问题,比如方法名冲突(也称为菱形继承问题),但是Python的MRO算法通常能够很好地处理这些问题。

class A:  
    def method(self):  
        return "A's method"  
  
class B(A):  
    pass  
  
class C(A):  
    def method(self):  
        return "C's method"  
  
class D(B, C):  
    pass  
  
# 创建D类的实例  
d = D()  
print(d.method())  # 输出: C's method,因为C在MRO中排在B之前

        在这个例子中,D类继承了BC,而BC都继承了A。当我们调用d.method()时,由于Cmethod方法在MRO中排在B的之前,所以Python会调用Cmethod方法。

  • 继承可以提高代码的重用性和可维护性,但是过度使用继承可能会导致代码变得复杂和难以理解。
  • 在设计类时,要考虑好继承关系,避免创建过于庞大的类层次结构。
  • 如果子类需要修改父类的行为,可以考虑使用方法覆盖(重写父类的方法)或扩展(在子类中调用父类的方法,并添加额外的功能)。

4.3 覆盖 override

  • 覆盖是指在有继承关系的类中,子类中实现了与基类同名的方法,在子类的实例调用该方法时,实际调用的是子类中的覆盖版本,这种现象叫覆盖

  • 作用:

    • 实现和父类同名,但功能不同的方法

  • 覆盖示例

class A:
    def work(self):
        print("A.work 被调用!")

class B(A):
    '''B类继承自A类'''
    def work(self):
        print("B.work 被调用!!!")
    pass

b = B()
b.work()  # 请问调用谁?  B

a = A()
a.work()  # 请问调用谁?  A

5.封装 

        在Python中,封装(Encapsulation)是面向对象编程(OOP)的一个核心概念。它主要涉及到将对象的属性和方法结合在一起,并隐藏对象的内部实现细节,只对外暴露必要的接口。这样做的目的是增加代码的安全性和可维护性,同时减少不同部分之间的依赖。

  1. 隐藏内部实现:类的内部细节(如属性和方法)被隐藏起来,不对外部直接可见。这通常通过名称修饰(name mangling)或双下划线前缀(__)来实现,尽管Python并没有真正的私有变量或方法,但这是一种约定俗成的做法。

  2. 提供公共接口:类通过提供公共方法(也称为接口)来与外部世界交互。这些方法是类的外部用户唯一可以调用的。

  3. 保护对象状态:封装允许类控制对其属性的访问,从而保护对象的状态不被随意修改。这可以通过getter和setter方法来实现,它们分别用于获取和设置属性值。

在Python中,虽然没有严格的访问控制(如Java中的privateprotectedpublic关键字),但可以通过使用双下划线前缀

class MyClass:  
    def __init__(self, value):  
        self.__secret_value = value  # 修饰为“私有”属性  
  
    def get_secret_value(self):  
        return self.__secret_value  
  
    def set_secret_value(self, value):  
        self.__secret_value = value

6.多态

        在Python中,多态(Polymorphism)是面向对象编程(OOP)的一个核心概念,它允许不同的类对象通过相同的接口调用方法。多态性主要分为编译时多态(也称为静态多态或方法重载)和运行时多态(也称为动态多态或方法重写)。Python主要支持的是运行时多态,这是通过继承和方法重写来实现的。

6.1多的基本概念

        多态意味着“多种形态”,在编程中,它允许一个接口或父类引用指向子类对象,并通过这个引用调用在子类中重写的方法。这样做的好处是,可以在不改变客户端代码的情况下,通过替换不同的子类来实现不同的行为。

6.2Python中的多态实现      

        在Python中,多态通常是通过继承和方法重写来实现的。以下是一个简单的例子:

class Animal:  
    def speak(self):  
        raise NotImplementedError("Subclass must implement abstract method")  
  
class Dog(Animal):  
    def speak(self):  
        return "Woof!"  
  
class Cat(Animal):  
    def speak(self):  
        return "Meow!"  
  
# 多态性示例  
def animal_speak(animal):  
    print(animal.speak())  
  
# 创建Dog和Cat的实例  
dog = Dog()  
cat = Cat()  
  
# 通过相同的接口调用方法  
animal_speak(dog)  # 输出: Woof!  
animal_speak(cat)  # 输出: Meow!
  • 面向对象编程语言的特征:

    • 继承

    • 封装

    • 多态

7.方法重写

        在Python中,方法重写(Method Overriding)是面向对象编程(OOP)中的一个重要概念。它允许子类提供一个特定的实现,该实现会覆盖(或重写)在父类中定义的同名方法。这样做的目的是允许子类根据自身的需要定制或扩展父类的行为。

7.1方法重写的基本步骤

  1. 定义一个父类,并在其中声明一个或多个方法。这些方法可以是具体的实现,也可以是抽象方法(在Python中,抽象方法通常通过在父类中引发NotImplementedError异常来模拟)。

  2. 创建一个子类,该子类继承自父类。

  3. 在子类中重写父类中定义的同名方法。这意味着子类提供了一个新的实现,该实现将替换父类中的实现。

以下是一个简单的Python示例,展示了方法重写的基本用法:

class Animal:  
    def speak(self):  
        return "说话" 
  
class Dog(Animal):  
    def speak(self):  
        return "Woof!"  
  
class Cat(Animal):  
    def speak(self):  
        return "Meow!"  
  
# 创建一个Dog实例并调用其speak方法  
dog = Dog()  
print(dog.speak())  # 输出: Woof!  
  
# 创建一个Cat实例并调用其speak方法  
cat = Cat()  
print(cat.speak())  # 输出: Meow!

7.2 内建函数重写

  • __abs__ abs(obj) 函数调用

  • __len__ len(obj) 函数调用

  • __reversed__ reversed(obj) 函数调用

  • __round__ round(obj) 函数调用

  • 内建函数 重写示例

# file : len_overwrite.py
class MyList:
    def __init__(self, iterable=()):
        self.data = [x for x in iterable]
    def __repr_(self):
        return "MyList(%s)" % self.data
    def __len__(self):
        print("__len__(self) 被调用!")
        return len(self.data)
    def __abs__(self):
        print("__len__(self) 被调用!")
        return MyList((abs(x) for x in self.data))

myl = MyList([1, -2, 3, -4])
print(len(myl))
print(abs(myl))

7.3运算符重载

  • 运算符重载是指让自定义的类生成的对象(实例)能够使用运算符进行操作

  • 运算符重载的作用

    • 让自定义类的实例像内建对象一样进行运算符操作

    • 让程序简洁易读

    • 对自定义对象将运算符赋予新的运算规则

  • 运算符重载说明:

    • 运算符重载方法的参数已经有固定的含义,不建议改变原有的意义

  • 算术运算符重载示例
class MyNumber:
    "此类用于定义一个自定义的类,用于演示运算符重载"
    def __init__(self, value):
        "构造函数,初始化MyNumber对象"
        self.data = value
    def __str__(self):
        "转换为表达式字符串"
        return "MyNumber(%d)" % self.data
    def __add__(self, rhs):
        "加号运算符重载"
        print("__add__ is called")
        return MyNumber(self.data + rhs.data)
    def __sub__(self, rhs):
        "减号运算符重载"
        print("__sub__ is called")
        return MyNumber(self.data - rhs.data)

n1 = MyNumber(100)
n2 = MyNumber(200)
print(n1 + n2)
print(n1 - n2)

 8.super函数

        在Python中,super()函数是用于调用父类(超类)的一个方法。它常用于多继承的环境中,以确保每个父类都被正确地初始化,并且允许子类扩展或重写父类的方法。super()解决了直接调用父类方法时可能遇到的名称解析问题,特别是在复杂的继承链中。

8.1基本用法

        当在子类中调用super()时,它会返回当前类的父类的一个临时对象,允许你调用该父类的方法。这通常用于__init__方法来确保父类被正确初始化。

class Parent:  
    def __init__(self):  
        print("Parent __init__")  
  
class Child(Parent):  
    def __init__(self):  
        super().__init__()  # 调用父类的__init__方法  
        print("Child __init__")  
  
# 创建Child类的实例  
child = Child()  
# 输出:  
# Parent __init__  
# Child __init__

在这个例子中,Child类的__init__方法使用super().__init__()来调用Parent类的__init__方法,确保父类被正确初始化。

8.2多继承中的用法

        在多继承的情况下,super()函数按照方法解析顺序(MRO,Method Resolution Order)来调用父类的方法。MRO是一个定义了在调用一个方法时应该搜索哪个类的顺序的算法。

class A:  
    def __init__(self):  
        print("A __init__")  
  
class B(A):  
    def __init__(self):  
        super().__init__()  
        print("B __init__")  
  
class C(A):  
    def __init__(self):  
        super().__init__()  
        print("C __init__")  
  
class D(B, C):  
    def __init__(self):  
        super().__init__()  
        print("D __init__")  
  
# 创建D类的实例  
d = D()  
# 输出可能(取决于Python版本和MRO的具体实现):  
# A __init__  
# C __init__  
# B __init__  
# D __init__

        在这个例子中,D类继承了BC,而BC都继承了AD__init__方法使用super()来调用它的一个父类的__init__方法。由于MRO的存在,super()会按照特定的顺序(在这个例子中可能是A -> C -> B -> D)来调用方法。

8.3注意事项

  • super()不是函数,而是一个类。当你调用super()时,你实际上是在创建一个super类的实例。
  • super()通常与__init__方法一起使用,但也可以用于调用其他被重写的父类方法。
  • 在使用super()时,不需要传递任何参数;Python会自动处理这些。
  • 在单继承的情况下,super()的行为可能看起来与直接调用父类方法相同,但在多继承中,它提供了更强大和灵活的功能。

        总之,super()是Python中一个非常有用的特性,它简化了在继承环境中对父类方法的调用,并帮助避免了由于直接调用父类方法而可能导致的错误。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值