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)# 就可以看到了
来源: http://www.bubuko.com/infodetail-2500627.html