您的位置:首页 > 其它

属性的两种定义方式

2016-03-02 21:46 344 查看
属性的定义有两种方式

装饰器 即:在方法上应用装饰器

静态字段 即:在类中定义值为property对象的静态字段

[b]装饰器方式:在类的普通方法上应用@property装饰器[/b]

新式类:我们知道Python中的类有经典类和新式类,新式类的属性比经典类的属性丰富。( 如果类继object,那么该类是新式类 )

class Goods(object):
def __init__(self):
self.original_price = 100 #普通字段
self.dicount_rate = 0.8   #普通字段
@property                    #获取属性
def price(self):
new_price = self.original_price * self.dicount_rate
return new_price

@price.setter           #方法名.setter 修改属性
def price(self,value):
self.original_price = value
@price.deleter        #方法名.deleter 删除
def price(self):
del self.original_price
###########调用#########
good_ojb =Goods()

o = good_ojb.price # 自动执行 @property 修饰的 price 方法,并获取方法的返回值
s = good_ojb.price = 200 # 自动执行 @price.setter 修饰的 price 方法,并将  200 赋值给方法的参数

print(o)
print(s)
del good_ojb.price # 自动执行 @price.deleter 修饰的 price 方法

good_ojb.price  #再次执行,发现报错提示:'Goods' object has no attribute 'original_price'


经典类:

# ############### 定义 ###############
class Goods:

@property
def price(self):
return "wupeiqi"
# ############### 调用 ###############
obj = Goods()
result = obj.price  # 自动执行 @property 修饰的 price 方法,并获取方法的返回值


注:经典类中的属性只有一种访问方式,其对应被 @property 修饰的方法

新式类中的属性有三种访问方式,并分别对应了三个被@property、@方法名.setter、@方法名.deleter修饰的方法

由于新式类中具有三种访问方式,我们可以根据他们几个属性的访问特点,分别将三个方法定义为对同一个属性:获取、修改、删除

---------------------------------------------------------------------

[b]静态字段方式,创建值为property对象的静态字[/b]

[b]当使用静态字段的方式创建属性时,经典类和新式类无区别[/b]

class Poo:

def get_bar(self):
return 'wupeiqi'

BAR = property(get_bar)

obj = Poo()
reuslt = obj.BAR        # 自动调用get_bar方法,并获取方法的返回值
print (reuslt)


property的构造方法中有个四个参数

第一个参数是方法名,调用
对象.属性
时自动触发执行方法

第二个参数是方法名,调用
对象.属性 = XXX
时自动触发执行方法

第三个参数是方法名,调用
del 对象.属性
时自动触发执行方法

第四个参数是字符串,调用
对象.属性.__doc__
,此参数是该属性的描述信息

class Foo():

def get_bar(self):
return ('wupeiqi')

# *必须两个参数
def set_bar(self, value):
return ('set value' + value)

def del_bar(self):
return ('wupeiqi')

BAR  = property(get_bar, set_bar, del_bar, 'description...')

obj = Foo()

obj.BAR            # 自动调用第一个参数中定义的方法:get_bar
obj.BAR="alex"   # 自动调用第二个参数中定义的方法:set_bar方法,并将“alex”当作参数传入
del obj.BAR          # 自动调用第三个参数中定义的方法:del_bar方法

obj.BAR.__doc__    # 自动获取第四个参数中设置的值:description...


由于静态字段方式创建属性具有三种访问方式,我们可以根据他们几个属性的访问特点,分别将三个方法定义为对同一个属性:获取、修改、删除

可对比@property装饰器的那三种方法

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     # 删除商品原价


注意: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)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: