- 1.屬性的定義
- 1.1:屬性的定義有兩種方式:
- 裝飾器 即:在方法上應用裝飾器
- 靜態欄位 即:在類中定義值為property物件的靜態欄位
- 1.2:裝飾器方式
- 在類的普通方法上應用@property裝飾器
- 經典類
- 1.1:屬性的定義有兩種方式:
class Goods:
@property
def price(self):
return "xwl"
# ############### 呼叫 ###############
obj = Goods()
result = obj.price # 自動執行 @property 修飾的 price 方法,並獲取方法的返回值
print(result) # xwl
- 新式類
# ############### 定義 ###############
class Goods(object):
@property
def price(self):
return '@property'
@price.setter
def price(self, value):
print(value)
return '@price.setter'
@price.deleter
def price(self):
return '@price.deleter'
# ############### 呼叫 ###############
obj = Goods()
print(obj.price) # 自動執行 @property 修飾的 price 方法,並獲取方法的返回值
obj.price = 123 # 自動執行 @price.setter 修飾的 price 方法,並將 123 賦值給方法的引數
del obj.price # 自動執行 @price.deleter 修飾的 price 方法
-
1.3:注意
- 經典類中的屬性只有一種訪問方式,其對應被 @property 修飾的方法
- 新式類中的屬性有三種訪問方式,並分別對應了三個被@property、@方法名.setter、@方法名.deleter修飾的方法
- 由於新式類中具有三種訪問方式,我們可以根據他們幾個屬性的訪問特點,分別將三個方法定義為對同一個屬性:獲取、修改、刪除
-
2.屬性的使用
- 2.1:當使用靜態欄位的方式建立屬性時,經典類和新式類無區別
- 2.2:property的構造方法中有個四個引數
- 第一個引數是方法名,呼叫 物件.屬性 時自動觸發執行方法
- 第二個引數是方法名,呼叫 物件.屬性 = XXX 時自動觸發執行方法
- 第三個引數是方法名,呼叫 del 物件.屬性 時自動觸發執行方法
- 第四個引數是字串,呼叫 物件.屬性.doc ,此引數是該屬性的描述資訊
class Foo:
def get_bar(self):
return 'xwl'
# *必須兩個引數
def set_bar(self, value):
print('set value' + value)
return 'set value' + value
def del_bar(self):
print('del bar')
return 'xwl'
BAR = property(get_bar, set_bar, del_bar, 'description...')
obj = Foo()
print(obj.BAR) # 自動呼叫第一個引數中定義的方法:get_bar
obj.BAR = "gmm" # 自動呼叫第二個引數中定義的方法:set_bar方法,並將“gmm”當作引數傳入
del obj.BAR # 自動呼叫第三個引數中定義的方法:del_bar方法
obj.BAR.__doc__ # 自動獲取第四個引數中設定的值:description...
- 2.3:示例1
class Goods(object):
def __init__(self):
# 原價
self.original_price = 100
# 折扣
self.discount = 0.8
def get_price(self):
# 實際價格 = 原價 * 折扣
new_price = self.original_price * self.discount
return new_price
def set_price(self, value):
self.original_price = value
def del_price(self, value):
del self.original_price
PRICE = property(get_price, set_price, del_price, '價格屬性描述...')
obj = Goods()
obj.PRICE # 獲取商品價格
obj.PRICE = 200 # 修改商品原價
del obj.PRICE # 刪除商品原價
- 示例2,Python WEB框架 Django 的檢視中 request.POST 就是使用的靜態欄位的方式建立的屬性
class WSGIRequest(http.HttpRequest):
def __init__(self, environ):
script_name = get_script_name(environ)
path_info = get_path_info(environ)
if not path_info:
# Sometimes PATH_INFO exists, but is empty (e.g. accessing
# the SCRIPT_NAME URL without a trailing slash). We really need to
# operate as if they'd requested '/'. Not amazingly nice to force
# the path like this, but should be harmless.
path_info = '/'
self.environ = environ
self.path_info = path_info
self.path = '%s/%s' % (script_name.rstrip('/'), path_info.lstrip('/'))
self.META = environ
self.META['PATH_INFO'] = path_info
self.META['SCRIPT_NAME'] = script_name
self.method = environ['REQUEST_METHOD'].upper()
_, content_params = cgi.parse_header(environ.get('CONTENT_TYPE', ''))
if 'charset' in content_params:
try:
codecs.lookup(content_params['charset'])
except LookupError:
pass
else:
self.encoding = content_params['charset']
self._post_parse_error = False
try:
content_length = int(environ.get('CONTENT_LENGTH'))
except (ValueError, TypeError):
content_length = 0
self._stream = LimitedStream(self.environ['wsgi.input'], content_length)
self._read_started = False
self.resolver_match = None
def _get_scheme(self):
return self.environ.get('wsgi.url_scheme')
def _get_request(self):
warnings.warn('`request.REQUEST` is deprecated, use `request.GET` or '
'`request.POST` instead.', RemovedInDjango19Warning, 2)
if not hasattr(self, '_request'):
self._request = datastructures.MergeDict(self.POST, self.GET)
return self._request
@cached_property
def GET(self):
# The WSGI spec says 'QUERY_STRING' may be absent.
raw_query_string = get_bytes_from_wsgi(self.environ, 'QUERY_STRING', '')
return http.QueryDict(raw_query_string, encoding=self._encoding)
# ############### 看這裡看這裡 ###############
def _get_post(self):
if not hasattr(self, '_post'):
self._load_post_and_files()
return self._post
# ############### 看這裡看這裡 ###############
def _set_post(self, post):
self._post = post
@cached_property
def COOKIES(self):
raw_cookie = get_str_from_wsgi(self.environ, 'HTTP_COOKIE', '')
return http.parse_cookie(raw_cookie)
def _get_files(self):
if not hasattr(self, '_files'):
self._load_post_and_files()
return self._files
# ############### 看這裡看這裡 ###############
POST = property(_get_post, _set_post)
FILES = property(_get_files)
REQUEST = property(_get_request)