python基础----特性(property)、静态方法(staticmethod)、类。。。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
python基础----特性(property)、静态⽅法(staticmethod)、类。
⼀、特性(property)
1 什么是特性property
property是⼀种特殊的属性,访问它时会执⾏⼀段功能(函数)然后返回值
1import math
2class Circle:
3def__init__(self,radius): #圆的半径radius
4 self.radius=radius
5
6 @property
7def area(self):
8return math.pi * self.radius**2 #计算⾯积
9
10 @property
11def perimeter(self):
12return 2*math.pi*self.radius #计算周长
13
14 c=Circle(10)
15print(c.radius)
16print(c.area) #可以向访问数据属性⼀样去访问area,会触发⼀个函数的执⾏,动态计算出⼀个值
17print(c.perimeter) #同上
18'''
19输出结果:
20314.1592653589793
2162.83185307179586
22'''
注意:此时的特性arear和perimeter不能被赋值
c.area=3 #为特性area赋值
'''
抛出异常:
AttributeError: can't set attribute
'''
2 为什么要⽤property
将⼀个类的函数定义成特性以后,对象再去使⽤的时候,根本⽆法察觉⾃⼰的name是执⾏了⼀个函数然后计算出来的,这种特性的使⽤⽅式遵循了统⼀访问的原则
除此之外,看下
ps:⾯向对象的封装有三种⽅式:
【public】
这种其实就是不封装,是对外公开的
【protected】
这种封装⽅式对外不公开,但对朋友(friend)或者⼦类(形象的说法是“⼉⼦”,但我不知道为什么⼤家不说“⼥⼉”,就像“parent”本来是“⽗母”的意思,但中⽂都是叫“⽗类”)公开【private】
这种封装对谁都不公开
python并没有在语法上把它们三个内建到⾃⼰的class机制中,在C++⾥⼀般会将所有的所有的数据都设置为私有的,然后提供set和get⽅法(接⼝)去设置和获取,在python中通过property⽅法可以实现
1class Foo:
2def__init__(self,val):
3 self.__NAME=val #将所有的数据属性都隐藏起来
4
5 @property
6def name(self):
7return self.__NAME#访问的是self.__NAME(这也是真实值的存放位置)
8
9 @name.setter
10def name(self,value):
11if not isinstance(value,str): #在设定值之前进⾏类型检查
12raise TypeError('%s must be str' %value)
13 self.__NAME=value #通过类型检查后,将值value存放到真实的位置self.__NAME
15 @name.deleter
16def name(self):
17raise TypeError('Can not delete')
18
19 f=Foo('egon')
20print()
21# =10 #抛出异常'TypeError: 10 must be str'
22del #抛出异常'TypeError: Can not delete'
1class Foo:
2def__init__(self,val):
3 self.__NAME=val #将所有的数据属性都隐藏起来
4
5def getname(self):
6return self.__NAME#访问的是self.__NAME(这也是真实值的存放位置)
7
8def setname(self,value):
9if not isinstance(value,str): #在设定值之前进⾏类型检查
10raise TypeError('%s must be str' %value)
11 self.__NAME=value #通过类型检查后,将值value存放到真实的位置self.__NAME
12
13def delname(self):
14raise TypeError('Can not delete')
15
16 name=property(getname,setname,delname) #不如装饰器的⽅式清晰
17
18⼀种property的古⽼⽤法
⼀种property的古⽼⽤法
⼆、静态⽅法(staticmethod)
通常情况下,在类中定义的所有函数(注意了,这⾥说的就是所有,跟self啥的没关系,self也只是⼀个再普通不过的参数⽽已)都是对象的绑定⽅法,对象在调⽤绑定⽅法时会⾃动将⾃⼰作为参数传递给⽅法的第⼀个参数。
除此之外还有两种常见的⽅法:静态⽅法和类⽅法,⼆者是为类量⾝定制的,但是实例⾮要使⽤,也不会报错。
是⼀种普通函数,位于类定义的命名空间中,不会对任何实例类型进⾏操作,python为我们内置了函数staticmethod来把类中的函数定义成静态⽅法
class Foo:
def spam(x,y,z): #类中的⼀个函数,千万不要懵逼,self和x啥的没有不同都是参数名
print(x,y,z)
spam=staticmethod(spam) #把spam函数做成静态⽅法
基于之前所学装饰器的知识,@staticmethod 等同于spam=staticmethod(spam),于是
class Foo:
@staticmethod #装饰器
def spam(x,y,z):
print(x,y,z)
使⽤演⽰
print(type(Foo.spam)) #类型本质就是函数
Foo.spam(1,2,3) #调⽤函数应该有⼏个参数就传⼏个参数
f1=Foo()
f1.spam(3,3,3) #实例也可以使⽤,但通常静态⽅法都是给类⽤的,实例在使⽤时丧失了⾃动传值的机制
'''
<class 'function'>
2 3
3 3
'''
应⽤场景:编写类时需要采⽤很多不同的⽅式来创建实例,⽽我们只有⼀个__init__函数,此时静态⽅法就派上⽤场了
class Date:
def__init__(self,year,month,day):
self.year=year
self.month=month
def now(): #⽤Date.now()的形式去产⽣实例,该实例⽤的是当前时间
t=time.localtime() #获取结构化的时间格式
return Date(t.tm_year,t.tm_mon,t.tm_mday) #新建实例并且返回
@staticmethod
def tomorrow():#⽤Date.tomorrow()的形式去产⽣实例,该实例⽤的是明天的时间
t=time.localtime(time.time()+86400)
return Date(t.tm_year,t.tm_mon,t.tm_mday)
a=Date('1987',11,27) #⾃⼰定义时间
b=Date.now() #采⽤当前时间
c=Date.tomorrow() #采⽤明天的时间
print(a.year,a.month,a.day)
print(b.year,b.month,b.day)
print(c.year,c.month,c.day)
三、类⽅法(classmethod)
类⽅法是给类⽤的,类在使⽤时会将类本⾝当做参数传给类⽅法的第⼀个参数,python为我们内置了函数classmethod来把类中的函数定义成类⽅法class A:
x=1
@classmethod
def test(cls):
print(cls,cls.x)
class B(A):
x=2
B.test()
'''
输出结果:
<class '__main__.B'> 2
'''
应⽤场景:
import time
class Date:
def__init__(self,year,month,day):
self.year=year
self.month=month
self.day=day
@staticmethod
def now():
t=time.localtime()
return Date(t.tm_year,t.tm_mon,t.tm_mday)
class EuroDate(Date):
def__str__(self):
return'year:%s month:%s day:%s' %(self.year,self.month,self.day)
e=EuroDate.now()
print(e) #我们的意图是想触发EuroDate.__str__,但是结果为
'''
输出结果:
<__main__.Date object at 0x1013f9d68>
'''
因为e就是⽤Date类产⽣的,所以根本不会触发EuroDate.__str__,解决⽅法就是⽤classmethod
import time
class Date:
def__init__(self,year,month,day):
self.year=year
self.month=month
self.day=day
# t=time.localtime()
# return Date(t.tm_year,t.tm_mon,t.tm_mday)
@classmethod #改成类⽅法
def now(cls):
t=time.localtime()
return cls(t.tm_year,t.tm_mon,t.tm_mday) #哪个类来调⽤,即⽤哪个类cls来实例化
class EuroDate(Date):
def__str__(self):
return'year:%s month:%s day:%s' %(self.year,self.month,self.day)
e=EuroDate.now()
print(e) #我们的意图是想触发EuroDate.__str__,此时e就是由EuroDate产⽣的,所以会如我们所愿
'''
输出结果:
year:2017 month:3 day:3
'''
强调,注意注意注意:静态⽅法和类⽅法虽然是给类准备的,但是如果实例去⽤,也是可以⽤的,只不过实例去调⽤的时候容易让⼈混淆,不知道你要⼲啥x=e.now() #通过实例e去调⽤类⽅法也⼀样可以使⽤,静态⽅法也⼀样
print(x)
'''
输出结果:
year:2017 month:3 day:3
'''
四、附加知识点__str__的⽤法
#__str__定义在类内部,必须返回⼀个字符串类型,
#什么时候会出发它的执⾏呢?打印由这个类产⽣的对象时,会触发执⾏
class People:
def__init__(self,name,age):
=name
self.age=age
def__str__(self):
return'<name:%s,age:%s>' %(,self.age)
p1=People('egon',18)
print(p1)
str(p1) #----->p1.__str__()。