python中的property及属性与特性之间的优先权

目录
  • 前言
  • 属性(attribute)
    • 属性的定义
  • 属性的用法
  • 特性(property)
    • 特性的定义
    • 特性的用法
    • 特性的使用场景
  • 属性和特性之间的差别和联系
  • 属性和特性之间的优先权

前言

这几天看《流畅的python》这本书了,在一个示例中又看到了property作为装饰器在使用,因为很久没有用这个东西了,对它的一些特性和使用方法等都不是很熟悉,所以又专门在搜了几篇博客和在官方文档中学习了它的相关用法。再者又刚好学到了python中的属性(attribute),所以刚好这两者可以两相对比,也许更好理解!

属性(attribute)

属性的定义

在python中,属性其实是(对象的)属性和(对象的)方法的集合。

一开始我以为就是:属性就是属性,方法就是方法,一个是“属性”,一个是行为,但是在打开IDE写了一个测试案例后,我就信服了:

# python中数据的属性和处理数据的方法统称为属性
class Cat:

    def __init__(self, name):
        self.name = name

    def run(self):
        print('小碎步...')

if __name__ == '__main__':
    tom = Cat('Tom')
    print(tom.__getattribute__('name'))  # 对象的属性
    print(tom.__getattribute__('run'))  # 对象的方法

在这里我定义了一个类,同时在初始化方法中为它添加了一个属性name,然后定义了一个run方法,之后在main方法里创建了tom这个实例,使用__getattribute__()方法来获取它的name属性和run属性,果不其然,居然真的都获取到了!

所以,以后再也不要说属性只是单纯的“属性”了!

属性的用法

属性用法很简单,不管是对象的属性还是方法,都是用.来获取或者调用。

1.设置或修改对象的属性

tom.name='Tom' #设置(修改)对象tom的name属性值为Tom

2.删除对象的属性

del tom.name #使用del关键字删除对象的属性

可以看到,属性删除后就不能再获取了。

3.调用对象的方法(属性)

tom.run() #直接用.调用即可

4.对象的方法置None

对象的方法我们无法删除,但是我们可以将其置为None。

tom.run=None

特性(property)

特性的定义

个人理解:特性就是属性的特例,因为预先知道某些属性的一些特定条件,比如取值范围,类型等等,所以在对这些属性进行操作的时候,为了在操作前后,保持一些特定条件不变(就是不准越界操作),所以就有了特性来约束它。

来看一下官方文档给的例子:

官方文档中提到:一个典型的例子就是托管x(这里的x是一个类的属性), 使用方法也特别的直接明了:如果 c 为 C 的实例,c.x 将调用 getter,c.x = value 将调用 setter, del c.x 将调用 deleter。就是在对c.x这个属性进行操作时,可以通过getter,setter,delx来控制它的修改和删除。

特性的用法

因为它是一个修饰器,所以调用方法有两种:

1.直接使用@符号调用

class Dog:

    def __init__(self):
        self.__name = None

    @property
    def name(self):
        print('调用了get_name方法...')
        return self.__name
    @name.setter
    def name(self, val):
        print('调用了set_name方法...')
        self.__name = val
    @name.deleter
    def name(self):
        print('调用了del_name方法...')
        del self.__name
if __name__ == '__main__':
    tom = Dog()
    tom.name = 'Tom'
    print(tom.name)
    del tom.name

2.当做一个正常的函数使用

class Cat:
    def __init__(self):
        self.__name = None
    def set_name(self, name):
        print('调用了set_name方法...')
        self.__name = name

    def get_name(self):
        print('调用了get_name方法...')

        return self.__name

    def del_name(self):
        print('调用了del_name方法...')
        del self.__name
    name = property(get_name, set_name, del_name, 'this is a property name.')
if __name__ == '__main__':
    tom = Cat()
    tom.name = 'Tom'
    print(tom.name)
    del tom.name

可以看到两种方法使用的效果都是一样的!

特性的使用场景

