189 8069 5689

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())

另外有需要云服务器可以了解下创新互联cdcxhl.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。


分享名称:27面向对象2_属性装饰器-创新互联
链接URL:http://cdxtjz.cn/article/dcsjji.html

其他资讯