• 属性的两种定义方式


    属性的定义有两种方式

    • 装饰器 即:在方法上应用装饰器
    • 静态字段 即:在类中定义值为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)
    
  • 相关阅读:
    C++静态库与动态库(转)
    Tornado异步
    Yacc与Lex
    云数据库
    linux如何查看端口被谁占用
    Innodb Double Write
    MySQL GTIDs(global transaction identifiers)
    Java并发编程:线程池的使用
    Oracle 建立索引及SQL优化
    解决redhat linux下IP地址可以ping通,域名无法ping通问题
  • 原文地址:https://www.cnblogs.com/alan-babyblog/p/5236636.html
Copyright © 2020-2023  润新知