重点讲一下这个,正是因为有一些特定场景的存在,才会出现property这个特性的,正如之前在《Django企业开发实战》一书中所说的那样:若无必要,勿增实体。而python向来以简洁优雅著称,因为这些特定场景,所以是有必要增加property这个实体的。

主要使用场景有两个:

1.限制一些属性为只读

在只使用@property修饰某个方法后,将其变成特定的属性,如果不添加setter和deleter方法,那么它就变成了只读属性。比如:用户名设置后就不允许修改:

class User:

    def __init__(self, username, password):
        self.__username = username
        self.password = password

    # 将username属性限定为只读
    @property
    def username(self):
        return self.__username
if __name__ == '__main__':
    tom=User('tom','1234')
    print(tom.username)
    tom.username='Tom'

可以看到在只读状态下,修改和删除属性都会失败!

2.限定属性的操作范围

生活中,你可能会遇到这样的情况,有一天你告诉你妈你想吃鱼,并且是红烧鱼而不是清蒸鱼,然后你妈命令你爸去买鱼,同时你妈嘱咐你爸说:买新鲜一点的啊,价格贵一点没关系!然后你爸心想:这个月工资还没发呢,能省省就省省吧,于是你爸在心中就大概确定了买一条鱼的开销区间(比如30到100)。可以看到在一条鱼上餐桌之前,你和你爸妈是对它进行了精挑细选,才得以上到你的餐桌,其实就是对鱼这个属性增加了一些条件限定:类型的限定:要红烧的而不是清蒸的;取值范围的限定:不能太贵也不能太便宜,30到100之前刚刚好。

接下来用代码实现一下这个栗子:

class Fish:

    def __init__(self):
        self.__price = None
        self.__cook = None
    @property
    def price(self):
        return self.__price
    @price.setter
    def price(self, pri):

        if not isinstance(pri, int):
            raise ValueError('价格有误!')
        if pri < 30:
            raise ValueError('太便宜了,不要!')
        elif pri > 100:
            raise ValueError('太贵了,不要!')
        else:
            self.__price = pri
            print('价格刚刚好!')
    @property
    def cook(self):
        return self.__price

    @cook.setter
    def cook(self,method):

        if method!='红烧':
            raise ValueError('我只要红烧鱼!')
        else:
            print('耶,我最爱的红烧鱼!')
if __name__ == '__main__':
    luck_fish=Fish()
    luck_fish.price=60
    # luck_fish.cook='清蒸'
    luck_fish.cook='红烧'

可以看到,只有当属性的取值返回和类型是规定的范围之内的时候,程序才会正常执行,而生活中类似这样的栗子很多,所以这也是特性存在的意义。

属性和特性之间的差别和联系

直观的看,特性的目的好像是把方法“属性化”,但这样做一点意义也没有,如果我可以定义一个属性,何必再额外定义一个方法,然后将其转化成属性呢?所以,更重要的目的就是应对一些特定场景。

从特性表现出来的性质和行为来看,它其实就是一种特定的“属性”。只不过特性的权利提升了一点点,就好像你可以去修改这个属性,但是能不能修改成功,就看你的上一级允不允许你修改(有没有给你这个属性添加限定条件),而特性的权利就扩展到了这个“上一级”。

属性和特性之间的优先权

在写程序的时候,也不乏会出现这样的例子:属性和特性之间重名了!那么这个时候在使用这个重名的属性(特性)时,程序是会报错?还是会使用属性的值?还是会使用特性的值?也许根据它们的名称就可以猜出来,特性嘛,肯定就特别一些嘛,所以会优先使用特性的值!下面这个栗子完美说明:

# 关系:在同名的情况下,实例属性会覆盖类属性,特性会覆盖实例属性

class Cat:
    @property
    def wow(self):
        return 'property---喵~'
