一、封装
1.类变量为该类全体实例对象所共有。
2.
外部代码可以直接调用实例变量来操作数据
bart = Student("Bart Simpson", 59)
bart.score = 99
实例的变量名以__开头,声明为“私有属性”。而私有属性是无法通过实例对象直接访问的。那么如果想要访问并修改私有属性,就需要实例对象通过获取和设置函数来操作。
那如果我们想要以访问并改变实例对象的公有属性的方式来访问和改变其私有属性呢?
此时可以分别使用@property 装饰器装饰获取函数,@私有属性名.setter 装饰器装饰设置函数(注:两者函数名均为私有属性名)。
class Rect:
def __init__(self,area):
self.__area = area
@property
def area(self):
return self.__area
rect = Rect(30)
#直接通过方法名来访问 area 方法
print("矩形的面积是:",rect.area)
矩形的面积为: 30
@area.setter
def area(self, value):
self.__area = value
rect.area = 90
print("修改后的面积:",rect.area)
修改后的面积: 90
这样,area 属性就有了 getter 和 setter 方法,该属性就变成了具有读写功能的属性。
2.获取对象信息:
hasattr(object,attr):判断有无该属性
getattr(object,'attr'):获取该属性的值
二、继承,多重继承:
1.super()继承特性?
super() 函数是用于调用父类(超类)的一个方法。
super() 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,但是如果使用多继承,会涉及到查找顺序(MRO)、重复调用(钻石继承)等种种问题。
注:Python3.x 和 Python2.x 的一个区别是: Python 3 可以使用直接使用 super().xxx 代替 super(Class, self).xxx
class FooParent(object):
def __init__(self):
self.parent = 'I\'m the parent.'
print ('Parent')
def bar(self,message):
print ("%s from Parent" % message)
class FooChild(FooParent):
def __init__(self):
# super(FooChild,self) 首先找到 FooChild 的父类(就是类 FooParent),然后把类 FooChild 的对象转换为类 FooParent 的对象
super(FooChild,self).__init__()
print ('Child')
def bar(self,message):
super(FooChild, self).bar(message)
print ('Child bar fuction')
print (self.parent)
if __name__ == '__main__':
fooChild = FooChild()
fooChild.bar('HelloWorld')
相当于通过super方法自动地通过MRO来找到父类从而继承。
2.多重继承:对于支持继承的编程语言来说,其方法(属性)可能定义在当前类,也可能来自于基类,所以在方法调用时就需要对当前类和基类进行搜索以确定方法所在的位置。而搜索的顺序就是所谓的「方法解析顺序」(Method Resolution Order,或MRO)。
MRO 是把类的继承关系线性化的一个过程,而线性化方式决定了程序运行过程中具体会调用哪个方法。既然如此,那什么样的 MRO 才是最合理的?Python 中又是如何实现的呢?
实质上,按照入度从左到右排列好后,自底向上一层一层地遍历。
具体见此:Python的方法解析顺序(MRO)[转] - morra - 博客园 (cnblogs.com)
三、多态
1.
isinstance(object, classinfo)
如果对象的类型与参数二的类型(classinfo)相同则返回 True,否则返回 False
2. 什么是多态?
2.1:对继承于父类中的方法,有的需要在子类中进行改动以适应子类的情况。
这样就避免了子类又重新声明一个方法,减少了冗余的定义。
那么由定义可知多态的条件:
1.继承:多态一定是发生在子类和父类之间
2.重写:子类重写了父类的方法
比如:
class CLanguage:
def say(self):
print("调用的是 Clanguage 类的say方法")
class CPython(CLanguage):
def say(self):
print("调用的是 CPython 类的say方法")
class CLinux(CLanguage):
def say(self):
print("调用的是 CLinux 类的say方法")
a = CLanguage()
a.say()
a = CPython()
a.say()
a = CLinux()
a.say()
3. “鸭子”设计模式:一种由多态衍生出的更灵活的编程机制
好处是什么?虽然通过多态实例对象可以调用其对应的具有多态性的方法,但如果我想要访问父类中的方法怎么办?难道又声明一个父类对象?这样做显得很麻烦。
而通过鸭子设计模式,我们将所有具有多态性的方法都放在一个类里面(我一般习惯性取名为DuckDesign),然后通过新增的参数去调用这个方法。
如:
class WhoSay:
def say(self,who):
who.say()
class CLanguage:
def say(self):
print("调用的是 Clanguage 类的say方法")
class CPython(CLanguage):
def say(self):
print("调用的是 CPython 类的say方法")
class CLinux(CLanguage):
def say(self):
print("调用的是 CLinux 类的say方法")
a = WhoSay()
#调用 CLanguage 类的 say() 方法
a.say(CLanguage())
#调用 CPython 类的 say() 方法
a.say(CPython())
#调用 CLinux 类的 say() 方法
a.say(CLinux())
四、定制类
1.__getitem__:
即如果对象有类型为字典的属性,那么就可以通过key来访问属性;如果没有,那么也会返回__getitem__的return值
(202条消息) python __getitem__()方法理解_至尊小宝的博客-CSDN博客___getitem__()
__call__:
使类实例对象变为了可调用对象;当执行 类实例对象(参数) 就会调用类中定义的__call__()
__str__:
在print(对象)时会自动调用这个方法:print(对象.__str__(参数))
整个的演示代码在这里:
class GeometricShape:
def __init__(self):
pass
class Two_dim_shape(GeometricShape):
def __init__(self):
super().__init__()
def __str__(self):
return f'the type is {self.__class__}'
def duck_test(self):
print("duck in class Two_dim_shape.")
class Three_dim_shape(GeometricShape):
def __init__(self):
super().__init__()
pass
class Circle(Two_dim_shape):
def __init__(self,center,radius,owner=None):
super().__init__()
self.center=center
self.radius=radius
self.__owner=owner ##声明私有属性
@property
def owner(self):
return self.__owner
@owner.setter
def owner(self,new_owner):
self.__owner=new_owner
def __call__(self,new_center,new_radius):
self.center=new_center
self.radius=new_radius
print(self)
def __str__(self):
return f'the center of the circle is {self.center}, the radius is {self.radius}'
def duck_test(self):
print("duck in class Circle.")
class DuckDesign:
def duck_test(self,who):##具有多态性的方法
who.duck_test()
##封装部分讲解
cir_4=Circle((5,6),7,'wang')
#print(getattr(cir_4,'owner')) ##将会报错 'Circle' object has no attribute 'owner'
print(getattr(cir_4,'owner'))
cir_4.owner='Li'
print(getattr(cir_4,'owner'))
##继承,定制类部分讲解
cir=Circle((3,4),5,'Liu')
print(cir)
cir((4,5),8)
##多态部分讲解
cir_1=Two_dim_shape()
cir_2=Circle((4,5),8)
print(cir_1)
print(cir_2) ##这里检验了__str__方法的多态性;__str__方法在Two_dim_shape和Circle中都有定义,而执行哪个全看实例对象的类型
cir_all=DuckDesign()
cir_all.duck_test(Two_dim_shape())
cir_all.duck_test(Circle((4,5),8))
结果:
wang
Li
the center of the circle is (3, 4), the radius is 5
the center of the circle is (4, 5), the radius is 8
the type is <class '__main__.Two_dim_shape'>
the center of the circle is (4, 5), the radius is 8
duck in class Two_dim_shape.
duck in class Circle.