zoukankan      html  css  js  c++  java
  • 面向对象

    1.类的组成    数据和函数,二者是类的属性

    2.两个作用: 实例化 属性引用  

       属性引用:类名.属性(增删改查) 

       实例化: 类名加括号就是实例化,会自动出发__init__的运行,可以用它为每个实例创建自己的特征

    1
    2
    3
    4
    类属性     特征(变量)
              技能(函数)
     
    对象属性:对象本身只有特征(变量)
    class Province:
        memo = "中国的23个省之一"                    #类的数据属性
     
        def __init__(self,name,capital,leader):
            self.Name = name
            self.Capital = capital
            self.Leadder = leader
     
        def sport_meet(self):
            print('%s 正在开运动会'% self.Name)
     
        def pao(self,pao):
            print('%s 正在放%s炮'% (self.Name,pao))
     
     
    -------------------类--------------------
     
    print(Province.__dict__)         #查看类属性字典
     
    print(Province.memo)             #查看类的数据属性
        中国的23个省之一
    print(Province.__dict__["memo"]) #查看类的数据属性
        中国的23个省之一
     
    Province.sport_meet("山西")               #查看类的函数属性
            正在开运动会
    Province.__dict__["sport_meet"]("山西")   #查看类的函数属性
            正在开运动会
    ---------------------------------------
     
    --------------类的其它属性------------------
     
    类名.__name__     # 类的名字(字符串)
    类名.__doc__      # 类的文档字符串
    类名.__base__     # 类的第一个父类(在讲继承时会讲)
    类名.__bases__    # 类所有父类构成的元组(在讲继承时会讲)
    类名.__dict__     # 类的字典属性
    类名.__module__   # 类定义所在的模块
    类名.__class__    # 实例对应的类(仅新式类中)
     
    ------------------------------------------
     
     
    # ----------------------对象--------------------
     
    hb = Province('河北','石家庄','李杨')            #创建实例
    print(hb.__dict__)
        {'Capital': '石家庄', 'Leadder': '李杨', 'Name': '河北'}
     
    print(hb.memo)          #实例调取类的数据属性
        中国的23个省之一
     
    hb.sport_meet()         #实例调取没有参数的函数
        河北 正在开运动会
     
    hb.pao("")           #实例调取有参数的函数
        河北 正在放大炮
    类和对象分别调用 特征和函数
     1 class Chinese:
     2     country="china"
     3     def __init__(self,name):
     4         self.name=name
     5 
     6     def play_ball(self,ball):
     7         print("%s 正在打 %s" %(self.name,ball))
     8 
     9 p1=Chinese("alex")
    10 
    11 #对象执行类的数据属性
    12 # print(p1.country)
    13 #     china
    14 
    15 
    16 #对象改p1.country="日本",相当于给对象的__dict__增加值,而不是改变类的数据属性
    17 print(p1.__dict__)
    18     # {'name': 'alex'}
    19 p1.country="日本"
    20 print(p1.__dict__)
    21     # {'name': 'alex', 'country': '日本'}
    22 print(p1.country)
    23     # 日本
    24 print(Chinese.country)
    25     #china
    View Code
     1 #类里面的数据属性contry只会被Chinese.country和p1.country调用到
     2 country = "日本"
     3 
     4 class Chinese:
     5     country = "china"       #只会被类和对象调用到,带点的
     6 
     7     def __init__(self,name):
     8         self.name=name
     9         print(country)      #此时的country就是一个普通的变量
    10 
    11     def play_ball(self,ball):
    12         print("%s 正在打 %s" %(self.name,ball))
    13 
    14 p1=Chinese("alex")
    15     #日本
    View Code
     1 #p1.l1 = [1,2,3]相当于给p1__dict__增加
     2 # p1.l1.append(5)相当于给原来的l1追加,相当于操作的是类
     3 class Chinese:
     4     l1 = ["alex","egon"]
     5     def __init__(self,name):
     6         self.name=name
     7 
     8 
     9     def play_ball(self,ball):
    10         print("%s 正在打 %s" %(self.name,ball))
    11 
    12 p1=Chinese("alex")
    13 
    14 
    15 p1.l1 = [1,2,3]
    16 print(Chinese.l1)
    17     #['alex', 'egon']
    18 
    19 #追加之后发现原来的l1也变了
    20 p1.l1.append(5)
    21 print(p1.l1)
    22     #['alex', 'egon', 5]
    23 print(Chinese.l1)
    24     #['alex', 'egon', 5]
    View Code

    静态方法  staticmethod

    #静态方法,此时对象调类里面的函数不是绑定方法,而是普通的函数
    
    class Foo:
        @staticmethod
        def spam(x,y,z):    #没有self,即使有self,也会当成普通参数
            print(x,y,z)
    
    f2=Foo()
    f2.spam(1,2,3)
    Example 1 @staticmethod
     import time
    class Date:
        def __init__(self,year,month,day):
            self.year=year
            self.month=month
            self.day=day
        @staticmethod
        def now():                 #用Date.now()的形式去产生实例,该实例用的是当前时间
            t=time.localtime()     #获取结构化的时间格式
            obj=Date(t.tm_year,t.tm_mon,t.tm_mday) #新建实例并且返回
            return obj
    
    #之前实例化
    # d1=Date(2017,1,13)
    # print(d1.year,d1.month,d1.day)
    #     2017 1 13
    
    #现在实例化,不需要传值
    # data_now = Date.now()
    # print(data_now.year,data_now.month,data_now.day)
    #     2017 4 22
    应用场景

    类方法  classmethod

      把一个方法绑定给类:类.绑定到类的方法(),会把类本身当做第一个参数自动传给绑定到类的方法

    class Foo:
    
        @classmethod #把一个方法绑定给类:类.绑定到类的方法(),会把类本身当做第一个参数自动传给绑定到类的方法
        def test(cls,x):
            print(cls,x) #拿掉一个类的内存地址后,就可以实例化或者引用类的属性了
    
    
    
    Foo.test(123)
        <class '__main__.Foo'> 123
    
    
    f = Foo()
    print(f.test)       # 发现现在对象调时候成了类的绑定方法
        <bound method Foo.test of <class '__main__.Foo'>>
    f.test(123)         #现在对象传值的时候第一个传的默认是类
        <class '__main__.Foo'> 123
    Example 1 @classmethod
    #__str__定义在类内部,必须返回一个字符串类型,
    #什么时候会触发它的执行呢?打印由这个类产生的对象时,会触发执行
    
    class People:
        def __init__(self,name,age):
            self.name=name
            self.age=age
        def __str__(self):
            return 'name:%s,age:%s' %(self.name,self.age)
    
    p1=People('egon',18)
    print(p1)
    
    
    
    import time
    class Date:
        def __init__(self,year,month,day):
            self.year=year
            self.month=month
            self.day=day
    
        @classmethod
        def now(cls): #用Date.now()的形式去产生实例,该实例用的是当前时间
            t=time.localtime() #获取结构化的时间格式
            obj=cls(t.tm_year,t.tm_mon,t.tm_mday) #新建实例并且返回
            return obj
    
    
    class EuroDate(Date):
        def __str__(self):
            return '年:%s,月:%s,日:%s' %(self.year,self.month,self.day)
    
    e1=EuroDate.now()
    print(e1)
    应用场景 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    在类内部定义的函数无非三种用途
    一:绑定到对象的方法
        只要是在类内部定义的,并且没有被任何装饰器修饰过的方法,都是绑定到对象的
         
        class Foo:
            def test(self): #绑定到对象的方法
                pass
            def test1(): #也是绑定到对象的方法,只是对象.test1(),会把对象本身自动传给test1,因test1没有参数所以会抛出异常
                pass
         
        绑定到对象,指的是:就给对象去用,
        使用方式:对象.对象的绑定方法(),不用为self传值
        特性:调用时会把对象本身当做第一个参数传给对象的绑定方法
         
     
         
    二:绑定到类的方法:classmethod
        在类内部定义的,并且被装饰器@classmethod修饰过的方法,都是绑定到类的
         
        class Foo:
            def test(self): #绑定到对象的方法
                pass
            def test1(): #也是绑定到对象的方法,只是对象.test1(),会把对象本身自动传给test1,因test1没有参数所以会抛出异常
                pass
         
        绑定到对象,指的是:就给对象去用,
        使用方式:对象.对象的绑定方法()
        特性:调用时会把对象本身当做第一个参数传给对象的绑定方法
         
         
    三:解除绑定的方法:staticmethod
        既不与类绑定,也不与对象绑定,不与任何事物绑定
        绑定的特性:自动传值(绑定到类的就是自动传类,绑定到对象的就自动传对象)
        解除绑定的特性:不管是类还是对象来调用,都没有自动传值这么一说了
         
        所以说staticmethod就是相当于一个普通的工具包
         
         
    class Foo:
        def test1(self):
            pass
        def test2():
            pass
         
     
         
        @classmethod
        def test3(cls):
            pass
        @classmethod
        def test4():
            pass
             
             
             
        @staticmethod
        def test5():
            pass
             
    test1与test2都是绑定到对象方法:调用时就是操作对象本身
        <function Foo.test1 at 0x0000000000D8E488>
        <function Foo.test2 at 0x0000000000D8E510>
    test3与test4都是绑定到类的方法:调用时就是操作类本身
        <bound method Foo.test3 of <class '__main__.Foo'>>
        <bound method Foo.test4 of <class '__main__.Foo'>>
    test5是不与任何事物绑定的:就是一个工具包,谁来都可以用,没说专门操作谁这么一说
        <function Foo.test5 at 0x0000000000D8E6A8>

      

    面向对象的三大特性 

    一.继承 

    继承 

      继承是一种创建新的类的方式,在python中,新建的类可以继承自一个或者多个父类,原始类称为基类或超类,新建的类称为派生类或子类。 

      python中类的继承分为:单继承和多继承

      继承有两种用途:  

      1:继承基类的方法,并且做出自己的改变或者扩展(代码重用)

      2:声明某个子类兼容于某基类,定义一个接口类Interface,接口类中定义了一些接口名(就是函数名)且并未实现接口的功能,子类继承接口类,

        并且实现接口中的功能

     1 class Animal:
     2 
     3     def eat(self):
     4         print "%s 吃 " %self.name
     5 
     6     def drink(self):
     7         print "%s 喝 " %self.name
     8 
     9     def shit(self):
    10         print "%s 拉 " %self.name
    11 
    12     def pee(self):
    13         print "%s 撒 " %self.name
    14 
    15 
    16 class Cat(Animal):
    17 
    18     def __init__(self, name):
    19         self.name = name
    20         self.breed = ''
    21 
    22     def cry(self):
    23         print '喵喵叫'
    24 
    25 class Dog(Animal):
    26     
    27     def __init__(self, name):
    28         self.name = name
    29         self.breed = ''
    30         
    31     def cry(self):
    32         print '汪汪叫'
    33         
    34 
    35 # ######### 执行 #########
    36 
    37 c1 = Cat('小白家的小黑猫')
    38 c1.eat()
    39 
    40 c2 = Cat('小黑的小白猫')
    41 c2.drink()
    42 
    43 d1 = Dog('胖子家的小瘦狗')
    44 d1.eat()
    继承

     组合

      软件重用的重要方式除了继承之外还有另外一种方式,即:组合

      组合指的是,在一个类中以另外一个类的对象作为数据属性,称为类的组合

    class Teacher:
        def __init__(self,name,sex,course):
            self.name=name
            self.sex=sex
            self.course=course
    class Student:
        def __init__(self,name,sex,course):
            self.name=name
            self.sex=sex
            self.course=course
    class Course:
        def __init__(self,name,price,peroid):
            self.name=name
            self.price=price
            self.period=peroid
    python_obj=Course('python',15800,'7m')
    t1=Teacher('egon','male',python_obj)
    s1=Student('cobila','male',python_obj)
    
    print(s1.course.name)
    print(t1.course.name)
    学生老师和成绩组合

    组合与继承  

      组合对比继承来说,也是用来重用代码,但是组合描述的是一种“有”的关系

      都是有效地利用已有类的资源的重要方式。但是二者的概念和使用场景皆不同  

      1.继承的方式

        通过继承建立了派生类与基类之间的关系,它是一种'是'的关系,比如白马是马,人是动物。 

        当类之间有很多相同的功能,提取这些共同的功能做成基类,用继承比较好,比如教授是老师

      2.组合的方式

        用组合的方式建立了类与组合的类之间的关系,它是一种‘有’的关系,比如教授有生日,教授教python课程  

    老师有课程
    学生有成绩
    学生有课程
    学校有老师
    学校有学生
    
    class Course:
        def __init__(self,name,price,period):
            self.name=name
            self.price=price
            self.period=period
            
    class Teacher:
        def __init__(name,course):
            self.name=name
            self.course=course
            
    class Student:
        def __init__(name,course):
            self.name=name
            self.course=course
    
    python=Course('python',15800,'7m')
    t1=Teacher('egon',python)
    s1=Student('alex',python)
    
    
    print(s1.course.name)
    print(s1.course.period)
    组合 

    派生 

      子类继承了父类的属性,然后衍生出自己新的属性,如果子类衍生出的新的属性与父类的某个属性名字相同,
      那么再调用子类的这个属性,就以子类自己这里的为准了

    class People:
        def __init__(self,name,sex,age):
            self.name=name
            self.age=age
            self.sex=sex
    
        def walk(self):
            print('%s is walking' %self.name)
    
    
    class Chinese(People):
        country='China'
        def __init__(self,name,sex,age,language='Chinese'):
            People.__init__(self,name,sex,age)
            self.language=language
    
        def walk(self):
            People.walk(self)
    
    class North_korean(People):
        country='Korean'
    
    
    c=Chinese('egon','male',18)
    print(c.name,c.age,c.sex)
        egon 18 male
    print(c.__dict__)
        {'sex': 'male', 'age': 18, 'language': 'Chinese', 'name': 'egon'}
    print(c.country)
        China
    c.walk()
        egon is walking
    派生

    接口与归一化设计 

      1.接口

      为何要用接口:

        接口提取了一群类共同的函数,可以把接口当做一个函数的集合。

        然后让子类去实现接口中的函数。

        这么做的意义在于归一化,什么叫归一化,就是只要是基于同一个接口实现的类,那么所有的这些类产生的对象在使用时,从用法上来说都一样。 

        归一化,让使用者无需关心对象的类是什么,只需要的知道这些对象都具备某些功能就可以了,这极大地降低了使用者的使用难度。

    class Interface:#定义接口Interface类来模仿接口的概念,python中压根就没有interface关键字来定义一个接口。
        def read(self): #定接口函数read
            pass
    
        def write(self): #定义接口函数write
            pass
    
    
    class Txt(Interface): #文本,具体实现read和write
        def read(self):
            print('文本数据的读取方法')
    
        def write(self):
            print('文本数据的读取方法')
    
    class Sata(Interface): #磁盘,具体实现read和write
        def read(self):
            print('硬盘数据的读取方法')
    
        def write(self):
            print('硬盘数据的读取方法')
    
    class Process(All_file):
        def read(self):
            print('进程数据的读取方法')
    
        def write(self):
            print('进程数据的读取方法')
    文件和程序的读写 接口设计   

       2.抽象类

      1 什么是抽象类

          与java一样,python也有抽象类的概念但是同样需要借助模块实现,抽象类是一个特殊的类,它的特殊之处在于只能被继承,不能被实例化

      2 为什么要有抽象类

          如果说类是从一堆对象中抽取相同的内容而来的,那么抽象类是从一堆中抽取相同的内容而来的,内容包括数据属性和函数属性。

    import abc
    #抽象类:本质还是类,与普通类额外的特点的是:加了装饰器的函数,子类必须实现他们
    class Animal(metaclass=abc.ABCMeta):
        tag='123123123123123'
        @abc.abstractmethod
        def run(self):
            pass
        @abc.abstractmethod
        def speak(self):
            pass
    
    
    
    class People(Animal):
        def run(self):
            pass
    
        def speak(self):
            pass
    
    
    peo1=People()
    print(peo1.run)
    抽象类 import abc 
     1 #_*_coding:utf-8_*_
     2 __author__ = 'Linhaifeng'
     3 #一切皆文件
     4 import abc #利用abc模块实现抽象类
     5 
     6 class All_file(metaclass=abc.ABCMeta):
     7     all_type='file'
     8     @abc.abstractmethod #定义抽象方法,无需实现功能
     9     def read(self):
    10         '子类必须定义读功能'
    11         pass
    12 
    13     @abc.abstractmethod #定义抽象方法,无需实现功能
    14     def write(self):
    15         '子类必须定义写功能'
    16         pass
    17 
    18 # class Txt(All_file):
    19 #     pass
    20 #
    21 # t1=Txt() #报错,子类没有定义抽象方法
    22 
    23 class Txt(All_file): #子类继承抽象类,但是必须定义read和write方法
    24     def read(self):
    25         print('文本数据的读取方法')
    26 
    27     def write(self):
    28         print('文本数据的读取方法')
    29 
    30 class Sata(All_file): #子类继承抽象类,但是必须定义read和write方法
    31     def read(self):
    32         print('硬盘数据的读取方法')
    33 
    34     def write(self):
    35         print('硬盘数据的读取方法')
    36 
    37 class Process(All_file): #子类继承抽象类,但是必须定义read和write方法
    38     def read(self):
    39         print('进程数据的读取方法')
    40 
    41     def write(self):
    42         print('进程数据的读取方法')
    43 
    44 wenbenwenjian=Txt()
    45 
    46 yingpanwenjian=Sata()
    47 
    48 jinchengwenjian=Process()
    49 
    50 #这样大家都是被归一化了,也就是一切皆文件的思想
    51 wenbenwenjian.read()
    52 yingpanwenjian.write()
    53 jinchengwenjian.read()
    54 
    55 print(wenbenwenjian.all_type)
    56 print(yingpanwenjian.all_type)
    57 print(jinchengwenjian.all_type)
    接口继承

    2 继承顺序原理(python如何实现的继承)

    python到底是如何实现继承的,对于你定义的每一个类,python会计算出一个方法解析顺序(MRO)列表,这个MRO列表就是一个简单的所有基类的线性顺序列表,例如

    >>> F.mro() #等同于F.__mro__
    [<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]

    为了实现继承,python会在MRO列表上从左到右开始查找基类,直到找到第一个匹配这个属性的类为止。
    而这个MRO列表的构造是通过一个C3线性化算法来实现的。我们不去深究这个算法的数学原理,它实际上就是合并所有父类的MRO列表并遵循如下三条准则:
    1.子类会先于父类被检查
    2.多个父类会根据它们在列表中的顺序被检查
    3.如果对下一个类存在两个合法的选择,选择第一个父类

     1 class A(object):
     2     def test(self):
     3         print('from A')
     4 
     5 class B(A):
     6     def test(self):
     7         print('from B')
     8 
     9 class C(A):
    10     def test(self):
    11         print('from C')
    12 
    13 class D(B):
    14     def test(self):
    15         print('from D')
    16 
    17 class E(C):
    18     def test(self):
    19         print('from E')
    20 
    21 class F(D,E):
    22     # def test(self):
    23     #     print('from F')
    24     pass
    25 f1=F()
    26 f1.test()
    27 print(F.__mro__) #只有新式才有这个属性可以查看线性列表,经典类没有这个属性
    28 
    29 #新式类继承顺序:F->D->B->E->C->A
    30 #经典类继承顺序:F->D->B->A->E->C
    31 #python3中统一都是新式类
    32 #pyhon2中才分新式类与经典类
    继承顺序

    3.子类调用父类的方法

    子类继承了父类的方法,然后想进行修改,注意了是基于原有的基础上修改,那么就需要在子类中调用父类的方法

    方法一:父类名.父类方法()

     1 class Vehicle: #定义交通工具类
     2      Country='China'
     3      def __init__(self,name,speed,load,power):
     4          self.name=name
     5          self.speed=speed
     6          self.load=load
     7          self.power=power
     8 
     9      def run(self):
    10          print('开动啦...')
    11 
    12 class Subway(Vehicle): #地铁
    13     def __init__(self,name,speed,load,power,line):
    14         Vehicle.__init__(self,name,speed,load,power)
    15         self.line=line
    16 
    17     def run(self):
    18         print('地铁%s号线欢迎您' %self.line)
    19         Vehicle.run(self)
    20 
    21 line13=Subway('中国地铁','180m/s','1000人/箱','',13)
    22 line13.run()
    View Code

    方法二:super()

    super在python2中的用法:
        1:super(自己的类,self).父类的函数名字
        2:super只能用于新式类
    class People(object):
        def __init__(self,name,sex,age):
            self.name=name
            self.age=age
            self.sex=sex
        def walk(self):
            print('%s is walking' %self.name)
    class Chinese(People):
        country='China'
        def __init__(self,name,sex,age,language='Chinese'):
            super(Chinese,self).__init__(name,sex,age)
            self.language=language
    c=Chinese('egon','male',18)
    print c.name,c.age,c.sex,c.language
    python2 supper
    class People:
        def __init__(self,name,sex,age):
            self.name=name
            self.age=age
            self.sex=sex
        def walk(self):
            print('%s is walking' %self.name)
    class Chinese(People):
        country='China'
        def __init__(self,name,sex,age,language='Chinese'):
            # self.name=name
            # self.sex=sex
            # self.age=age
            # People.__init__(self,name,sex,age)
            super(Chinese,self).__init__(name,sex,age)
            self.language=language
        def walk(self,x):
            super().walk()
            print('子类的x',x)
    c=Chinese('egon','male',18)
    print(c.name,c.age,c.sex,c.language)
    c.walk(123)
    python3 supper

     二.多态

    多态指的是一类事物有多种形态,(一个抽象类有多个子类,因而多态的概念依赖于继承)

      1. 序列类型有多种形态:字符串,列表,元组。

      2. 动物有多种形态:人,狗,猪

      3. 文件有多种形态:文件文件,可执行文件

    import abc
    class Animal(metaclass=abc.ABCMeta): #同一类事物:动物
        @abc.abstractmethod
        def talk(self):
            pass
    
    class People(Animal): #动物的形态之一:人
        def talk(self):
            print('say hello')
    
    class Dog(Animal): #动物的形态之二:狗
        def talk(self):
            print('say wangwang')
    
    class Pig(Animal): #动物的形态之三:猪
        def talk(self):
            print('say aoao')
    动物多态
    import abc
    class File(metaclass=abc.ABCMeta): #同一类事物:文件
        @abc.abstractmethod
        def click(self):
            pass
    
    class Text(File): #文件的形态之一:文本文件
        def click(self):
            print('open file')
    
    class ExeFile(File): #文件的形态之二:可执行文件
        def click(self):
            print('execute file')
    文件有多种形态:文件文件,可执行文件 

    多态性

    同一种调用方式,不同的调用效果

    多态性是指具有不同功能的函数可以使用相同的函数名,这样就可以用一个函数名调用不同内容的函数。 

    在面向对象方法中一般是这样表述多态性:向不同的对象发送同一条消息,不同的对象在接收时会产生不同的行为(即方法)。也就是说,每个对象可以用自己的方式去响应共同的消息。所谓消息,就是调用函数,不同的行为就是指不同的实现,即执行不同的函数。

    综上我们也可以说,多态性是‘一个接口(函数func)

    class Animal:
        def run(self):
            raise AttributeError('子类必须实现这个方法')
    
    
    class People(Animal):
        def run(self):
            print('people is walking')
    
    class Pig(Animal):
        def run(self):
            print('pig is walking')
    
    
    class Dog(Animal):
        def run(self):
            print('dog is running')
    
    peo1=People()
    pig1=Pig()
    ------------------人和猪都有run方法---------
    peo1.run()
    pig1.run()
        people is walking
        pig is walking
    
    -----------------多态性,函数把run方法包装------------
    多态性:定义统一的接口,可以传入不同类型的值,但是调用的逻辑都一样,执行的结果却不一样
    def Run(name):
        name.run()
    
    Run(peo1)
    Run(pig1)
        people is walking
        pig is walking
    多态性

     三.封装

      为什么要封装

        封装数据的主要原因是:保护隐私(作为男人的你,脸上就写着:我喜欢男人,你害怕么?)

        封装方法的主要原因是:隔离复杂度(快门就是傻瓜相机为傻瓜们提供的方法,该方法将内部复杂的照相功能都隐藏起来了

                                                          比如你不必知道你的鸟是怎出来的,你直接掏出自己的接口就能用尿这个功能)

      封装的两个层面 

        1.第一个层面的封装:(什么都不用做):创建类和对象会分别创建二者的名称空间,我们只能用类名.或者obj.的方式去访问里面的名字,这本身就是一种                 封装  

        2.第二个层面的封装:类中把某些属性和方法隐藏起来(或者说定义成私有的),只在类的内部使用、外部无法访问,或者留下少量接口(函数)供外部访问 

    class A:
        __x = 1             #转换为_A__x
        def __test(self):
            print("from A")
    
    print(A.__dict__)
        {   '_A__x': 1  }
    
    ------查看类的隐藏属性————
    
    obj = A()
    print(A._A__x)
        1
    print(obj._A__x)
        1
    A._A__test(123)
        from A
    obj._A__test()
        from A
    封装

       特性(property)

       property是一种特殊的属性,访问它时会执行一段功能(函数)然后返回值

    import math
    class Circle:
        def __init__(self,radius): #圆的半径radius
            self.radius=radius
    
        @property
        def area(self):
            return math.pi * self.radius**2 #计算面积
    
        @property
        def perimeter(self):
            return 2*math.pi*self.radius #计算周长
    
    c=Circle(10)
    print(c.radius)
    print(c.area)         #可以向访问数据属性一样去访问area,会触发一个函数的执行,动态计算出一个值
    print(c.perimeter)
    -----------------------执行结果--------
    10
    314.1592653589793
    62.83185307179586
    property
    class People:
        def __init__(self,name,age,height,weight):
            self.name=name
            self.age=age
            self.height=height
            self.weight=weight
        @property
        def bodyindex(self):
            return self.weight/(self.height**2)
    
    
    p1=People('cobila',38,1.65,74)
    print(p1.bodyindex)
    p1.weight=200
    print(p1.bodyindex)
    
    ------------------------结果---------
    
    27.180899908172638
    73.46189164370983
    BMI 指数
    class People:
        def __init__(self,name):
            self.__name = name
    
        @property
        def name(self):
            return self.__name
    
    p1 = People("egon")
    print(p1.name)      #会找含有@property下name的函数
    
    -----------------------------
    egon
    @property 查找 
    class People:
        def __init__(self,name,Sex):
            self.name = name
            self.__sex = Sex
    
        @property
        def sex(self):
            return self.__sex
    
        @sex.setter
        def sex(self,value):
            self.__sex = value
    
    p1 = People("egon","male")
    print(p1.sex)      #会找含有@property下name的函数
    
    p1.sex = "famale"  #修改会找@sex.setter下的函数
    print(p1.sex)
    
    ---------------------
    male
    famale
    
    
    
    #修改性别,判断性别如果不为字符串,就报错
    class People:
        def __init__(self,name,Sex):
            self.name = name
            self.__sex = Sex
    
        @property
        def sex(self):
            return self.__sex
    
        @sex.setter
        def sex(self,value):
            if not isinstance(value,str):      #如果性别不为字符串,就报错
                raise TypeError("性别必须为字符串")
            self.__sex = value
    
    p1 = People("egon","male")
    p1.sex = 123           #修改会找@sex.setter下的函数
    print(p1.sex)
    
    -----------------
    TypeError: 性别必须为字符串
    
    
    
    
    # 实例化时后,如果不是字符串,也报错
    class People:
        def __init__(self,name,Sex):
            self.name = name
            self.sex = Sex      #此时是self.sex,而不是self.__sex
    
        @property
        def sex(self):
            return self.sex
    
        @sex.setter
        def sex(self,value):
            if not isinstance(value,str):      #如果性别不为字符串,就报错
                raise TypeError("性别必须为字符串")
            self.__sex = value
    
    p1 = People("egon",111)     #执行报错
    
    ----------------
    TypeError: 性别必须为字符串
    @property 修改
    # 实例化时,删除性别
    class People:
        def __init__(self,name,Sex):
            self.name = name
            self.sex = Sex      #此时是self.sex,而不是self.__sex
                            #实例化self.sex时候,会执行下面的@sex.setter内容
        @property
        def sex(self):
            return self.__sex
    
        @sex.setter
        def sex(self,value):
            if not isinstance(value,str):      #如果性别不为字符串,就报错
                raise TypeError("性别必须为字符串")
            self.__sex = value
    
        @sex.deleter
        def sex(self):
            del self.__sex
    
    p1 = People("egon","male")
    print(p1.sex)
        male
    del p1.sex          #删除
    print(p1.sex)
        报错
    @property 删除
  • 相关阅读:
    1093 Count PAT's(25 分)
    1089 Insert or Merge(25 分)
    1088 Rational Arithmetic(20 分)
    1081 Rational Sum(20 分)
    1069 The Black Hole of Numbers(20 分)
    1059 Prime Factors(25 分)
    1050 String Subtraction (20)
    根据生日计算员工年龄
    动态获取当前日期和时间
    对计数结果进行4舍5入
  • 原文地址:https://www.cnblogs.com/zhangningyang/p/8266761.html
Copyright © 2011-2022 走看看