【python】面向对象之类成员(属性)

  • 1.属性的定义
    • 1.1:属性的定义有两种方式:
      • 装饰器 即:在方法上应用装饰器
      • 静态字段 即:在类中定义值为property对象的静态字段
    • 1.2:装饰器方式
      • 在类的普通方法上应用@property装饰器
      • 经典类
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)
posted @ 2024-08-21 22:27  Tony_xiao  阅读(2)  评论(0编辑  收藏  举报