Python高级语法4:类对象和实例对象访问属性的区别和property属性

简介: Python高级语法4:类对象和实例对象访问属性的区别和property属性

一、再论静态方法和类方法以及实例方法



  • 1.1、类属性、实例属性它们在定义和使用中有所区别,而最本质的区别内存中保存的位置不同
  • 实例属性属于对象
  • 类属性属于类


class Province(object):
      # 类属性
      country = '中国'
      def __init__(self, name):
            # 实例属性
            self.name = name
# 创建一个实例对象
obj = Province('山东省')
# 直接访问实例属性
print(obj.name)
# 直接访问类属性
Province.country
  • 由上述代码可以看出【实例属性需要通过对象来访问】【类属性通过类访问】,在使用上可以看出 实例属性和类属性的归属是不同的
  • 类属性在内存中只保存一份
  • 实例属性在每个对象中都要保存一份
  • 应用场景:通过类创建实例对象时,如果每个对象需要具有相同名字的属性,那么就使用类属性,用一份既可
  • 1.2、实例方法、静态方法和类方法 (类里面的三种方法,区别在于调用方式不同)
  • 实例方法:由对象调用;至少一个self参数;执行实例方法时,自动将调用该方法的对象赋值给self;
  • 类方法:由类调用; 至少一个cls参数;执行类方法时,自动将调用该方法的类赋值给cls;
  • 静态方法:由类调用;无默认参数;
class Foo(object):
     def __init__(self, name):
           self.name = name
def ord_func(self):
     """ 定义实例方法,至少有一个self参数 """
     # print(self.name)
     print('实例方法')
@classmethod
def class_func(cls):
     """ 定义类方法,至少有一个cls参数 """
     print('类方法')
@staticmethod
def static_func():
     """ 定义静态方法 ,无默认参数"""
     print('静态方法')
f = Foo("中国")
# 调用实例方法
f.ord_func()
# 调用类方法
Foo.class_func()
# 调用静态方法
Foo.static_func()
  • 相同点:对于所有的方法而言,均属于类,所以 在内存中也只保存一份
  • 不同点:方法调用者不同、调用方法时自动传入的参数不同。


二、property 属性



  • 2.1、什么是property属性,在方法名的加上property就是 property属性,在调用上 dog.run 优于 dog.eat()


class Dog(object):
      def eat(self):
            print("吃")
      # 定义property属性
      @property
      def run(self):
            print("跑")
dog = Dog()
dog.eat()  # 调用实例方法
dog.run    # 调用property属性
  • property属性的定义和调用要注意一下几点:
  • 定义时,在实例方法的基础上添加 @property 装饰器;并且仅有一个self参数
  • 调用时,无需括号


方法:dog.eat() 
property属性:dog.run
  • 2.2、property属性有两种方式
  • 装饰器 即:在方法上应用装饰器
  • 类属性 即:在类中定义值为property对象的类属性
  • 2.2.1、装饰器方式在类的实例方法上应用@property装饰器,Python中的类有经典类和新式类,新式类的属性比经典类的属性丰富。( 如果类继object,那么该类是新式类
  • 经典类,具有一种@property装饰器


class Goods:
   @property
   def price(self):
        return "laowang"
# ############### 调用 ###############
obj = Goods()
result = obj.price  # 自动执行 @property 修饰的 price 方法,并获取方法的返回值
print(result)
  • 新式类,具有三种@property装饰器


# ############### 定义 ###############
class Goods:
      """python3中默认继承object类
      以python2、3执行此程序的结果不同,因为只有在python3中才有@xxx.setter  @xxx.deleter
      """
      @property
      def price(self):
           print('@property')
      @price.setter
      def price(self, value):
           print('@price.setter')
      @price.deleter
      def price(self):
           print('@price.deleter')
# ############### 调用 ###############
obj = Goods()
obj.price          # 自动执行 @property 修饰的 price 方法,并获取方法的返回值
obj.price = 123    # 自动执行 @price.setter 修饰的 price 方法,并将  123 赋值给方法的参数
del obj.price      # 自动执行 @price.deleter 修饰的 price 方法


注意

  • 经典类中的属性只有一种访问方式,其对应被 @property 修饰的方法
  • 新式类中的属性有三种访问方式,并分别对应了三个被@property、@方法名.setter、@方法名.deleter修饰的方法
  • 由于新式类中具有三种访问方式,我们可以根据它们几个属性的访问特点,分别将三个方法定义为对同一个属性:获取、修改、删除


class Goods(object):
     def __init__(self):
         # 原价
         self.original_price = 100
         # 折扣
         self.discount = 0.8
     @property
     def price(self):
         # 实际价格 = 原价 * 折扣
         new_price = self.original_price * self.discount
         return new_price
     @price.setter
     def price(self, value):
         self.original_price = value
     @price.deleter
     def price(self):
         del self.original_price
obj = Goods()
obj.price         # 获取商品价格
obj.price = 200   # 修改商品原价
del obj.price     # 删除商品原价
  • 2.2.2、类属性 方式,创建值为property对象的类属性,我比较喜欢这个方式
  • 当使用 类属性 的方式创建 property属性 时,经典类新式类 无区别


class Person:
   def get_name(self):
      return 'laowang'
   BAR = property(get_name)
obj = Person()
reuslt = obj.BAR  # 自动调用get_bar方法,并获取方法的返回值
print(reuslt)
  • property 方法中有个 四个参数
  • 第 1 个参数是方法名,调用 对象.属性 时自动触发执行方法
  • 第 2 个参数是方法名,调用 对象.属性 = XXX 时自动触发执行方法
  • 第 3 个参数是方法名,调用 del 对象.属性 时自动触发执行方法
  • 第 4 个参数是字符串,调用 对象.属性.__doc__ ,此参数是该属性的描述信息


class Person(object):
     def __init__(self,name):
          self.name = name
     def get_name(self): 
          return self.name
     def set_name(self,new_name):
          self.name = new_name
          print("设置名字为:%s"%self.name)
     def del_name(self):
          del  self.name
     BAR = property(get_name,set_name,del_name,"描述信息...")
person = Person("小王")
person.BAR      # 自动调用第一个参数中定义的方法:get_name
person.BAR = "小李" # 自动调用第二个参数中定义的方法:set_name方法,并将 "小李" 当作参数传入
person.del_name  # 自动调用第三个参数中定义的方法:del_name方法
desc = Person.BAR.__doc__   # 自动获取第四个参数中设置的值:描述信息...
print("描述是:%s"%desc)
  • 由于类属性方式创建 property属性 具有3种访问方式,我们可以根据它们几个属性的访问特点,分别将 三个方法定义为对同一个属性:获取、修改、删除,如下商品的价格


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):
        del self.original_price
    PRICE = property(get_price, set_price, del_price, '价格属性描述...')
