python基础学习20_面向对象之【多态】(包含多态、类属性与实例属性、类方法与实例方法)

# -*- encoding: utf-8 -*-
"""
面向对象之多态

1、多态:一类事物有多种形态(最好依赖于继承,但不必须)
   1.1、定义:多态是一种使用对象的方式,子类重写父类中的方法,调用不同子类对象的相同父类方法,可以产生不同的执行结果。
   1.2、优点:调用灵活,更容易编写出通用的代码
2、类属性和实例属性
   2.1、类属性:类对象拥有的属性,被该类所有实例对象所共有
        2.1.1、使用场景:记录某项指标,如果数据始终保持一致使用类属性
        2.1.2、优点:仅占一份内存,更加节省内存空间
        2.2.3、访问:可以通过 类对象 或者 实例对象 访问
                     类对象.类属性
                     实例对象.类属性
        2.2.4、修改:只能通过类对象修改,不能通过实例对象修改。
                    若通过实例对象修改类属性,实则表示创建了一个实例属性。
   2.2、实例属性:每个实例对象的同一实例属性不同
        2.2.1、访问:仅能通过实例对象访问,不能通过类对象访问
        2.2.2、缺点:实例属性要求每个对象为其单独开辟一份内存空间来记录数据。
                    即不同实例对象的实例属性各占一份内存空间。
3、类方法和静态方法
   3.1、类方法:
        3.1.1、特点:被修饰器@classmethod修饰,第一个参数必须是类对象,一般以cls作为第一个参数
        3.1.2、使用场景:类方法一般与类属性配合使用
                        当方法中需要访问类对象(如需要访问私有属性)时,定义类方法
   3.2、静态方法:
        3.2.1、特点:被修饰器@staticmethod修饰,既不需要传入类对象,也不需要传入实例对象
                    (形参没有self/cls)
        3.2.2、使用场景:取消不必要的参数传递,减少不必要的内存占用和性能消耗
4、类方法、静态方法、实例方法三者的区别
   4.1、调用:类方法和静态方法能被类对象和实例对象直接调用;实例方法可以被实例对象调用,但是不能被类对象调用
   4.2、结果:实例方法随着实例属性的变化而变化;
             类方法中都是类属性,始终不变
             静态方法中可以通过类对象.类属性访问类属性
"""

'''
(一)多态实现步骤
1、定义父类,提供公共方法
2、定义子类,重写父类方法
3、传递子类对象给调用者,可以看到不同子类对象,执行效果不同
'''

# 定义父类Dog
class Dog(object):
    def work(self):
        print('指哪打哪')

# 定义子类TrackerDog,重写父类Dog中的work方法
class TrackerDog(Dog):
    def work(self):
        print('追击犯人!')

# 定义子类DrugDog,重写父类Dog中的work方法
class DrugDog(Dog):
    def work(self):
        print('追击毒品!')


class Human(object):
    # 传入对象dog,对象不同,执行的work函数不同
    def work(self,dog):
        dog.work()


td = TrackerDog()
dd = DrugDog()

zhangsan = Human()
# 传入不同的对象 td/dd,得到不同的结果
zhangsan.work(td)  # 追击犯人!
zhangsan.work(dd)  # 追击毒品!


# (二)、类属性和实例属性
# 1、类属性
class Dog(object):
    # 定义类属性
    tooth = 10

# 创建实例对象
d1 = Dog()
d2 = Dog()

# 通过类对象访问类属性
print(Dog.tooth)  # 10

# 通过实例对象访问类属性
print(d1.tooth)  # 10
print(d2.tooth)  # 10
# 类对象拥有的属性,被该类所有实例对象所共有

# ***通过类对象修改类属性***
Dog.tooth = 20

# 通过类对象访问类属性
print(Dog.tooth)  # 20

# 通过实例对象访问类属性
print(d1.tooth)  # 20
print(d2.tooth)  # 20


# ***通过实例对象修改类属性***
d1.tooth = 8

# 通过类对象访问类属性
print(Dog.tooth)  # 20

# 通过实例对象访问类属性
print(d1.tooth)  # 8
print(d2.tooth)  # 20

# ***可以看出并不能通过实例对象来修改类属性!!!只是实例对象为自己创造了一个与类属性同名的实例属性!!!

# 2、实例属性
class Dog(object):
    def __init__(self):
        # 定义实例属性
        self.age = 6
    # 定义实例方法
    def print_age(self):
        print(f'狗子今年{age}岁')


d1 = Dog()
# 通过实例对象访问实例属性
print(d1.age)  # 6
# 通过类对象访问实例属性
# print(Dog.age)  # AttributeError: type object 'Dog' has no attribute 'age'


# (三)、类方法和静态方法

class Dog(object):
    __age = 11
    # 定义类方法
    @ classmethod
    def get_info(cls):
        # cls 指代Dog类对象
        return cls.__age
    # 定义静态方法
    @staticmethod
    def print_info():
        print('这是一只静态狗')
        print(Dog.__age)
    # 定义实例方法
    def run(self):
        print('狗会跑')


d1 = Dog()
# 类方法可以被实例对象调用
print(d1.get_info())  # 11
# 类方法可以被类对象调用
print(Dog.get_info())  # 11


# 静态方法可以被实例对象调用
print(d1.print_info())  # 这是一只静态狗  # 11
# 静态方法可以被类对象调用
print(Dog.print_info())  # 这是一只静态狗  # 11


# 实例方法可以被实例对象调用
print(d1.run())  # 狗会跑
# 实例方法不可以被类对象直接调用,需要在调用时传入实例对象
# print(Dog.run())  # TypeError: run() missing 1 required positional argument: 'self'
print(Dog.run(d1))  # 狗会跑
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值