if __name__ == '__main__':
    # 实例属性会覆盖类属性
    jerry = Cat()

    # 特性会覆盖实例属性
    print(jerry.__dict__)  # 查看对象的属性字典
    jerry.__dict__['wow'] = 'normal---喵~'
    print(jerry.__dict__)
    print(jerry.wow)  # 虽然修改了jerry的wow的值,但是依旧返回的是其特性的值
    print(jerry.__dict__['wow'])
    del Cat.wow  # 删除类特性后,返回的就是正常的属性值
    # del Cat.wow  # 删除特性
    print(jerry.wow)
    Cat.wow = property(lambda self: 'add a property---喵~')  # 为类新增和属性同名的特性
    print(jerry.wow)  # 之后还是优先访问特性的值

到此这篇关于python中的property及属性与特性之间的优先权的文章就介绍到这了,更多相关python property 内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Python 使用@property对属性进行数据规范性校验的实现

    在绑定属性时,如果我们直接把属性暴露出去,虽然写起来很简单,但是,没办法检查参数,导致可以把成绩随便改: s = Student() s.score = 9999 这显然不合逻辑.为了限制score的范围,可以通过一个​​set_score()​​方法来设置成绩,再通过一个​​get_score()​​来获取成绩,这样,在​​set_score()​​方法里,就可以检查参数: class Student(object): def get_score(self): return self._sco

  • python中的property及属性与特性之间的优先权

    目录 前言 属性(attribute) 属性的定义 属性的用法 特性(property) 特性的定义 特性的用法 特性的使用场景 属性和特性之间的差别和联系 属性和特性之间的优先权 前言 这几天看<流畅的python>这本书了,在一个示例中又看到了property作为装饰器在使用,因为很久没有用这个东西了,对它的一些特性和使用方法等都不是很熟悉,所以又专门在搜了几篇博客和在官方文档中学习了它的相关用法.再者又刚好学到了python中的属性(attribute),所以刚好这两者可以两相对比,也许

  • Python中关于property使用的小技巧

    目录 property属性 具体实例 property属性的有两种方式 装饰器方式 旧式类 新式类 类属性方式 property对象与@property装饰器对比 property对象类属性 @property装饰器 property属性 一种用起来像是使用实例属性一样的特殊属性,可以对应于某个方法 既要保护类的封装特性,又要让开发者可以使用 对象.属性 的方式操作方法,@property 装饰器,可以直接通过方法名来访问方法,不需要在方法名后添加一对 () 小括号. 来看下求圆的面积的例子 c

  • python中关于property的最详细使用方法

    为什么要写这篇文章 其实是因为最近学到了python的property装饰器的相关知识,刚开始学得云里雾里,于是乎,看了许多相关博客,不巧,大概是自己基础不太好吧,真心感觉许多人写的太过深奥,而且不是很全面.于是本人花了整整一下午实验,现在将关于property的相关知识分享出来.如有错误之处,还望各位不吝赐教! 什么是property装饰器 顾名思义,这是一个装饰器,起到一个辅助作用,具体理解请看下面一个例子.我们知道,程序中有许多变量都有范围的限制,比如年龄,工资,身高等不可能为负数.但是用

  • python 中的@property的用法详解

    目录 1.什么是property 2.property属性定义的两种方式 3.用property代替getter和setter方法 1.什么是property 简单地说就是一个类里面的方法一旦被@property装饰,就可以像调用属性一样地去调用这个方法,它能够简化调用者获取数据的流程,而且不用担心将属性暴露出来,有人对其进行赋值操作(避免使用者的不合理操作).需要注意的两点是 调用被装饰方法的时候是不用加括号的 方法定义的时候有且只能有self一个参数 >>> class Goods(

  • python中@Property属性使用方法

    目录 一.前言 二.创建用于计算的属性 三.为属性添加安全保护机制 一.前言 本文介绍的属性与类属性和实例属性不同.类属性和实例属性介绍的属性将返回所存储的值.而本文要介绍的属性是一种特殊的属性,访问它时将计算它的值.另外,该属性还可以为属性添加安全保护机制. 二.创建用于计算的属性 在Python中,可以通过@property(装饰器)将一个方法转换为属性,从而实现用于计算的属性.将方法转换为属性后,可以直接通过方法名来访问方法,而不需要再添加一对小括号“()”,这样可以让代码更简洁. 通过@

  • 详解Python装饰器之@property

    一.property() 函数讲解 了解 @property 装饰器之前,我们首先要了解内置函数的 property(). class property(fget=None, fset=None, fdel=None, doc=None) 描述: 返回 property 属性. 参数说明: fget -- 获取属性值的函数. fset -- 设置属性值的函数. fdel -- 删除属性值函数. doc -- property 属性的文档字符串,如果没有给出 doc,则该 property 将拷贝

  • 一文详述 Python 中的 property 语法

    property() 函数的作用是在新式类中返回属性值. Python中有一个property的语法,它类似于C#的get set语法,其功能有以下两点: 将类方法设置为只读属性: 实现属性的getter和setter方法: 下面开始本文的重点介绍,Python 中的 property 语法介绍,具体内容如下所示: 在大多数语言的程序中,一个类,每有一个属性,就会对应 setter 和 getter,基本都是标配. 示例: class Money(object): def __init__(se

  • python中模块的__all__属性详解

    python模块中的__all__属性,可用于模块导入时限制,如: from module import * 此时被导入模块若定义了__all__属性,则只有__all__内指定的属性.方法.类可被导入. 若没定义,则导入模块内的所有公有属性,方法和类 # kk.py class A(): def __init__(self,name,age): self.name=name self.age=age class B(): def __init__(self,name,id): self.nam

  • python中string模块各属性以及函数的用法介绍

    任何语言都离不开字符,那就会涉及对字符的操作,尤其是脚本语言更是频繁,不管是生产环境还是面试考验都要面对字符串的操作. python的字符串操作通过2部分的方法函数基本上就可以解决所有的字符串操作需求: • python的字符串属性函数 • python的string模块 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1.字符串属性函数  系统版本:CentOS release 6.2 (Final)2.6.32-220.

  • Python中关于面向对象私有属性方法的详细讲解

    目录 1.私有属性和私有方法 私有属性: 私有方法: 类部调用私有属性和私有方法 子类不能继承父类私有属性和方法 实例属性(对象属性) 通过实例(对象)去修改类属性 2.修改私有属性的值 3.类属性和实例属性 4.类方法和静态方法 类方法: 静态方法: 实例方法 5.__new__方法 6.单例模式 福利 1.私有属性和私有方法 封装的意义: 将属性和方法放到一起做为一个整体,然后通过实例化对象来处理: 隐藏内部实现细节,只需要和对象及其属性和方法交互就可以了: 对类的属性和方法增加 访问权限控

  • Python中bytes字节串和string字符串之间的转换方法

    目录 背景 代码 代码说明: 验证一下 附:bytes和string区别 总结 背景 在工作中经常会碰到字节串(bytes)与字符串(string)之间转换的问题,做个记录. bytes只负责用字节序列的形式(二进制形式)存储数据,不关心数据本身是图片.文字.视频等等.如果需要使用并且展示的话,按照对应的解析规则处理,就可以拿到对应类型的数据.如常见的字符串类型,只需要使用对应的字符编码格式,就可以拿到字符串的内容. 下面会用一些代码来表示bytes的构造,以及和字符串之间的转换. 代码 先看一

  • Python中如何获取类属性的列表

    前言 最近工作中遇到个需求是要得到一个类的静态属性,也就是说有个类 Type ,我要动态获取 Type.FTE 这个属性的值. 最简单的方案有两个: getattr(Type, 'FTE') Type.__dict__['FTE'] 那么,如果要获取类属性的列表,该怎么做呢? 首先上场的是 dir ,它能返回当前范围的所有属性名称列表: >>> dir() ['__builtins__', '__doc__', '__name__', '__package__'] >>>

随机推荐