一、@property
引用自:https://blog.csdn.net/u014595019/article/details/49725727
1. 未使用@property的实例
class Exam(object):
def __init__(self, score):
self._score = score
def get_score(self):
return self._score
def set_score(self, val):
if val < 0:
self._score = 0
elif val > 100:
self._score = 100
else:
self._score = val
>>> e = Exam(60)
>>> e.get_score()
60
>>> e.set_score(70)
>>> e.get_score()
70
获取、设置class中的参数
2. 通过@property优化
class Exam(object):
def __init__(self, score):
self._score = score
@property
def score(self):
return self._score
@score.setter
def score(self, val):
if val < 0:
self._score = 0
elif val > 100:
self._score = 100
else:
self._score = val
>>> e = Exam(60)
>>> e.score
60
>>> e.score = 90
>>> e.score
90
>>> e.score = 200
>>> e.score
100
score(self)用来获取
score(self, val)用来进行参数设置
3.不使用 score.setter 装饰器
score就只有一个只读属性
class Exam(object):
def __init__(self, score):
self._score = score
@property
def score(self):
return self._score
>>> e = Exam(60)
>>> e.score
60
>>> e.score = 200 # score 是只读属性,不能设置值
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-676-b0515304f6e0> in <module>()
----> 1 e.score = 200
AttributeError: can't set attribute
4.小结
@property 把方法『变成』了属性。
二、@staticmethod && @classmethod
引用自: https://zhuanlan.zhihu.com/p/28010894
1. demo
class A(object):
def m1(self, n):
print("self:", self)
@classmethod
def m2(cls, n):
print("cls:", cls)
@staticmethod
def m3(n):
pass
a = A()
a.m1(1) # self: <__main__.A object at 0x000001E596E41A90>
A.m2(1) # cls: <class '__main__.A'>
A.m3(1)
2. 说明
a) m1 :实例方法,第一个参数必须是 self(约定俗成的)
b) m2 :类方法,第一个参数必须是cls(同样是约定俗成)
c) m3 :静态方法
3. 运行顺序
- 执行 class 命令:此时会创建一个类 A 对象,初始化类里面的属性和方法
此刻实例对象还没创建出来 - a=A(): 调用类的构造器,构造出实例对象 a
- a.m1(1) :把实例对象传递给 self 参数进行绑定
-
A.m2(1) :类对象传递给 cls 参数,cls 和 A 都指向类对象
image.png
4. 使用场景
@staticmethod
当方法中不需要访问任何实例方法和属性,纯粹地通过传入参数并返回数据的功能性方法。
它节省了实例化对象的开销成本,往往这种方法放在类外面的模块层作为一个函数存在也是没问题的,而放在类中,仅为这个类服务。
demo:
from hashlib import sha1
import tornado.web
class SignatureHandler(tornado.web.RequestHandler):
def get(self):
"""
根据签名判断请求是否来自微信
"""
signature = self.get_query_argument("signature", None)
echostr = self.get_query_argument("echostr", None)
timestamp = self.get_query_argument("timestamp", None)
nonce = self.get_query_argument("nonce", None)
if self._check_sign(TOKEN, timestamp, nonce, signature):
logger.info("微信签名校验成功")
self.write(echostr)
else:
self.write("你不是微信发过来的请求")
@staticmethod
def _check_sign(token, timestamp, nonce, signature):
sign = [token, timestamp, nonce]
sign.sort()
sign = "".join(sign)
sign = sha1(sign).hexdigest()
return sign == signature
@classmethod
作为工厂方法创建实例对象,例如内置模块 datetime.date 类中就有大量使用类方法作为工厂方法,以此来创建date对象
demo:
class date:
def __new__(cls, year, month=None, day=None):
self = object.__new__(cls)
self._year = year
self._month = month
self._day = day
return self
@classmethod
def fromtimestamp(cls, t):
y, m, d, hh, mm, ss, weekday, jday, dst = _time.localtime(t)
return cls(y, m, d)
@classmethod
def today(cls):
t = _time.time()
return cls.fromtimestamp(t)
注意事项
如果希望在方法裡面调用静态类,那么把方法定义成类方法是合适的,因为要是定义成静态方法,那么你就要显示地引用类A,这对继承来说可不是一件好事情
class A:
@staticmethod
def m1()
pass
@staticmethod
def m2():
A.m1() # bad
@classmethod
def m3(cls):
cls.m1() # good
网友评论