封装

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

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

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

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

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

  1 封装:
  2         体现在两点:
  3             1、数据的封装(将数据封装到对象中)
  4                 obj = Foo('宝宝',22)
  5             2、封装方法和属性,将一类操作封装到一个类中
  6 
  7         class Foo:
  8             def __init__(self,name,age):
  9                 self.name = name
 10                 self.age = age
 11             def show (self):
 12                 print(self.name,self.age)
封装
  1 1.用我们常用的__init__方法里的self取值
  2 class Course:#恰好给我们提供了实现这种思路的方法
  3 #             #一种思路,python
  4     def __init__(self,price,period,name):
  5         self.price = price
  6         self.period = period
  7         self.name = name
  8 c = Course(2000,'linux','6 months')
  9 print(c.period)
 10 
 11 2.在类里面定义一个空字典,然后装在字典里面取值
 12 def course(price,name ,period):
 13     dic = {}
 14     dic['price'] = price
 15     dic ['name'] = name
 16     dic ['period'] = period
 17     return dic
 18 
 19 c = Course(2000,'python','6 months')
 20 print(c.period)  #对象名.属性名     查看属性的值
 21 
 22 3.利用namedtuple方法
 23 from collections import namedtuple  #只有属性没有方法的类
 24 Course = namedtuple('Course',['name','price','period']) #传两个参数,第一个为自定义的名字,第二个传进去的是属性
 25 python = Course('python',10000,'6 moths')  #相当于实例化了
 26 print(python.name)
 27 
 28 对象名.属性名取值的三种方法
对象名.属性名取值的三种方法

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

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

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

  1 成人的BMI数值:
  2 过轻:低于18.5
  3 正常:18.5-23.9
  4 过重:24-27
  5 肥胖:28-32
  6 非常肥胖, 高于32
  7   体质指数(BMI)=体重(kg)÷身高^2(m)
  8   EX:70kg÷(1.75×1.75)=22.86

如上面的指标来计算下你自己的体质指数

  1 class Person:
  2     def __init__(self,height,weight,name,sex):
  3         self.__height = height  #私有属性(让你不再外面调它)
  4                                 # 在本类中可以调用,在类外就不可以调用了
  5         self.__weigth = weight
  6         self.__name = name
  7         self.__sex = sex
  8     def tell_bmi(self):  #体重指数
  9         return self.__weigth/self.__height ** 2  #在本类中可以调用
 10 
 11     def tell_height(self):
 12         print(self.__height)
 13     def tell_weight(self):  #告诉体重
 14         return  self.__weigth
 15     def set_weigth(self,new_weight):   #修改体重
 16         if new_weight >20:
 17              self.__weigth = new_weight
 18         else:
 19             raise TypeError('你也太瘦了,瘦的连斤数都(快)没了')   #如果体重小于20或者负的,就主动提示一个报错
 20 egg = Person(1.6,96,'haiyan','female')
 21 print(egg.tell_bmi())
 22 # egg.__height #在类外不能调用
 23 # print(egg._Person__height)  #在类外查看得这样调用
 24 print(egg.__dict__)  #查看变形后的类型
 25 # egg.set_weigth(-10)
 26 # print(egg.tell_weigth())
 27 egg.set_weigth(66)  #修改体重为66
 28 print(egg.tell_weight())
 29 
 30 计算体质指数,衡量人健康的标准(对象的私有属性一)
计算体质指数,衡量人健康的标准(对象的私有属性一)
  1 class People:
  2     def __init__(self,name,age,sex,height):
  3         self.__name = name
  4         self.__age = age
  5         self.__sex = sex
  6         self.__height = height
  7 
  8     def tell_name(self):  #看人名字
  9         print(self.name)
 10     def set_name(self,val): #修改名字
 11         if not isinstance(val, str):
 12             raise TypeError('名字必须是字符串类型')
 13         self.__name = val
 14     def tell_info(self):
 15          print('''
 16            ---------%s info-----------
 17            name:%s
 18            age:%s
 19            sex:%s
 20            height:%s'''%(self.__name,self.__name,self.__age,self.__sex,self.__height))
 21 
 22 p=People('egon',21,'male','180')
 23 p.tell_info()
 24 p.set_name('haiyan')   #调用修改名字的方法
 25 p.tell_info()
 26 # print(p._People__name)#就可以看到了
 27 
 28 对象属性的私有属性二
对象属性的私有属性二

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

  1 # 方法的私有属性
  2 class Parent:
  3     def __init__(self):
  4         self.__func()  #__func==_Parent__func
  5     def __func(self):
  6         print('Parent func')
  7 
  8 class Son(Parent):
  9     def __init__(self):
 10         self.__func()  #_Son__func
 11     def __func(self):
 12         print('Son func')
 13 
 14     def _Parent__func(self):
 15         print('son _Parent__func')
 16 s = Son()
 17 print(Parent.__dict__)  #类名.__dict__查看变形后的结果
 18 
 19 # 私有属性:在本类内是可以正常调用的
 20 #           在本类外就必须以_类名__属性名调用(但是不建议你调)
 21 
 22 类方法的私有属性1
类方法的私有属性1

  1 class Foo:
  2     def __func(self):
  3         print('from foo')
  4 class Bar(Foo):
  5     def __func(self):
  6         print('from bar')
  7 b = Bar()
  8 b._Foo__func()
  9 b._Bar__func()
 10 
 11 方法的私有属性2
方法的私有属性2
  1 class Foo:
  2     def __init__(self,height,weight):
  3         self.height = height
  4         self.weight = weight
  5     def __heightpow(self):  #私有方法
  6         return self.height * self.height
  7     def tell_bmi(self):
  8         return self.weight/self.__heightpow()
  9 
 10 egon = Foo(1.7,120)
 11 print(egon.tell_bmi())
 12 print(Foo.__dict__)
 13 print(egon._Foo__heightpow())  #虽说是私有的,但是还是可以查看的
 14 
 15 装饰方法的私有属性3
