属性的两种定义方式
属性的定义有两种方式:
- 装饰器 即:在方法上应用装饰器
- 静态字段 即:在类中定义值为property对象的静态字段
装饰器方式:在类的普通方法上应用@property装饰器
新式类:我们知道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修饰的方法
由于新式类中具有三种访问方式,我们可以根据他们几个属性的访问特点,分别将三个方法定义为对同一个属性:获取、修改、删除
---------------------------------------------------------------------
静态字段方式,创建值为property对象的静态字
当使用静态字段的方式创建属性时,经典类和新式类无区别
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)
    我可以输,但我不会认输
 
                    
                
 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号