python中的封装继承多态_Python面向对象中的继承、多态和封装

从某处调用封装的内容

调用被封装的内容时,有两种方式:① 通过对象直接调用 ② 通过self间接调用通过对象直接调用class MyClass:

def __init__(self, name, age):

self.name = name

self.age = age

obj = MyClass("oldniu", 20)

print(obj.name) # 通过obj对象直接调用里面的name属性

print(obj.age) # 通过obj对象直接调用里面的age属性

通过self间接调用class MyClass:

def __init__(self, name, age):

self.name = name

self.age = age

def func(self):

print(self.name) # 使用self间接调用obj对象中的name属性

print(self.age) # 使用self间接调用obj对象中的age属性

obj = MyClass("oldniu", 20)

obj.func() # 对象执行方法时Python会默认将obj传给参数self

综上所述,对于面向对象广义上的封装来说,其实就是使用初始化方法将内容封装到 对象 中,然后通过对象直接或者self间接获取被封装的内容。

我们再看狭义上的封装私有静态属性class MyClass:

__gender = "男" # 私有静态属性

def __init__(self, name, age):

self.name = name

self.age = age

def get_gender(self):

return self.__gender # 在类的内部可以访问私有静态属性

# print(MyClass.__gender) # 类名不能直接访问私有静态属性

obj = MyClass("oldniu", 20)

# print(obj.__gneder) # 对象不能访问私有静态属性

print(obj.get_gender()) # 男

对于私有静态字段来说,只能在本类中内部访问,类的外部,子类均不可访问。

tips:其实在类的外部可以通过使用_MyClass__gender访问私有静态属性,但是一般我们不会去使用。

私有方法class MyClass:

def __init__(self, name, age):

self.name = name

self.age = age

def __func(self):

print("666666")

def func(self):

self.__func() 类内部访问静态方法

obj = MyClass("dogfa", 20)

obj.func()

# 私有方法和私有静态字段一样,只能在本类中内部访问,类的外部和子类均不课访问。

三、继承

什么是继承?⼦类可以⾃动拥有⽗类中除了私有属性外的其他所有内容就是继承。继承的优点提高代码的复用性

提高代码的维护性

使类与类之间发生关联

继承的分类单继承

多继承

我们先来看单继承类名,对象执行父类方法# 定义一个Animal父类

class Animal:

type_name = "动物类"

def __init__(self, name):

self.name = name

def eat(self):

print("吃吃吃...")

# 继承于Animal类

class Dog(Animal):

pass

# 类名调用父类的属性和方法

print(Dog.type_name)

Dog.eat(111)

# 对象调用父类的属性和方法

dog = Dog("二哈") # 调用父类的__init__方法实例化对象

print(dog.name)

print(dog.type_name)

dog.eat()

print(dog.__dict__)

执行顺序实例化对象时必须执行__init__方法,类中没有,从父类找,父类没有,从object类中找。

先要执行自己类中的eat方法,自己类没有才能执行父类中的方法。

同时执行类及父类方法

方法一:

如果想执行父类的func方法,这个方法并且子类中夜用,那么就在子类的方法中写上:

父类.func(对象,其他参数)class Animal:

type_name = "动物类"

def __init__(self, name, age, gender):

self.name = name

self.age = age

self.gender = gender

def eat(self):

print("吃吃吃...")

class Bird(Animal):

def __init__(self, name, age, gender, wing):

Animal.__init__(self, name, age, gender) # 执行了父类的__init__方法进行初始化

self.wing = wing # 给对象封装wing属性

obj = Bird("鹦鹉", 3, "雌", "翅膀")

print(obj.__dict__)

# {'name': '鹦鹉', 'age': 3, 'gender': '雌', 'wing': '翅膀'}

方法二:

利用super,super().func(参数)class Animal:

type_name = "动物类"

def __init__(self, name, age, gender):

self.name = name

self.age = age

self.gender = gender

def eat(self):

print("吃吃吃...")

class Bird(Animal):

def __init__(self, name, age, gender, wing):

super().__init__(name, age, gender) # 使用super会自动将self传给父类

self.wing = wing # 给对象封装wing属性

obj = Bird("鹦鹉", 3, "雌", "翅膀")

print(obj.__dict__)

# {'name': '鹦鹉', 'age': 3, 'gender': '雌', 'wing': '翅膀'}

