Python知识点:面向对象第二部分

2023-12-31 11:20:45

1、魔法方法

1.1?__init__魔法方法

init()函数是Python中一个特殊的函数,它在创建对象时自动执行,用于初始化对象的属性。 当我们创建一个类的实例时,Python会自动调用该类的init函数,并传入该对象自身作为第一个参数(通常习惯上命名为self),然后我们可以在init函数中为对象的属性赋初始值。

1.1.1不带参数的init魔法方法

示例:

class Washer():
    def __init__(self):  # 初始化魔法方法
        # 添加属性
        print('这是初始化魔法方法')
        self.height = 1000
        self.width = 300

    def print_info(self, name):
        """获取属性"""
        print('洗衣机的高度是:', self.height)
        print(name)


xiaotiane = Washer()
xiaotiane.print_info('nihao')

注意:init魔法方法 注意不要写成int魔法方法,不要多下划线或少下划线

1.1.2带参数的init魔法方法

示例:

class Washer():
    def __init__(self, height, width):  # 初始化魔法方法
        # 添加属性
        self.height = height
        self.width = width

    def print_info(self):
        """获取属性"""
        print('洗衣机的高度是:', self.height)
        print('洗衣机的高度是:', self.width)


xiaotiane = Washer(1000, 300)
xiaotiane.print_info()
1.2 str魔法方法

当print输出一个对象的时候,默认打印的是对象的内存空间地址,如果在类中定义了str魔法方法之后,那么此时在打印对象的时候就是打印的这个方法的返回值。

示例:

class Washer():
    def wash(self):
        print('洗衣服===')

    def __str__(self):  # 类的说明或者类的状态
        return '这是洗衣机的使用说明'


xiaotiane = Washer()
print(xiaotiane)
1.3 del魔法方法

当删除一个对象的时候,Python解释器会自动调用del魔法方法

示例:

class Washer():
    def wash(self):
        print('洗衣服===')

    def __del__(self):
        """删除对象"""
        print(f'{self}对象已经被删除')


xiaotiane = Washer()
del xiaotiane
print(xiaotiane)  # 报错

注意:

  • 如果一个类有多个对象,每个对象的属性是各自独立保存的,都是独立的地址。

  • 但是实例方法是所有对象所共享的,只占用一份内存空间,类会通过self参数来判断是那个对象调用了该实例方法。

2、面向对象-继承

2.1?继承的概念

Python中面向对象中的继承就是指的是多个类之间的一个从属关系,即子类默认继承父类的所有方法和属性。

2.2 单继承

所谓单继承就是指子类只继承一个父类

示例:

# 定义父类
class Master(object):
    def __init__(self):
        self.kongfu = '一剑仙人跪'

    def battle(self):
        print(f'运用了{self.kongfu}和敌人battle')


# 定义子类
class Prentice(Master):
    pass


# 用子类创建对象,调用父类的属性和方法
xiaoxu = Prentice()
print(xiaoxu.kongfu)  # 子类对象调用父类的属性
xiaoxu.battle()  # 子类的对象调用父类的方法

总结:

  • 子类在继承的时候,在定义类的时候,小括号中写的就是父类的名字

  • 父类的方法和属性都会被子类继承

2.3 多继承

所谓多继承就是指一个子类同时继承多个父类。

示例:

# 定义第一个父类
class Master(object):
    def __init__(self):
        self.kongfu = '一剑仙人跪'
        self.name = '李淳罡'

    def battle(self):
        print(f'运用了{self.kongfu}和敌人battle')


# 定义第二个父类
class Maid(object):
    def __init__(self):
        self.kongfu = '霸王卸甲'
        self.name = '青鸟'

    def battle(self):
        print(f'运用了{self.kongfu}和敌人battle')

    def aaa(self):
        print('这是侍女类的aaa方法')


# 定义子类类
class Prentice(Master, Maid):
    def __init__(self):
        self.kongfu = '剑气滚龙壁'

    def battle(self):
        print(f'运用了{self.kongfu}和敌人battle')


# 用徒弟创建对象,调用师傅的属性和方法
xiaoxu = Prentice()
print(xiaoxu.kongfu)
# 子类的魔法属性__mro__ 决定了属性和方法的查找顺序
print(Prentice.__mro__)

总结:

  • 多继承可以继承多个父类,也继承了所有父类的属性和方法

  • 注意:如果多个父类中有同名的方法和属性,则默认使用第一个父类的属性和方法(根据类中魔法属性mro的顺序来查找的)

  • 多个父类中,不同名的属性和方法,不会有任何影响

2.4 子类重写父类的同名方法和属性

示例:

# 定义第一个父类
class Master(object):
    def __init__(self):
        self.kongfu = '一剑仙人跪'
        self.name = '李淳罡'

    def battle(self):
        print(f'运用了{self.kongfu}和敌人battle')


# 定义第二个父类
class Maid(object):
    def __init__(self):
        self.kongfu = '霸王卸甲'
        self.name = '青鸟'

    def battle(self):
        print(f'运用了{self.kongfu}和敌人battle')

    def aaa(self):
        print('这是侍女类的aaa方法')