obj = Goods()
obj.PRICE         # 获取商品价格
obj.PRICE = 200   # 修改商品原价
del obj.PRICE     # 删除商品原价
  • 2.3、Django框架中应用了property属性(了解)
    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)


综上所述


  • 定义property属性共有两种方式,分别是【装饰器】和【类属性】,而【装饰器】方式针对经典类和新式类又有所不同。
  • 通过使用property属性,能够简化调用者在获取数据的流程


目录
相关文章
|
26天前
|
测试技术 Python
【03】做一个精美的打飞机小游戏,规划游戏项目目录-分门别类所有的资源-库-类-逻辑-打包为可玩的exe-练习python打包为可执行exe-优雅草卓伊凡-持续更新-分享源代码和游戏包供游玩-1.0.2版本
【03】做一个精美的打飞机小游戏,规划游戏项目目录-分门别类所有的资源-库-类-逻辑-打包为可玩的exe-练习python打包为可执行exe-优雅草卓伊凡-持续更新-分享源代码和游戏包供游玩-1.0.2版本
101 31
【03】做一个精美的打飞机小游戏,规划游戏项目目录-分门别类所有的资源-库-类-逻辑-打包为可玩的exe-练习python打包为可执行exe-优雅草卓伊凡-持续更新-分享源代码和游戏包供游玩-1.0.2版本
|
3月前
|
存储 开发者 Python
Python 中的数据结构与其他编程语言数据结构的区别
不同编程语言都有其设计理念和应用场景,开发者需要根据具体需求和语言特点来选择合适的数据结构
118 55
|
2月前
|
存储 应用服务中间件 开发工具
对象存储OSS-Python设置代理访问请求
通过 Python SDK 配置 nginx 代理地址请求阿里云 OSS 存储桶服务。示例代码展示了如何使用 RAM 账号进行身份验证,并通过代理下载指定对象到本地文件。
113 15
|
2月前
|
数据采集 存储 XML
python实战——使用代理IP批量获取手机类电商数据
本文介绍了如何使用代理IP批量获取华为荣耀Magic7 Pro手机在电商网站的商品数据,包括名称、价格、销量和用户评价等。通过Python实现自动化采集,并存储到本地文件中。使用青果网络的代理IP服务,可以提高数据采集的安全性和效率,确保数据的多样性和准确性。文中详细描述了准备工作、API鉴权、代理授权及获取接口的过程,并提供了代码示例,帮助读者快速上手。手机数据来源为京东(item.jd.com),代理IP资源来自青果网络(qg.net)。
|
4月前
|
Java C++ Python
Python基础---类
【10月更文挑战第10天】Python类的定义
49 2
|
4月前
|
索引 Python
python-类属性操作
【10月更文挑战第11天】 python类属性操作列举
45 1
|
C# Python
Python中的module,library,package之间的区别
背景 Python中有一些基本的名词,很多人,尤其是一些初学者,可能听着就很晕。 此处,简单总结一下,module,library,package之间的大概区别。 Python中的module的简介 module,中文翻译为:模块 Python中的module,说白了,就是Python文件,而python文件一般后缀为py,所以就是你的xxx.py而已。
1750 0
|
2月前
|
人工智能 数据可视化 数据挖掘
探索Python编程:从基础到高级
在这篇文章中,我们将一起深入探索Python编程的世界。无论你是初学者还是有经验的程序员,都可以从中获得新的知识和技能。我们将从Python的基础语法开始,然后逐步过渡到更复杂的主题,如面向对象编程、异常处理和模块使用。最后,我们将通过一些实际的代码示例,来展示如何应用这些知识解决实际问题。让我们一起开启Python编程的旅程吧!
|
2月前
|
存储 数据采集 人工智能
Python编程入门:从零基础到实战应用
本文是一篇面向初学者的Python编程教程,旨在帮助读者从零开始学习Python编程语言。文章首先介绍了Python的基本概念和特点,然后通过一个简单的例子展示了如何编写Python代码。接下来,文章详细介绍了Python的数据类型、变量、运算符、控制结构、函数等基本语法知识。最后,文章通过一个实战项目——制作一个简单的计算器程序,帮助读者巩固所学知识并提高编程技能。
|
2月前
|
Unix Linux 程序员
[oeasy]python053_学编程为什么从hello_world_开始
视频介绍了“Hello World”程序的由来及其在编程中的重要性。从贝尔实验室诞生的Unix系统和C语言说起,讲述了“Hello World”作为经典示例的起源和流传过程。文章还探讨了C语言对其他编程语言的影响,以及它在系统编程中的地位。最后总结了“Hello World”、print、小括号和双引号等编程概念的来源。
126 80

热门文章

最新文章