封装
一、封装:
补充封装:
封装:
体现在两点:
1、数据的封装(将数据封装到对象中)
obj = Foo('宝宝',22)
2、封装方法和属性,将一类操作封装到一个类中
class Foo:
def __init__(self,name,age):
self.name = name
self.age = age
def show (self):
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)
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)
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 #在本类外就必须以_类名__属性名调用(但是不建议你调)
3.封装类对象的私有属性
1
2
3
4
5
6
7
8
|
成人的BMI数值: 过轻:低于 18.5 正常: 18.5 - 23.9 过重: 24 - 27 肥胖: 28 - 32 非常肥胖, 高于 32 体质指数(BMI) = 体重(kg)÷身高^ 2 (m) 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())
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)#就可以看到了
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 # 在本类外就必须以_类名__属性名调用(但是不建议你调)
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()
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()) #虽说是私有的,但是还是可以查看的
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)
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)
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)
6.setter
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
@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)#就可以看到了