# 定义子类
class Prentice(Master, Maid):
    def __init__(self):
        self.kongfu = '剑气滚龙壁'

    def battle(self):
        print(f'运用了{self.kongfu}和敌人battle')


# # 用子类创建对象,调用父类的属性和方法
# xiaoxu = Prentice()
# print(xiaoxu.kongfu)
# xiaoxu.battle()

print(Prentice.__mro__)
2.5子类调用父类的同名方法和属性

示例:

# 定义第一个父类
class Master(object):
    def __init__(self):
        self.kongfu = '一剑仙人跪'
        self.name = '李淳罡'

    def battle(self):
        print(f'运用了{self.kongfu}和敌人battle')


# 定义第二个父类
class Maid(object):
    def __init__(self):
        self.kongfu = '霸王卸甲'
        self.name = '青鸟'

    def battle(self):
        print(f'运用了{self.kongfu}和敌人battle')

    def aaa(self):
        print('这是侍女类的aaa方法')


# 定义子类
class Prentice(Master, Maid):
    def __init__(self):
        self.kongfu = '剑气滚龙壁'

    def battle(self):
        self.__init__()
        print(f'运用了{self.kongfu}和敌人battle')

    # 把父类的同名方法和属性再次封装就可以了
    def master_battle(self):
        # 父类名.方法名(self)
        Master.__init__(self)
        Master.battle(self)
        # Master().battle()  # 不推荐使用


# # 用子类创建对象,调用父类的属性和方法
xiaoxu = Prentice()
# print(xiaoxu.kongfu)
xiaoxu.battle()
xiaoxu.master_battle()
xiaoxu.battle()

核心点:无论何时何地,self都表示的是子类的对象,在调用父类方法时,通过传递self参数,来控制方法和属性的访问和修改。

Master().battle() # 不推荐使用,因为相当于重新创建了一个新的父类对象,占用不必要的内存。

2.6 多层继承

所谓多层继承就是父类被子类1继承,然后子类1(父类)被子类2继承

示例:

# 定义第一个父类
class Master(object):
    def __init__(self):
        self.kongfu = '一剑仙人跪'
        # self.name = '李淳罡'

    def battle(self):
        print(f'运用了{self.kongfu}和敌人battle')


# 定义第二个父类
class Maid(object):
    def __init__(self):
        self.kongfu = '霸王卸甲'
        self.name = '青鸟'

    def battle(self):
        print(f'运用了{self.kongfu}和敌人battle')

    def aaa(self):
        print('这是侍女类的aaa方法')


# 定义子类
class Prentice(Master, Maid):
    def __init__(self):
        self.kongfu = '剑气滚龙壁'

    def battle(self):
        self.__init__()
        print(f'运用了{self.kongfu}和敌人battle')

    # 把父类的同名方法和属性再次封装就可以了
    def master_battle(self):
        # 父类名.方法名(self)
        Master.__init__(self)
        Master.battle(self)
        # Master().battle()  # 不推荐使用


class Daughter(Prentice):
    pass


xiaodigua = Daughter()
print(xiaodigua.kongfu)
xiaodigua.battle()
xiaodigua.master_battle()

3、super()方法

使用super()方法可以自动查找父类,调用的顺序遵循__mro__类属性的顺序,比较适合单继承使用

注意:如果继承了多个父类,且父类有同名方法和属性,则默认只执行第一个父类的同名方法和属性(且同名方法只执行一次,目前super不支持多个父类的同名方法).

示例:

# 定义第一个父类
class Master(object):
    def __init__(self):
        self.kongfu = '一剑仙人跪'
        # self.name = '李淳罡'

    def battle(self):
        print(f'运用了{self.kongfu}和敌人battle')


# 定义第二个父类
class Maid(Master):
    def __init__(self):
        self.kongfu = '霸王卸甲'
        self.name = '青鸟'

    def battle(self):
        print(f'运用了{self.kongfu}和敌人battle')

    def aaa(self):
        print('这是侍女类的aaa方法')

    def bbb(self):
        super().__init__()
        super().battle()

# 定义子类
class Prentice(Maid):
    def __init__(self):
        self.kongfu = '剑气滚龙壁'

    def battle(self):
        self.__init__()
        print(f'运用了{self.kongfu}和敌人battle')

    # 把父类的同名方法和属性再次封装就可以了
    def master_battle(self):
        # 父类名.方法名(self)
        Master.__init__(self)  # 如果定义的类名修改,那么这个里面的代码也要修改
        Master.battle(self)

    def old_battle(self):
        # 方案一  super().方法()
        # super().__init__()
        # super().battle()

        # 方案二  super(类名,self).方法()
        super(Maid, self).__init__()
        super(Maid, self).battle()


xiaoxu = Prentice()
xiaoxu.old_battle()
print(Prentice.__mro__)
xiaoxu.battle()
xiaoxu.bbb()

4、私有属性

4.1?定义私有属性和方法

在Python中,可以为实例方法和属性设置私有权限,即设置某个实例属性和实例方法不继承给子类。

