Python: 学习系列之五:类、继承、多态、封装

系列

class A(object):
    # 类属性
    name = 'cong'

    # 类方法
    @classmethod
    def cm(cls, p1):
        print(p1)

    # 构造函数
    def __init__(self, n):
        # 定义实例对象属性并赋值
        self.age = 20
        # 定义实例对象的私有属性,双下划线开头表示私有访问,外部访问不到
        self.__city = 'shanghai'
        A.name = n  # 给类对象属性赋值

    # 静态方法
    @staticmethod
    def sm(p1, p2):
        print(p1, p2)

    # 实例方法
    def do_something(self):
        print('hello')

    # 定义实例对象的私有方法,双下划线开头表示私有访问,外部访问不到
    def __set_city(self, city):
        self.__city = city

    # 对属性进行的封装
    def get_city(self):
        print('he is from %s' % self.__city)


a = A('congcong')
print(A.name)  # cong,使用类对象调用
print(a.name)  # cong,当使用实例去调的时候,实际指向类对象的引用
print(a.age)  # 20

A.cm('a')  # 类对象调用类方法
a.cm('a')  # 实例对象调用类方法

A.sm('a', 'b')  # 类对象调用静态方法
a.sm('a', 'b')  # 实例对象调用静态方法

a.do_something()  # 使用实例去调用函数

# ---------------在外部设置新的属性-------------------------
A.sex = 'Male'  # 在类的外部定义新的类属性
a.birthday = '2019-6-16'  # 在类的外部定义新的实例属性

print(A.sex)
print(a.sex)
print(a.birthday)


# ---------------在外部设置新的方法-------------------------
# 在外部,定义一个函数作为实例方法
def newF1(self):
    print('this is external method 1')


# 第一种方法,给类对象设置此实例方法
A.newF1 = newF1
a.newF1()

# 第二种方法,行不通,给实例对象设置此实例方法
# a.newF1 = newF1 # 不能这样设置,会报TypeError: newF1() missing 1 required positional argument: 'self'

# 第三种办法,动态绑定实例方法
from types import MethodType

a.newF1 = MethodType(newF1, a)
a.newF1()

继承、重写,MRO

"""
    Python所有的类都继承一个统一的基类object
    Python子类可以继承多个父类,这是与JAVA/C# 最大的不同,子类会继续所有直接父类和间接父类的所有方法和属性,包括类方法,静态方法等
    如果两个父类中有两个相同的方法,Python是通过MRO(Method Resolution Order方法解析顺序)来解决的
"""


# A是根父类
class A(object):
    def f(self):
        print('A.f')


# B继承于A
class B(A):
    # 如果对继承于父类的访问不满意,可以对此方法进行重写,重写的方式是:在子类中定义与父类中同名的属性或方法(包括装饰器)
    def f(self):
        print('B.f')


# C继承于A
class C(A):
    def f(self):
        print('C.f')


# D继承于两个父类B和C
class D(B, C):
    def f(self):
        # 可以通过super()来调用父类的方法
        super().f()  # B.f
        super(D, self).f()  # B.f, super的第一个参数是类对象,第二个参数是实例对象
        # 根据D的MRO顺序是D->B->C->A,那如果想改这个顺序呢
        super(B, self).f()  # C.f, 以B的下一个类对象作为被指定的父类
        super(C, self).f()  # A.f


d = D()
d.f()  # B.f 如果两个父类中有两个相同的方法,Python是通过MRO来解决的

# 通过调用类对象上的mro()方法,可以查看到解析顺序
# [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
print(D.mro())

多态

"""
    多态性意味着有多重形式。在面向对象编程范式中,多态性往往表现为"一个接口,多个功能"
    具体主要使用方法是在父类中定义了一个方法,在不同的子类中对此方法进行重写,在运行过程中根据变量所引用对象的类型,动态地决定调用哪个对象中的方法

"""


class ParentClass(object):
    def f(self):
        print('ParentClass.f')


class ChildClass1(ParentClass):
    def f(self):
        print('ChildClass1.f')


class ChildClass2(ParentClass):
    def f(self):
        print('ChildClass2.f')


def exec(obj):
    obj.f()


"""
    在JAVA/C#中,调用于必须用
    ParentClass p = new ParentClass(); p.f();
    ParentClass p = new ChildClass1(); p.f();
    ParentClass p = new ChildClass2(); p.f();
    这种方法来明确指定p的类型后,才能调用f方法,但在Python中不必要这样
    Python是动态语言,它崇尚"鸭子类型":当看到一只鸟走起来像鸭子,游泳起来像鸭子,叫起来像鸭子,那这只鸟就是鸭子,而在JAVA/C#中必须先明确知道对象的类型是什么,然后才会执行对应的方法
    在鸭子类型中,我们并不关心对象的类型是什么,到底是不是鸭子,只关心对象的行为,代码如下

"""
a = ParentClass()
exec(a)  # ParentClass.f
a = ChildClass1()
exec(a)  # ChildClass1.f
a = ChildClass2()
exec(a)  # ChildClass2.f

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值