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__方法

posted @ 2016-03-05 17:05  蓝色骨头  阅读(204)  评论(0)    收藏  举报