一、静态属性
静态属性:是将类中的函数封装,实现像调用数据属性一样的方式调用函数属性,在python中利用@property语句实现
封装的概念:使得调用者无法察觉到被调用对象的实现逻辑,就是对象的封装
1、不利用@property的方式
class Room:
def __init__(self, name, owner, width, length, height):
self.name = name
self.owner = owner
self.width = width
self.length = length
self.height = height
def cal_area(self):
print("%s住的%s,面积为%s" % (self.owner, self.name, self.width * self.length))
R1 = Room("公寓", "MB", 100, 100, 100)
R1.cal_area() # 这里可以被看出调用的是一个函数属性
结果:
MB住的公寓,面积为10000
2、利用@property的方式
class Room:
def __init__(self, name, owner, width, length, height):
self.name = name
self.owner = owner
self.width = width
self.length = length
self.height = height
@property
def cal_area(self):
return self.width * self.length # 注意为了实现和数据属性相同的调用方式,需要加入return值
R1 = Room("公寓", "MB", 100, 100, 100)
print(R1.name)
print(R1.cal_area) # 这里函数属性的调用已经完全和数据属性相同了
结果:
公寓
10000
3、property的延伸
一个静态属性property本质就是实现了get,set,delete三种方法
(1)方法一:
class Foo:
@property
def AAA(self):
print('get的时候运行我啊')
@AAA.setter
def AAA(self,value):
print('set的时候运行我啊')
@AAA.deleter
def AAA(self):
print('delete的时候运行我啊')
# 只有在属性AAA定义property后才能定义AAA.setter,AAA.deleter
f1=Foo()
f1.AAA # get的时候运行我啊
f1.AAA='aaa' # set的时候运行我啊
del f1.AAA # delete的时候运行我啊
(2)方法二:
class Foo:
def get_AAA(self):
print('get的时候运行我啊')
def set_AAA(self,value):
print('set的时候运行我啊')
def delete_AAA(self):
print('delete的时候运行我啊')
AAA=property(get_AAA,set_AAA,delete_AAA) # 内置property三个参数与get,set,delete一一对应
f1=Foo()
f1.AAA # get的时候运行我啊
f1.AAA='aaa' # set的时候运行我啊
del f1.AAA # delete的时候运行我啊
(3)案例1:
class Goods:
def __init__(self):
# 原价
self.original_price = 100
# 折扣
self.discount = 0.8
@property
def price(self):
# 实际价格 = 原价 * 折扣
new_price = self.original_price * self.discount
return new_price
@price.setter
def price(self, value):
self.original_price = value
@price.deleter
def price(self):
del self.original_price
obj = Goods()
obj.price # 获取商品价格
print("111---->",obj.price)
print("222---->",obj.__dict__)
obj.price = 200 # 修改商品原价
print("333---->",obj.__dict__)
print("444---->",obj.price)
del obj.price # 删除商品原价
print("555---->",obj.__dict__)
结果:
111----> 80.0
222----> {'original_price': 100, 'discount': 0.8}
333----> {'original_price': 200, 'discount': 0.8}
444----> 160.0
555----> {'discount': 0.8}
(4)案例2:实现类型检测功能
第一关:
p1=People(‘alex’) # property自动实现了set和get方法属于数据描述符,比实例属性优先级高,所以你这面写会触发property内置的set,抛出异常
class People:
def __init__(self,name):
self.name=name
@property
def name(self):
return self.name
p1=People('alex') # 会报错
第二关:修订版
class People:
def __init__(self,name):
self.name=name # 实例化就触发property
@property
def name(self):
# return self.name # 无限递归
print('get------>')
return self.DouNiWan
@name.setter
def name(self,value):
print('set------>')
self.DouNiWan=value
@name.deleter
def name(self):
print('delete------>')
del self.DouNiWan
p1=People('alex') # self.name实际是存放到self.DouNiWan里
print("111-->",p1.name)
print("222-->",p1.name)
print("333-->",p1.name)
print("444-->",p1.__dict__)
p1.name='egon'
print("555-->",p1.__dict__)
del p1.name
print("666-->",p1.__dict__)
结果:
111--> alex
get------>
222--> alex
get------>
333--> alex
444--> {'DouNiWan': 'alex'}
set------>
555--> {'DouNiWan': 'egon'}
delete------>
666--> {}
第三关:加上类型检查
class People:
def __init__(self,name):
self.name=name # 实例化就触发property
@property
def name(self):
# return self.name #无限递归
print('get------>')
return self.DouNiWan
@name.setter
def name(self,value):
print('set------>')
if not isinstance(value,str):
raise TypeError('必须是字符串类型')
self.DouNiWan=value
@name.deleter
def name(self):
print('delete------>')
del self.DouNiWan
p1=People('alex') # self.name实际是存放到self.DouNiWan里 # set------>
p1.name=1 # 会报错
二、类方法
类方法:是用在需要类中的函数不和实例捆绑时,即不通过实例去调用类的某个函数(函数末尾有self参数,就说明了这个函数和实例绑定。有cls参数,就说明和类绑定)
利用@classmethod语句,将某个属性只和类绑定而不和实例绑定
1、不利用@classmethod的方法
class Room:
tag = 1
def __init__(self, name, owner, width, length, height):
self.name = name
self.owner = owner
self.width = width
self.length = length
self.height = height
R1 = Room("公寓", "MB", 100, 100, 100)
print(R1.tag) # 想得出这个tag,需要产生一个实例并调用它的tag属性
结果:
1
2、利用@classmethod的方法
class Room:
tag = 1
def __init__(self, name, owner, width, length, height):
self.name = name
self.owner = owner
self.width = width
self.length = length
self.height = height
@classmethod
def tell_info(cls):
print(cls.tag)
R1 = Room("公寓", "MB", 100, 100, 100)
Room.tell_info() # python会自动将Room传给cls参数
结果:
1
通过@classmethod定义过的方法就是给类用的,R1.tell_info()虽然也可以运行,但是不规范(相当于R1将自己所属的类传入了cls)
三、静态方法
静态方法:只是名义上归属类管理,通过类和实例都可以调用,即这个属性既不和实例绑定也不和类绑定,叫做类的工具包
通过@staticmethod语句,实现类的静态方法
class Room:
def __init__(self, name, owner, width, length, height):
self.name = name
self.owner = owner
self.width = width
self.length = length
self.height = height
@staticmethod
def take_shower(name1, name2, name3):
print("%s,%s,%s is taking shower together" % (name1, name2, name3))
R1 = Room("公寓", "MB", 100, 100, 100)
Room.take_shower("CJJ", "MB", "LGJ") # 通过类可以调用
R1.take_shower("CJJ", "MB", "LGJ") # 通过实例可以调用
结果:
CJJ,MB,LGJ is taking shower together
CJJ,MB,LGJ is taking shower together
如果不写@staticmethod,例如def test():
这个函数只能通过类调用,不能实例调用
四、总结
静态属性:即可以访问实例属性,也可以访问类属性
类方法:可以访问类属性,不能访问实例属性
静态方法:不能访问类属性也不能访问实例属性