python基础0305
面向对象
封装
实例本身就拥有数据,要访问这些数据,没必要从外边构造函数去访问,可以直接在类内部定义访问数据的函数。这样就把数据封装起来了。
封装就是将抽象得到的数据和行为(或功能)相结合,形成一个有机的整体(即类);封装的目的是增强安全性和简化编程,使用者不必了解具体的实现细节,而只是要通过外部接口,一特定的访问权限来使用类的成员。
class A:
def __init__(self):
self.val = 0
a = A()
a.val
0
a.val = 3
a.val
3
上例中,封装之后实例属性值依然可以随意更改,并不安全。可以借助property工具固定属性。
@property
class A:
def __init__(self,val):
self.__val = val
@property
def get_val(self):
if self.__val < 0:
return 0
else:
return self.__val
@get_val.setter
def set_val(self,val):
if isinstance(val,(int,float)) and val > 0:
self.__val = val
else:
self.__val = 0
a = A(-1)
a.get_val
0
a.set_val = 20
a.get_val
20
@property 将实例方法变成实例的固定属性,切不能直接修改。
@method.setter将实例的赋值方法变成直接给实例属性赋值。
class A:
def __init__(self):
self.__val = 0
def get_val(self):
if self.__val < 0:
return 0
else:
return self.__val
def set_val(self,val):
self.__val = val
val = property(get_val,set_val)
a = A()
a.val
0
a.val = 30
a.val
30
a.get_val()
30
a.set_val(-2)
a.val
0
type(a.val)
int
type(A.val)
property
dir(property)
['__class__',
'__delattr__',
'deleter',
'fdel',
'fget',
'fset',
'getter',
'setter']
help("property")
class property(object)
| property(fget=None, fset=None, fdel=None, doc=None) -> property attribute
...
继承
面向对象的编程带来的好处之一是代码重用,实现重用的方式之一就是通过继承机制。继承完全可以理解成类之间的类型和子类型关系。
class door:
def __init__(self,number,status):
self.number = number
self.status = status
def open(self):
self.status = "OPEN"
def close(self):
self.status = "CLOSE"
class mydoor:
def __init__(self,number,status,is_lock):
self.number = number
self.status = status
self.is_lock = is_lock
def open(self):
if self.status == "OPEN":
print("IS OPEN")
elif self.is_lock:
print("you need the key")
else:
self.status = "OPEN"
def close(self):
if self.status == "OPEN":
self.status = "CLOSE"
else:
print("THE DOOR IS CLOSED")
def lock(self):
if self.status == "CLOSE":
if self.is_lock:
print("DOOR IS LOCK")
else:
self.is_lock = True
else:
print("place close the door first")
不使用继承需要重新定义一个新类。如果使用继承:
class lockabledoor(door):#door 父类
def __init__(self,number,status,is_lock):
super(lockabledoor,self).__init__(number,status)
self.is_lock = is_lock
def open(self):#重写
if self.is_lock:
print("you need key")
else:
super(lockabledoor,self).open()
def lock(self):
if self.status == "CLOSE":
self.is_lock = True
else:
print("YOU need to close the door")
close 方法可以直接继承自父类,不需重写,实例就可以直接使用。
super函数可以实现在子类中调用父类的方法,子类定义同名方法会覆盖父类同名方法,super函数调用父类实例可以在子类中同时实现父类功能。
更多关于super函数可以参考Python:super函数。
class A:
__class_private_var = 'class private var'
class_public_var = "class pubic var"
def __init__(self):
self.__instance_private_var = 'instance private var'
self.instance_public_var = 'instance public var'
def __instance_private_method(self):
try:
print(self.__class_private_var)
except:
pass
try:
print(self.class_public_var)
except:
pass
try:
print(self.__instance_private_var)
except:
pass
try:
print(self.instance_public_var)
except:
pass
def instance_pubic_method(self):
try:
print(self.__class_private_var)
except:
pass
try:
print(self.class_public_var)
except:
pass
try:
print(self.__instance_private_var)
except:
pass
try:
print(self.instance_public_var)
except:
pass
@classmethod
def __private_class_method(cls):
try:
print(cls.__class_private_var)
except:
pass
try:
print(cls.class_public_var)
except:
pass
@classmethod
def public_class_method(cls):
try:
print(cls.__class_private_var)
except:
pass
try:
print(cls.class_public_var)
except:
pass
class B(A):
pass
b = B()
dir(b)
['_A__class_private_var',
'_A__instance_private_var',
'_A__intance_private_method',
'_A__private_class_method',
'__class__',
'__delattr__',
'__dict__',
'__dir__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__getattribute__',
'__gt__',
'__hash__',
'__init__',
'__le__',
'__lt__',
'__module__',
'__ne__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__',
'__weakref__',
'class_public_var',
'instance_pubic_method',
'instance_pubic_var',
'public_class_method']
b.instance_pubic_method()
class private var
class public var
instance private var
instance public var
b.public_class_method()
class private var
class public var
私有的方法、变量(类和实例)是不可继承的
公有的方法、变量(类和实例)是可继承的
父类公有的方法(类和实例)是可以访问父类的私有变量的
class B(A):
__class_private_var = 'child class private var'
class_public_var = 'child class public var'
def __init__(self):
super(B, self).__init__()
self.__instance_private_var = 'child instance private var'
self.instance_public_var = 'child instance public var'
b = B()
dir(b)
['_A__class_private_var',
'_A__instance_private_method',
'_A__instance_private_var',
'_A__private_class_method',
'_B__class_private_var',
'_B__instance_private_var',
'__class__',
'__delattr__',
'__dict__',
'__dir__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__getattribute__',
'__gt__',
'__hash__',
'__init__',
'__le__',
'__lt__',
'__module__',
'__ne__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__',
'__weakref__',
'class_public_var',
'instance_pubic_method',
'instance_public_var',
'public_class_method']
b.instance_public_method() # 调用父类的方法
class private var # 打印父类的私有变量 父类方法不能访问子类私有变量
child class public var # 打印子类的公有变量
instance private var # 打印父类的私有内置变量 父类方法不能访问子类的私有内置变量
child instance public var # 打印子类的公有内置变量
b.public_class_method() # 调用父类的类方法
class private var # 打印父类的私有变量 父类方法不能调用子类私有变量
child class public var # 打印子类的公用变量
具体运行过程请进行模拟
调用父类方法的时候,父类私有变量和方法__private直接被翻译成_class__private形式。其中class 是当前调用的方法所在的类层。
class A:
def __method(self):
print("method of A")
class B(A):
def __method(self):
super(B,self)._A__method()
print("method of B")
def method(self):
self.__method()
b = B()
b.method()
method of A
method of B
父类私有方法继承,可以在子类重写私有方法并用super()函数调用实现父类私有方法。
多继承
class A:
def method(self):
print("method of A")
class B:
def method(self):
print("method of B")
class C(A,B):
pass
c = C()
c.method()
method of A
class C(B,A):
pass
c = C()
c.method()
method of B
class A:
def method(self):
print("method of A")
class B(A):
pass
class C(B,A):
pass
C.mro()
[__main__.C, __main__.B, __main__.A, object]
class C(A,B):
pass
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-32-36940528567b> in <module>()
----> 1 class C(A,B):
2 pass
TypeError: Cannot create a consistent method resolution
order (MRO) for bases B, A
多重继承是需要遵循 MRO 规则。Python:super函数文章里有介绍MRO规则。
MRO method resolution order
本地优先级:根据声明顺序从左往右查找
单调性:所有子类中,也应满足其查找顺序
MRO 通过 C3算法计算出来
C3算法的MERGE步骤
* 顺序遍历列表
* 首先素满足以下条件,否则遍历下一个序列
* 在其他序列也是首元素
* 在其他序列里不存在
* 从所有序列中移除元素,合并到MRO序列中
* 重复执行,直到所有序列为空或无法执行下去
Python 的多继承是一济毒药
MIXIN
class Document():
def __init__(self,content):
self.content = content
def format(self):
pass
def display():
raise NotImplementedError
class Word(Document):
def format(self):
self.content = "I am word".format(self.content)
class Montior():
def display(self):
print(self.content)
class Montior_with_word(Montior,Word):
pass
mww = Montior_with_word("sunchao")
mww.display()
sunchao
mww.format()
mww.display()
I am word
Montior_with_word.__mro__
(__main__.Montior_with_word,
__main__.Montior,
__main__.Word,
__main__.Document,
object)
- 实例要先初始化找父类__init__方法


浙公网安备 33010602011771号