设置私有属性和私有方法的语法是:在属性和方法前面加上两个下划线。

示例:

# 定义父类
class Master(object):
    def __init__(self):
        self.kongfu = '一剑仙人跪'
        self.__name = '李淳罡'

    def battle(self):
        print(f'运用了{self.kongfu}和敌人battle')

    def __print_info(self):
        print(self.__name)


# 定义子类
class Prentice(Master):
    pass


# 用子类创建对象,调用父类的属性和方法
xiaoxu = Prentice()
# print(xiaoxu.__name)
# xiaoxu.print_info()
# laoli = Master()
# print(laoli.__name)
# xiaoxu.__print_info()
# laoli.__print_info()

总结:对象不能访问私有属性和私有方法,子类无法继承父类的私有属性和私有方法。

8.2 获取和修改私有属性值

在Python中,一般定义方法名get_xxxx用来表示获取私有属性,定义set_xxxxx用来表示修改私有属性值,这是约定俗称的命名方法,不是强制要求。

示例:

# 定义父类
class Master(object):
    def __init__(self):
        self.kongfu = '一剑仙人跪'
        self.__name = '李淳罡'

    def battle(self):
        print(f'运用了{self.kongfu}和敌人battle')

    def get_name(self):
        return self.__name

    def set_name(self):
        self.__name = '老徐'


# 定义子类
class Prentice(Master):
    pass


# 用子类创建对象,调用父类的属性和方法
xiaoxu = Prentice()
print(xiaoxu.get_name())
xiaoxu.set_name()
print(xiaoxu.get_name())

总结:

继承的特点:

子类默认拥有父类的所有属性和方法,除了私有属性和私有方法。

5、多态

5.1了解多态

多态指的是一类事物有多

多态指的是一类事物有多种形态(一个抽象类有多个子类,因而多态的概念依赖于继承)

  • 定义:多态是一种使用对象的方式,子类重写父类方法,调用不同的子类对象的同一父类方法时,产生不同的对象。

  • 好处:调用灵活,有了多态,更加容易编写出来通用的代码,做出通用的编程,以适应不同的需求。

  • 实现步骤:

    • 定义父类,并提供公共方法

    • 定义子类,并重写父类方法

    • 传递子类对象给调用者,可以看到不同的子类的执行结果。

5.2?体验多态

示例:

# 需求:狗有很多种,有抓坏人的  有找毒品的   警察带不同狗工作可以做不同的事
# 定义父类
class Dog(object):
    def work(self):
        pass


# 定义子类
class ArmyDog(Dog):
    def work(self):
        print('抓坏人,小偷')


class DrugDog(Dog):
    def work(self):
        print('找毒品')


class Person(object):
    def work_with_dog(self, dog):
        dog.work()


# 创建对象,实现不同的功能,传入不同的对象,观察执行结果
ad = ArmyDog()
dd = DrugDog()

xiaofu = Person()
xiaofu.work_with_dog(ad)
xiaofu.work_with_dog(dd)

6、类属性和实例属性

6.1 类属性

6.1.1 设置和访问类属性

  • 类属性就是类对象所拥有的属性,他被该类的所有对象所共有

  • 类属性可以使用类对象或者实例对象访问

示例:

class Wife(object):
    gender = '女'  # 类属性

    def __init__(self, name, age):
        self.name = name   # 实例属性
        self.age = age

    def print_info(self):
        print(self.name)
        print(self.age)


xiaoxu = Wife('张磊', 18)
# xiaoxu.print_info()

xiaoxu1 = Wife('张磊2', 30)
# xiaoxu1.print_info()

# print(xiaoxu1.gender)  # 实例对象访问类属性
# print(xiaoxu.gender)

# print(Wife.gender)  # 类对象访问类属性
# # id地址一样
# print(id(xiaoxu1.gender))
# print(id(xiaoxu.gender))
# # id地址不一样
print(id(xiaoxu1.name))
print(id(xiaoxu.name))

总结:

  • 记录的某项数据始终保持一致的时候,则可以定义类属性

  • 实例属性要求每一个对象为其开辟一份独立的内存空间记录属性值,而类属性为全局所共有,仅占用一份内存空间,更加的节省资源。

6.1.2?修改类属性

类属性只能通过类对象来修改,不能通过实例对象来修改,如果这样操作了,只是重新为此实例对象重新添加了一个实例属性而已。

示例:

class Wife(object):
    gender = '女'  # 类属性

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def print_info(self):
        print(self.name)
        print(self.age)


xiaozhang = Wife('张磊', 18)
xiaozhang1 = Wife('张磊1', 30)

# 通过类对象修改类属性
# print(Wife.gender)
# Wife.gender = '中性'
# print(Wife.gender)
# print(xiaozhang.gender)
# print(xiaozhang1.gender)

# 不能通过实例对象修改类属性
xiaozhang.gender = '中性'
print(Wife.gender)
print(xiaozhang.gender)
print(xiaozhang1.gender)

文章来源:https://blog.csdn.net/m0_73527543/article/details/135309058
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。