装饰方法的私有属性3

5.property

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

1.计算圆的面积和周长

  1 from math import pi
  2 class Circle:
  3     def __init__(self,radius):
  4         self.radius = radius
  5     @property  #装饰器:把一个方法当成一个属性用了
  6     def area(self):
  7         return self.radius * self.radius* pi
  8     @property
  9     def peimeter(self):
 10         return 2*pi*self.radius
 11 
 12 c = Circle(10)
 13 print(c.area)  #当成一个属性来调了,就不用加括号了
 14 print(c.peimeter)
 15 
 16 property
property

2.缓存网页信息

  1 from urllib.request import urlopen
  2 class Web_page:
  3     def __init__(self,url):
  4         self.url = url
  5         self.__content = None  #内容设置为None
  6     @property
  7     def content(self):
  8         if self.__content:  #如果不为空,就说明已经下载了  _Web_page__content
  9             return self.__content
 10         else:
 11             self.__content = urlopen(self.url).read()#做缓存
 12             return self.__content
 13 mypage = Web_page('http://www.baidu.com')
 14 print(mypage.content)
 15 print(mypage.content)
 16 print(mypage.content)
 17 
 18 property(2)
property(2)

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

  1 class Num:
  2     def __init__(self,*args):
  3         print(args)
  4         if len(args)==1 and (type(args[0]) is list or type(args[0]) is tuple):
  5             self.numbers=args[0]
  6         else:
  7             self.numbers = args
  8 
  9     @property
 10     def sum(self):
 11         return sum(self.numbers)
 12 
 13     @property
 14     def avg(self):
 15         return self.sum/len(self.numbers)
 16 
 17     @property
 18     def min(self):
 19         return min(self.numbers)
 20 
 21     @property
 22     def max(self):
 23         return max(self.numbers)
 24 num = Num([3,1,3])
 25 vvv = Num(8,2,3)
 26 print(num.sum)
 27 print(num.min)
 28 print(num.avg)
 29 print(num.max)
 30 print('-----------')
 31 print(vvv.sum)
 32 print(vvv.min)
 33 print(vvv.avg)
 34 print(vvv.max)
 35 
 36 property(3)
property(3)

6.setter

  1 class Num:
  2     def __init__(self,*args):
  3         print(args)
  4         if len(args)==1 and (type(args[0]) is list or type(args[0]) is tuple):
  5             self.numbers=args[0]
  6         else:
  7             self.numbers = args
  8 
  9     @property
 10     def sum(self):
 11         return sum(self.numbers)
 12 
 13     @property
 14     def avg(self):
 15         return self.sum/len(self.numbers)
 16 
 17     @property
 18     def min(self):
 19         return min(self.numbers)
 20 
 21     @property
 22     def max(self):
 23         return max(self.numbers)
 24 num = Num([3,1,3])
 25 vvv = Num(8,2,3)
 26 print(num.sum)
 27 print(num.min)
 28 print(num.avg)
 29 print(num.max)
 30 print('-----------')
 31 print(vvv.sum)
 32 print(vvv.min)
 33 print(vvv.avg)
 34 print(vvv.max)
 35 
 36 property(3)
property(3)
  1 class Goods:
  2     __discount = 0.8  #类的私有属性
  3     def __init__(self,name,price):
  4         self.name = name
  5         self.__price = price
  6 
  7     @property
  8     def price(self):
  9         # if hasattr(self,'__price'):
 10             return self.__price * Goods.__discount
 11         # else:
 12         #     raise NameError
 13 
 14     @price.setter
 15     def price(self,new_price):
 16         if type(new_price) is int:
 17             self.__price = new_price
 18 
 19     @price.deleter
 20     def price(self):
 21         del self.__price
 22 
 23 apple = Goods('apple',10)
 24 # print(apple.price)
 25 apple.price = 20
 26 print(apple.price)
 27 
 28 # del apple.price
 29 # print(apple.price)
 30 # apple.set_price(20)
 31 # apple._Goods__apple
 32 
 33 买东西
买东西
@property把一个类中的方法 伪装成属性
原来是obj.func()
现在是obj.func -->属性
1.因为属性不能被修改
所以用了@funcname.setter
obj.func = new_value 调用的是被@funcname.setter装饰器装饰的方法
被@property装饰的方法名必须和被@funcname.setter装饰的方法同名
2.也可以另一种方法修改,但是上一种方法吧一个类中的方法伪装成属性来调用了,而这种方法还是原来实例化一样调用
例如:
  1 class People:
  2     def __init__(self,name,age,sex,height):
  3         self.__name = name
  4         self.__age = age
  5         self.__sex = sex
  6         self.__height = height
  7 
  8     def tell_name(self):  #看人名字
  9         print(self.name)
 10     def set_name(self,val): #修改名字
 11         if not isinstance(val, str):
 12             raise TypeError('名字必须是字符串类型')
 13         self.__name = val
 14     def tell_info(self):
 15          print('''
 16            ---------%s info-----------
 17            name:%s
 18            age:%s
 19            sex:%s
 20            height:%s'''%(self.__name,self.__name,self.__age,self.__sex,self.__height))
 21 
 22 p=People('egon',21,'male','180')
 23 p.tell_info()
 24 p.set_name('haiyan')   #调用修改名字的方法
 25 p.tell_info()
 26 # print(p._People__name)#就可以看到了
 
 
分类: 面向对象

posted @ 2019-09-19 16:26  Py猫的故事  阅读(195)  评论(0编辑  收藏  举报
返回顶部