• python全栈开发基础【第十五篇】面向对象三大特性——封装


    1.封装:

    什么是封装呢?(封装不是单纯意义的隐藏,其实它还是可以查看的)

      就是把一些不想让别人看的给隐藏起来了

    封装数据:目的是保护隐私

    功能封装:目的是隔离复杂度

    如果用了私有的,在类的外部,无法直接使用变形的属性,但是在类的内部可以直接使用

    # 对象名.属性名取值的三种方法
    1.用我们常用的__init__方法里的self取值
    class Course:#恰好给我们提供了实现这种思路的方法
    #             #一种思路,python
        def __init__(self,price,period,name):
            self.price = price
            self.period = period
            self.name = name
    c = Course(2000,'linux','6 months')
    print(c.period)
    
    2.在类里面定义一个空字典,然后装在字典里面取值
    def course(price,name ,period):
        dic = {}
        dic['price'] = price
        dic ['name'] = name
        dic ['period'] = period
        return dic
    
    c = Course(2000,'python','6 months')
    print(c.period)  #对象名.属性名     查看属性的值
    
    3.利用namedtuple方法
    from collections import namedtuple  #只有属性没有方法的类
    Course = namedtuple('Course',['name','price','period']) #传两个参数,第一个为自定义的名字,第二个传进去的是属性
    python = Course('python',10000,'6 moths')  #相当于实例化了
    print(python.name)
    

    2.封装类属性的私有属性(就是类属性前面加__)

    #类属性1
    class Goods:
        # 按照打八折计算 (定义了一个私有类属性)
        __discount = 0.8  #变形后:_Goods__discount
        def __init__(self,name,price):
            self.name = name
            self.price = price
        def goods_price(self):
            return  self.price * Goods.__discount
    apple = Goods('apple',10)
    print(apple.goods_price())
    # print(Goods.__dict__)  #类名.__dict__
    print(Goods._Goods__discount)
    
    #类属性的私有方法
    # 封装:把你不想让人看的隐藏起来
    # 数据封装:目的保护隐私
    class Teacher:
        __School = 'oldboy'  #类属性
        def __init__(self,name,salary):
            self.name = name
            self .__salary  =  salary  #_Teacher__salary
                # 老师的属性   值
            #怎么把薪水隐藏起来?
            self.__salary=salary
        def foo(self):
            print('------')
    
    t=Teacher('egon',2000)
    print(t.__dict__)
    # print(t.name)
    print(t._Teacher__salary)#让显示出来
    print(Teacher._Teacher__School)  #类属性使用_类名__属性名
    t.foo()
    #在本类内是可以正常调用的
    #在本类外就必须以_类名__属性名调用(但是不建议你调)
    

      

    3.封装类对象的私有属性

    成人的BMI数值:
    过轻:低于18.5
    正常:18.5-23.9
    过重:24-27
    肥胖:28-32
    非常肥胖, 高于32
      体质指数(BMI)=体重(kg)÷身高^2(m)
      EX:70kg÷(1.75×1.75)=22.86
    
    # 计算体质指数,衡量人健康的标准(对象的私有属性一)
    class Person:
        def __init__(self,height,weight,name,sex):
            self.__height = height  #私有属性(让你不再外面调它)
                                    # 在本类中可以调用,在类外就不可以调用了
            self.__weigth = weight
            self.__name = name
            self.__sex = sex
        def tell_bmi(self):  #体重指数
            return self.__weigth/self.__height ** 2  #在本类中可以调用
            
        def tell_height(self):
            print(self.__height)
        def tell_weight(self):  #告诉体重
            return  self.__weigth
        def set_weigth(self,new_weight):   #修改体重
            if new_weight >20:
                 self.__weigth = new_weight
            else:
                raise TypeError('你也太瘦了,瘦的连斤数都(快)没了')   #如果体重小于20或者负的,就主动提示一个报错
    egg = Person(1.6,96,'haiyan','female')
    print(egg.tell_bmi())
    # egg.__height #在类外不能调用
    # print(egg._Person__height)  #在类外查看得这样调用
    print(egg.__dict__)  #查看变形后的类型
    # egg.set_weigth(-10)
    # print(egg.tell_weigth())
    egg.set_weigth(66)  #修改体重为66
    print(egg.tell_weight())
    # 对象属性的私有属性二
    class People:
        def __init__(self,name,age,sex,height):
            self.__name = name
            self.__age = age
            self.__sex = sex
            self.__height = height
    
        def tell_name(self):  #看人名字
            print(self.name)
        def set_name(self,val): #修改名字
            if not isinstance(val, str):
                raise TypeError('名字必须是字符串类型')
            self.__name = val
        def tell_info(self):
             print('''
               ---------%s info-----------
               name:%s
               age:%s
               sex:%s
               height:%s'''%(self.__name,self.__name,self.__age,self.__sex,self.__height))
    
    p=People('egon',21,'male','180')
    p.tell_info()
    p.set_name('haiyan')   #调用修改名字的方法
    p.tell_info()
    # print(p._People__name)#就可以看到了
    

      

    4.封装类方法的私有属性  

    类方法的私有属性1
    # 方法的私有属性
    class Parent:
        def __init__(self):
            self.__func()  #__func==_Parent__func
        def __func(self):
            print('Parent func')
    
    class Son(Parent):
        def __init__(self):
            self.__func()  #_Son__func
        def __func(self):
            print('Son func')
    
        def _Parent__func(self):
            print('son _Parent__func')
    s = Son()
    print(Parent.__dict__)  #类名.__dict__查看变形后的结果
    
    # 私有属性:在本类内是可以正常调用的
    #           在本类外就必须以_类名__属性名调用(但是不建议你调)
    
    #方法的私有属性2
    class Foo:
        def __func(self):
            print('from foo')
    class Bar(Foo):
        def __func(self):
            print('from bar')
    b = Bar()
    b._Foo__func()
    b._Bar__func()
    
    #装饰方法的私有属性3
    class Foo:
        def __init__(self,height,weight):
            self.height = height
            self.weight = weight
        def __heightpow(self):  #私有方法
            return self.height * self.height
        def tell_bmi(self):
            return self.weight/self.__heightpow()
    
    egon = Foo(1.7,120)
    print(egon.tell_bmi())
    print(Foo.__dict__)
    print(egon._Foo__heightpow())  #虽说是私有的,但是还是可以查看的
    

     5.property

    为什么要用property:将一个类的函数定义成特性以后,对象再去使用的时候obj.name,根本无法察觉自己的name是执行了一个函数然后计算出来的,这种特性的使用方式遵循了统一访问的原则

    1.计算圆的面积和周长

    from math import pi
    class Circle:
        def __init__(self,radius):
            self.radius = radius
        @property  #装饰器:把一个方法当成一个属性用了
        def area(self):
            return self.radius * self.radius* pi
        @property
        def peimeter(self):
            return 2*pi*self.radius
    
    c = Circle(10)
    print(c.area)  #当成一个属性来调了,就不用加括号了
    print(c.peimeter)
    

     2.缓存网页信息

    from urllib.request import urlopen
    class Web_page:
        def __init__(self,url):
            self.url = url
            self.__content = None  #内容设置为None
        @property
        def content(self):
            if self.__content:  #如果不为空,就说明已经下载了  _Web_page__content
                return self.__content
            else:
                self.__content = urlopen(self.url).read()#做缓存
                return self.__content
    mypage = Web_page('http://www.baidu.com')
    print(mypage.content)
    print(mypage.content)
    print(mypage.content)
    

    3.求和,平均值,最大值,最小值

    class Num:
        def __init__(self,*args):
            print(args)
            if len(args)==1 and (type(args[0]) is list or type(args[0]) is tuple):
                self.numbers=args[0]
            else:
                self.numbers = args
    
        @property
        def sum(self):
            return sum(self.numbers)
    
        @property
        def avg(self):
            return self.sum/len(self.numbers)
    
        @property
        def min(self):
            return min(self.numbers)
    
        @property
        def max(self):
            return max(self.numbers)
    num = Num([3,1,3])
    vvv = Num(8,2,3)
    print(num.sum)
    print(num.min)
    print(num.avg)
    print(num.max)
    print('-----------')
    print(vvv.sum)
    print(vvv.min)
    print(vvv.avg)
    print(vvv.max)
    

    6.setter

    #买东西
    class Goods:
        __discount = 0.8  #类的私有属性
        def __init__(self,name,price):
            self.name = name
            self.__price = price
    
        @property
        def price(self):
            # if hasattr(self,'__price'):
                return self.__price * Goods.__discount
            # else:
            #     raise NameError
    
        @price.setter
        def price(self,new_price):
            if type(new_price) is int:
                self.__price = new_price
    
        @price.deleter
        def price(self):
            del self.__price
    
    apple = Goods('apple',10)
    # print(apple.price)
    apple.price = 20
    print(apple.price)
    
    # del apple.price
    # print(apple.price)
    # apple.set_price(20)
    # apple._Goods__apple
    
    @property把一个类中的方法 伪装成属性
    原来是obj.func()
    现在是obj.func -->属性
    1.因为属性不能被修改
    所以用了@funcname.setter
    obj.func = new_value 调用的是被@funcname.setter装饰器装饰的方法
    被@property装饰的方法名必须和被@funcname.setter装饰的方法同名
    2.也可以另一种方法修改,但是上一种方法吧一个类中的方法伪装成属性来调用了,而这种方法
    还是原来实例化一样调用
    例如:
    class People:
        def __init__(self,name,age,sex,height):
            self.__name = name
            self.__age = age
            self.__sex = sex
            self.__height = height
    
        def tell_name(self):  #看人名字
            print(self.name)
        def set_name(self,val): #修改名字
            if not isinstance(val, str):
                raise TypeError('名字必须是字符串类型')
            self.__name = val
        def tell_info(self):
             print('''
               ---------%s info-----------
               name:%s
               age:%s
               sex:%s
               height:%s'''%(self.__name,self.__name,self.__age,self.__sex,self.__height))
    
    p=People('egon',21,'male','180')
    p.tell_info()
    p.set_name('haiyan')   #调用修改名字的方法
    p.tell_info()
    # print(p._People__name)#就可以看到了
    

      

  • 相关阅读:
    玩转MySQL之Linux下的简单操作(服务启动与关闭、启动与关闭、查看版本)
    玩转MySQL之Linux下修改默认编码
    机器学习算法及应用领域相关的中国大牛
    [转载]Python 包管理工具解惑
    Vim常用操作和快捷键技巧总结
    [转载]那些C++牛人的博客
    [转载]学习c/c++的好网站
    [转载]C++内存管理
    [转载]SQL数据库如何加快查询速度
    [转载]Python3.x和Python2.x的区别
  • 原文地址:https://www.cnblogs.com/xiaohema/p/8453697.html
Copyright © 2020-2023  润新知