本篇介绍面向对象编程的( 封装、多态 )相关知识点,一起学习,共同进步
Python专栏请参考
:人生苦短-我学python面向对象三大特性:封装、继承、多态
class Master(object):
def __init__(self):
self.kongfu = "古法煎饼果子配方"
def make_cake(self):
print("[古法] 按照 <%s> 制作了一份煎饼果子..." % self.kongfu)
class School(object):
def __init__(self):
self.kongfu = "现代煎饼果子配方"
def make_cake(self):
print("[现代] 按照 <%s> 制作了一份煎饼果子..." % self.kongfu)
class Prentice(School, Master):
def __init__(self):
self.kongfu = "猫氏煎饼果子配方"
# 私有属性,可以在类内部通过self调用,但不能通过对象访问
self.__money = 10000
# 私有方法,可以在类内部通过self调用,但不能通过对象访问
def __print_info(self):
print(self.kongfu)
print(self.__money)
def make_cake(self):
self.__init__()
print("[猫氏] 按照 <%s> 制作了一份煎饼果子..." % self.kongfu)
def make_old_cake(self):
Master.__init__(self)
Master.make_cake(self)
def make_new_cake(self):
School.__init__(self)
School.make_cake(self)
class PrenticePrentice(Prentice):
pass
damao = Prentice()
# 对象不能访问私有权限的属性和方法
# print(damao.__money)
# damao.__print_info()
pp = PrenticePrentice()
# 子类不能继承父类私有权限的属性和方法
print(pp.__money)
pp.__print_info()
Traceback (most recent call last):
File "D:/Phython/study/venv/Include/hello.py", line 47, in <module>
print(damao.__money)
AttributeError: 'Prentice' object has no attribute '__money'
对象名.属性名 = 数据 ----> 直接修改
对象名.方法名() ----> 间接修改
class Master(object):
def __init__(self):
self.kongfu = "古法煎饼果子配方"
def make_cake(self):
print("[古法] 按照 <%s> 制作了一份煎饼果子..." % self.kongfu)
class School(object):
def __init__(self):
self.kongfu = "现代煎饼果子配方"
def make_cake(self):
print("[现代] 按照 <%s> 制作了一份煎饼果子..." % self.kongfu)
class Prentice(School, Master):
def __init__(self):
self.kongfu = "猫氏煎饼果子配方"
# 私有属性,可以在类内部通过self调用,但不能通过对象访问
self.__money = 10000
# 现代软件开发中,通常会定义get_xxx()方法和set_xxx()方法来获取和修改私有属性值。
# 返回私有属性的值
def get_money(self):
return self.__money
# 接收参数,修改私有属性的值
def set_money(self, num):
self.__money = num
def make_cake(self):
self.__init__()
print("[猫氏] 按照 <%s> 制作了一份煎饼果子..." % self.kongfu)
def make_old_cake(self):
Master.__init__(self)
Master.make_cake(self)
def make_new_cake(self):
School.__init__(self)
School.make_cake(self)
class PrenticePrentice(Prentice):
pass
damao = Prentice()
# 对象不能访问私有权限的属性和方法
# print(damao.__money)
# damao.__print_info()
# 可以通过访问公有方法set_money()来修改私有属性的值
damao.set_money(100)
# 可以通过访问公有方法get_money()来获取私有属性的值
print(damao.get_money())
100
所谓多态:定义时的类型和运行时的类型不一样,此时就成为多态 ,多态的概念是应用于Java和C#这一类强类型语言中,而Python崇尚“鸭子类型”。
鸭子类型:虽然我想要一只"鸭子",但是你给了我一只鸟。 但是只要这只鸟走路像鸭子,叫起来像鸭子,游泳也像鸭子,我就认为这是鸭子。
Python的多态,就是弱化类型,重点在于对象参数是否有指定的属性和方法,如果有就认定合适,而不关心对象的类型是否正确。
Python “鸭子类型”
class F1(object):
def show(self):
print('F1.show')
class S1(F1):
def show(self):
print('S1.show')
class S2(F1):
def show(self):
print('S2.show')
# 由于在Java或C#中定义函数参数时,必须指定参数的类型
# 为了让Func函数既可以执行S1对象的show方法,又可以执行S2对象的show方法,
# 所以在def Func的形参中obj的类型是 S1和S2的父类即F1
#
# 而实际传入的参数是:S1对象和S2对象
def Func(obj):
# python是弱类型,即无论传递过来的是什么,obj变量都能够指向它,这也就没有所谓的多态了(弱化了这个概念)
obj.show()
s1_obj = S1()
Func(s1_obj) # 在Func函数中传入S1类的对象 s1_obj,执行 S1 的show方法,结果:S1.show
s2_obj = S2()
Func(s2_obj) # 在Func函数中传入Ss类的对象 ss_obj,执行 Ss 的show方法,结果:S2.show
S1.show
S2.show
通俗点理解:定义obj这个变量是说的类型是:F1的类型,但是在真正调用Func函数时给其传递的不一定是F1类的实例对象,有可能是其子类的实例对象,
这种情况就是所谓的多态
多态:不同的子类对象,调用相同的父类方法,产生不同的结果
案例如下
# 多态:同一种事物的多种形态,动物分为人类,猪类(在定义角度)
class Animal:
def run(self):
raise AttributeError('子类必须实现这个方法')
class People(Animal):
def run(self):
print('人正在走')
class Pig(Animal):
def run(self):
print('pig is walking')
class Dog(Animal):
def run(self):
print('dog is running')
peo = People()
pig = Pig()
d = Dog()
peo.run()
pig.run()
d.run()
人正在走
pig is walking
dog is running
1.增加了程序的灵活性
2.增加了程序额可扩展性
class People(object):
name = 'Tom' # 公有的类属性
__age = 12 # 私有的类属性
p = People()
print(p.name) # 正确
print(People.name) # 正确
print(p.__age) # 错误,不能在类外通过实例对象访问私有的类属性
print(People.__age) # 错误,不能在类外通过类对象访问私有的类属性
class People(object):
address = '山东' # 类属性
def __init__(self):
self.name = 'xiaowang' # 实例属性
self.age = 20 # 实例属性
p = People()
p.age = 12 # 实例属性
print(p.address) # 正确
print(p.name) # 正确
print(p.age) # 正确
print(People.address) # 正确
print(People.name) # 错误
print(People.age) # 错误
山东
xiaowang
12
山东
Traceback (most recent call last):
File "D:/Phython/study/venv/Include/hello.py", line 14, in <module>
print(People.name) # 错误
AttributeError: type object 'People' has no attribute 'name'
class People(object):
country = 'china' #类属性
print(People.country)
p = People()
print(p.country)
p.country = 'japan'
print(p.country) # 实例属性会屏蔽掉同名的类属性
print(People.country)
del p.country # 删除实例属性
print(p.country)
china
china
japan
china
china
class People(object):
country = 'china'
#类方法,用classmethod来进行修饰
@classmethod
def get_country(cls):
return cls.country
p = People()
print(p.get_country()) #可以用过实例对象引用
print(People.get_country()) #可以通过类对象引用
china
china
class People(object):
country = 'china'
#类方法,用classmethod来进行修饰
@classmethod
def get_country(cls):
return cls.country
@classmethod
def set_country(cls,country):
cls.country = country
p = People()
print(p.get_country()) #可以用过实例对象访问
print(People.get_country()) #可以通过类访问
p.set_country("japan")
print(p.get_country())
print(People.get_country())
运行结果
china
china
japan
japan
class People(object):
country = 'china'
@staticmethod
#静态方法
def get_country():
return People.country
p = People()
# 通过对象访问静态方法
print(p.get_country())
# 通过类访问静态方法
print(People.get_country())
china
china
通过cls引用的必定是类对象的属性和方法
;过self引用的可能是类属性、也有可能是实例属性(这个需要具体分析)
,不过在存在相同名称的类属性和实例属性的情况下,实例属性优先级更高。The best investment is in yourself
2020.04.05 记录辰兮的第48篇博客