再来看看多继承

在多继承中要补充一点,在这里要注意类的种类。类可以分为经典类和新式类。

新式类:继承object类的类称为新式类。在Python3中默认都是继承object类,所以默认所有类都是新式类。

经典类:不继承object类的类称为经典类。在Python2中默认使用经典类,当然也可以自己手动继承object类来达到变成经典类的目的。经典类的多继承

在Python的继承体系中, 我们可以把类与类继承关系化成⼀个树形结构的图。class A:

pass

class B(A):

pass

class C(A):

pass

class D(B, C):

pass

class E:

pass

class F(D, E):

pass

class G(F, D):

pass

class H:

pass

class Foo(H, G):

pass

对付这种mro画图就可以:

wAAACwAAAAAAQABAEACAkQBADs=

继承关系图已经有了,那如何进⾏查找呢? 记住⼀个原则, 在经典类中采⽤的是深度优先遍历⽅案。 什么是深度优先,就是⼀条路走到头, 然后再回来, 继续找下⼀个。

类的MRO: Foo-> H -> G -> F -> E -> D -> B -> A -> C

新式类的继承mro序列

MRO是一个有序列表L,在类被创建时就计算出来。

通用计算公式为:mro(Child(Base1,Base2)) = [ Child ] + merge( mro(Base1), mro(Base2), [ Base1, Base2] )

(其中Child继承自Base1, Base2)

如果继承至一个基类:class B(A)

这时B的mro序列为mro( B ) = mro( B(A) )

= [B] + merge( mro(A) + [A] )

= [B] + merge( [A] + [A] )

= [B,A]

如果继承至多个基类:class B(A1, A2, A3 …)

这时B的mro序列mro(B) = mro( B(A1, A2, A3 …) )

= [B] + merge( mro(A1), mro(A2), mro(A3) ..., [A1, A2, A3] )

= ...

计算结果为列表,列表中至少有一个元素即类自己,如上述示例[A1,A2,A3]。merge操作是C3算法的核心。

表头和表位

表头:

列表的第一个元素

表尾:

列表中表头以外的元素集合(可以为空)

示例

列表:[A, B, C]

表头是A,表尾是B和C

列表之间的+操作

+操作:

[A] + [B] = [A, B]

(以下的计算中默认省略)

———————

merge操作示例:如计算merge( [E,O], [C,E,F,O], [C] )

有三个列表 : ① ② ③

1 merge不为空,取出第一个列表列表①的表头E,进行判断

各个列表的表尾分别是[O], [E,F,O],E在这些表尾的集合中,因而跳过当前当前列表

2 取出列表②的表头C,进行判断

C不在各个列表的集合中,因而将C拿出到merge外,并从所有表头删除

merge( [E,O], [C,E,F,O], [C]) = [C] + merge( [E,O], [E,F,O] )

3 进行下一次新的merge操作 ......

---------------------

wAAACwAAAAAAQABAEACAkQBADs=

计算mro(A)方式:mro(A) = mro( A(B,C) )

原式= [A] + merge( mro(B),mro(C),[B,C] )

mro(B) = mro( B(D,E) )

= [B] + merge( mro(D), mro(E), [D,E] ) # 多继承

= [B] + merge( [D,O] , [E,O] , [D,E] ) # 单继承mro(D(O))=[D,O]

= [B,D] + merge( [O] , [E,O] , [E] ) # 拿出并删除D

= [B,D,E] + merge([O] , [O])

= [B,D,E,O]

mro(C) = mro( C(E,F) )

= [C] + merge( mro(E), mro(F), [E,F] )

= [C] + merge( [E,O] , [F,O] , [E,F] )

= [C,E] + merge( [O] , [F,O] , [F] ) # 跳过O,拿出并删除

= [C,E,F] + merge([O] , [O])

= [C,E,F,O]

原式= [A] + merge( [B,D,E,O], [C,E,F,O], [B,C])

= [A,B] + merge( [D,E,O], [C,E,F,O], [C])

= [A,B,D] + merge( [E,O], [C,E,F,O], [C]) # 跳过E

= [A,B,D,C] + merge([E,O], [E,F,O])

= [A,B,D,C,E] + merge([O], [F,O]) # 跳过O

= [A,B,D,C,E,F] + merge([O], [O])

= [A,B,D,C,E,F,O]

---------------------

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值