27面向对象2_属性装饰器
目前创新互联建站已为上千余家的企业提供了网站建设、域名、雅安服务器托管、成都网站托管、企业网站设计、临颍网站维护等服务,公司将坚持客户导向、应用为本的策略,正道将秉承"和谐、参与、激情"的文化,与客户和合作伙伴齐心协力一起成长,共同发展。
目录
属性装饰器...1
对象的销毁:...3
overload方法重载:...4
习题:...4
属性装饰器
对用户来说,属性装饰器包装后的这种用法好,只记一种即可,如stu1.chinese、stu1.chinese=100、del stu1.chinese;对程序员来说,两种写法的代码量并没有减少;
查看@property源码,class property(object),python3的类祖先为object,def __init__(self,fget=None,fset=None,fdel=None,doc=None);
两种方式:
方一:@property、@chinese.setter、@chinese.deleter
方二:english = property(lambda self: self._english,setenglish)
一般好的设计,把实例的属性保护起来,不让外部直接访问,外部使用getter读取属性和setter设置属性;
property装饰器,后面跟的函数名就是以后的属性名,它就是getter,这个必须有,有了它至少是只读属性;
setter装饰器,与属性名同名,且接收2个参数,第一个是self,第二个是将要赋值的值,有了它,属性可写;
deleter装饰器,可控制是是否删除属性,很少用;
property装饰器必须在前,setter、deleter装饰器在后;
property装饰器能通过简单的方式,把对方法的操作变成对属性的访问,并起到了一定隐藏效果;
注:
类设计:自圆其说;客户满意;
pycharm中stu1.__后面属性内容不会提示,即认为解释器要隐藏的东西;
例:
class Person:
def __init__(self,chinese,english,history):
self._chinese = chinese #对于要隐藏的实例属性要用_或__,下面要提供获取或修改属性的方法,且一定要用方法来操作,不要直接操作
self._english = english
self.__history = history
def getscore(self):
return self._chinese,self._english,self.__history
def gethistory(self): #实例属性的获取getter,经常用
return self.__history
def sethistory(self,value): #实例属性的设置setter,经常用,即self.__history该属性可rw读写
self.__history = value
def getenglish(self): #self._english该属性只可r读,另可w不可r用处不大
return self._english
stu1 = Person(80,90,88)
print(stu1.gethistory()) #这样的事很多,每次都用获取方法得到或设置方法修改,这样很麻烦
print(stu1.getscore())
输出:
88
(80, 90, 88)
例:
class Person:
def __init__(self,chinese,english,history):
self._chinese = chinese
self._english = english
self.__history = history
@property #属性装饰器,将方法转为属性,方一,通过stu1.chinese该属性可读
def chinese(self):
return self._chinese
@chinese.setter #此处chinese即为上面方法转属性的chinese,通过stu1.chinese=100该属性可写
def chinese(self,value):
self._chinese = value
@chinese.deleter #动态的删除属性,慎用,通过del stu1.chinese将自动执行该方法
def chinese(self):
# del self._chinese
print('del chinese')
# def getenglish(self): #可将此段简写为lambda self: self._english
# return self._english
# english = property(getenglish) #通过stu1.english该属性可读
def setenglish(self,value):
self._english = value
english = property(lambda self: self._english,setenglish) #方二,通过stu1.english=120该属性可读可写,类库中使用此方式的多
def __del__(self):
print('leaving')
stu1 = Person(80,90,88)
print(stu1.chinese) #r
stu1.chinese = 100 #w
print(stu1.chinese)
del stu1.chinese #del
输出:
80
100
del chinese
90
120
leaving
对象的销毁:
类中可定义__del__方法,称为析构函数(方法);
作用:销毁类的实例时调用,以释放占用的资源;收尾工作,把打开的资源(连接网络、DB、打开文件等操作)关闭掉,不用这些实例时要销毁,同with语句;
由于python实现了垃圾回收机制,会自动执行该方法,不能确定何时执行,有必要请使用del语句手动调用这个方法删除实例;
def __del__(self):
print('leaving')
overload方法重载:
python没有重载;python不需要重载;其它语言都有重载的概念;
所谓重载,即同一个方法名,但参数数量、类型不一样,就是同一个方法的重载;
python中,方法(函数)定义里,形参非常灵活,不需要指定类型,就算指定了也只是一个说明而非约束,参数个数也不固定(可变参数),一个函数的定义可实现很多种不同形式实参的调用,所以python不需要方法重载;
注:
标识符覆盖,override重写;
静态编译型语言,标识符一样的两个可同时用,多态;
python天生就支持多态(多种类型),如函数级的多态,def add(x,y),int和str都支持,会自动识别,一个函数对多种形态(多个数据类型)进行处理,甚至返回多种形态;
面向对象的多态,继承和覆盖override;
继承,盖住,不是有你没我,有我没你,而是我在我优先,我不在你重见天日,类似实例属性和类属性,有优先问题;
encapsulation封装:
面向对象的三要素之一;
将数据和操作组织到类中,即属性和方法;
将数据隐藏起来,给使用者提供操作,使用者通过操作就可获取或修改数据,getter,setter;
通过访问控制,暴露适当的数据和操作给用户,该隐藏的隐藏起来,保护成员或私有成员;
习题:
1、随机整数生成类,可以指定一批生成的个数,可指定数值的范围,可调整每批生成数字的个数;
import random
class RandomNums:
def __init__(self,nums=10,min=0,max=100):
self.nums = nums
self.min = min
self.max = max
def create(self):
return [random.randint(self.min,self.max) for _ in range(self.nums)]
rn = RandomNums(10,0,100)
print(rn.create())
#####
#作为工具类实现,提供类方法
class RandomNums:
@classmethod
def create(cls,nums=12,min=1,max=100):
return [random.randint(min,max) for _ in range(nums)]
print(RandomNums.create())
#####
#使用生成器实现
class RandomGenerator:
def __init__(self,count=10,start=1,stop=100):
self.count = count
self.start = start
self.stop = stop
self.gen = self._generator()
def _generator(self):
while True:
yield random.randint(self.start,self.stop)
def generate(self):
return [next(self.gen) for _ in range(self.count)]
rg = RandomGenerator(10,1,100)
print(rg.generate())
#####
class RandomGenerator:
def __init__(self,count=10,start=1,stop=10):
self.count = count
self.start = start
self.stop = stop
self.gen = self._generate()
def _generate(self):
while True:
yield [random.randint(self.start,self.stop) for _ in range(self.count)]
def generate(self,count):
self.count = count
return next(self.gen)
rg = RandomGenerator()
lst = rg.generate(15)
print(lst)
2、使用上题中的类,随机生成20个数字,两两配对形成二维坐标系的坐标,把这些坐标组织起来,并打印输出;
import random
class RandomGenerator:
def __init__(self,count=10,start=1,stop=100):
self.count = count
self.start = start
self.stop = stop
self.gen = self._generate()
def _generate(self):
while True:
yield [random.randint(self.start,self.stop) for _ in range(self.count)]
def generate(self,count):
self.count = count
return next(self.gen)
class Point:
def __init__(self,x,y):
self.x = x
self.y = y
def __repr__(self):
return '{}:{}'.format(self.x,self.y)
rg = RandomGenerator()
lst = [Point(x,y) for x,y in zip(rg.generate(12),rg.generate(12))]
# for p in lst: #此方式打印,不需要Point类中的__repr__方法
# print('{}:{}'.format(p.x,p.y))
print(Point(4,5))
print(lst)
3、记录车的品牌mark、color颜色、price价格、speed速度等特征,并实现增加车辆信息,显示全部信息的功能;
class Car:
def __init__(self,mark,color,price,speed):
self.mark = mark
self.color = color
self.price = price
self.speed = speed
class CarInfo:
def __init__(self):
self.info = [] #数据在哪,方法就在哪
def addcar(self,car:Car):
self.info.append(car)
def getall(self):
return self.info
ci = CarInfo()
car = Car('audi','red',100,400)
ci.addcar(car)
print(ci.getall())
注:
修改车辆信息在Car中;
4、实现温度的处理;
摄氏温度和华氏温度的转换:
C = 5 * (F-32) / 9
F = 9 * C / 5 + 32
摄氏温度与开氏温度的转换:
K = C + 273.15
class Temperature:
def __init__(self,t,unit='c'):
self._c = None
self._f = None
self._k = None
if unit == 'f':
self._f = t
self._c = self.f2c(t)
elif unit == 'k':
self._k = t
self._c = self.k2c(t)
else:
self._c = t
@property
def c(self):
return self._c
@property
def f(self):
if self._f == None:
self._f = self.c2f(self._c)
return self._f
@property
def k(self):
if self._k == None:
self._k = self.c2k(self._c)
return self._k
@classmethod
def f2c(cls,f):
return 5*(f-32)/9
@classmethod
def f2k(cls,f):
return cls.c2k(cls.f2c(f))
@classmethod
def k2c(cls,k):
return k-273.15
@classmethod
def k2f(cls,k):
return cls.c2f(cls.k2c(k))
@classmethod
def c2k(cls,c):
return c+273.15
@classmethod
def c2f(cls,c):
return 9*c/5+32
t = Temperature(100) #实例化
print(t.c,t.f,t.k) #实例属性访问
print(t.f2c(212.0)) #实例也可以用类方法
t = Temperature(373.15,unit='k')
print(t.c,t.f,t.k)
print(Temperature.c2f(100)) #如果只是工具,就用类方法或静态方法,不用实例化;如果需要为用户保存数据,且该实例会发生变化,就要实例化
print(Temperature.c2k(100))
print(Temperature.f2k(212))
print(Temperature.f2c(212))
print(Temperature.k2c(373.15))
print(Temperature.k2f(373.15))
5、模拟购物车购物;
class Color:
RED = 0
GREEN = 1
BLUE = 2
GOLDEN = 3
BLACK = 4
OTHER = 1000
class Item:
def __init__(self,**kwargs):
self.__spec = kwargs
def __repr__(self):
return str(sorted(self.__spec.items()))
class Cart:
def __init__(self):
self.items = []
def additem(self,item:Item):
self.items.append(item)
def getall(self):
return self.items
mycart = Cart()
myphone = Item(mark = 'huawei',color = Color.GOLDEN,price=3000)
mycart.additem(myphone)
print(mycart.getall())
网页名称:27面向对象2_属性装饰器
文章位置:http://ybzwz.com/article/pegpdi.html