今天学习python类看到 @property 的用法觉得很新奇,就自己尝试了很久,刚开始不明白,后来终于明白了点

其实总结一句话就是, @property 把类中的方法调用方式改变成当成属性属性调用方式了,调用方式改变了,作用没变,说的总归没实践明白,来看栗子

class Student:
def __init__(self, name, score):
self.name = name
self.score = score s = Student("jacks", 99)
print(s.name)
print(s.score)

上面是一个很普通的类,并且实例化了

执行结果也很明显就是

jacks

99

然后我们很容易更改这个score分数,比如这样

s.score = 101
print(s.score)

101

你觉得这样合理吗,虽然python很自由,但是有些变量总归不想让人随便更改,那么怎么办呢?我们可以使用私有变量,然后就变化为如下代码

class Student:
def __init__(self, name, score):
self.name = name
self.__score = score
def get_score(self):
return self.__score
def set_score(self, score):
try:
if 0 < score <100:
self.__score = score
else:
print("Out of range")
except TypeError:
print("Only int value")

以上代码不仅隐藏了score变量,更给这个变量赋值增加了判断,超出100或者小于0或者字符串都是不合法的。

并且实例私有变量私有化后,是不能直接赋值,同时也不能直接被拿到,我们来测试下

s = Student("bob", 99)
#实例化一个类
print(s.name)
print(s.__score)
#打印实例name属性和__score
print(s.name)
print(s.__score)
#来看结果
bob
Traceback (most recent call last):
File "E:/python_learn/learn1.py", line 19, in <module>
print(s.__score)
AttributeError: 'Student' object has no attribute '__score'
#报错了,找不到__score

为什么直接打印不了私有变量呢,因为被隐藏了,需要用上面的get_score方法来调用,我们来测试下

s = Student("bob", 99)
print(s.name)
#调用实例的get_score方法
print(s.get_score())
#来看下结果
bob
99
#我们得到了正确结果

那么我们怎么来修改这个私有变量呢?上面已经测试过了,直接调用私有变量都不行,那么直接修改肯定也是不可以的

那么我们就需要写一个set_score方法来修改这个私有变量了,然后用实例调用这个方法来修改私有变量

#调用实例的set_score方法
s.set_score(88)
print(s.get_score())
#来看结果
88
#已经成功修改了score的值

上面的每次修score值和调用score的值是不是很麻烦?每次都要调用实例方法?有没有一种简便的方法呢?答案是有的,那就是 使用 @property,把实例调用方法的方式变成调用属性一样简单,上面铺垫了那么多就是为了下面的一刻,先来看代码

class Student:
def __init__(self, name, score):
self.name = name
self.__score = score
@property
def get_score(self):
return self.__score
@get_score.setter
def set_score(self, score):
try:
if 0 < score <100:
self.__score = score
else:
print("Out of range")
except TypeError:
print("Only int value")
s = Student("bob", 99)
#实例化一个类
print(s.get_score)
#打印私有变量__score有没有感觉调用方式的不同?有就对了,以前调用方式这样的 print(s.get_score()) 是调用方法的方式,现在是用属性调用的方式
s.set_score = 89
#同上,以前设置私有__score是用 s.set_score(89)这样的调用方法方式,现在也是用属性赋值的方式
print(s.get_score)
#打印私有__score的值,同上,调用方法也不同了
89
#值改变了

所以这就是 @property 的神奇之处,把一个实例的方法的使用方式变成属性的使用方式,简便了很多

至于  @get_score.setter 在上面使用 @property 就会产生这个setter的子类

@property 等价于 上面的get_score方法

@get_score.setter 等价于上面的set_score方法

同样的,上面代码中,无论是方法调用方式还是属性调用方式,定义在类中的方法名或者叫做后来的属性名在你的实例调用时候一定要与代码中相同,即红色的部分

下面代码和上面相同的只是方法名变了,实例调用名也变了

class Student:
def __init__(self, name, score):
self.name = name
self.__score = score
@property
def score(self):
return self.__score
@score.setter
def scores(self, score):
try:
if 0 < score <100:
self.__score = score
else:
print("Out of range")
except TypeError:
print("Only int value")
s = Student("bob", 99)
print(s.score)
s.scores = 89
print(s.score)

上面的对于私有属性保护很有用,对于公开的没啥用,公开属性你可以随便就赋值定义了,还保护个屁啊

下面拓展一些东西

先看代码

class Student:
def __init__(self, name, score):
self.__name = name
self.__score = score
def get_value(self):
return self.__name, self.__score
s = Student("jacks", 99)
print(s.get_value())
#看下结果
('jacks', 99)

然后我们给实例增加一个属性并赋值

s.__name = "TOM"
#你觉得这个__name和实例里的__name相同吗?

我们来打印下

print(s.__name)
#看结果
TOM
#居然可以直接调用并打印,看来这个并不是私有属性啊,为什么会这样呢?不应该和上面是一样的吗?
如果你理解为一样的话,那就错了,如果你理解不一样那就对了
#我们来看下实例所有属性
print(s.__dict__)
#看结果
{'_Student__name': 'jacks', '_Student__score': 99, '__name': 'TOM'}

实例的私有属性name是   '_Student__name'

而新增的则是 '__name' 两个截然不同的属性

所以大家不要被误解了。

python 学习笔记之@property的更多相关文章

  1. 【python学习笔记】9.魔法方法、属性和迭代器

    [python学习笔记]9.魔法方法.属性和迭代器 魔法方法:xx, 收尾各有两个下划线的方法 __init__(self): 构造方法,创建对象时候自动执行,可以为其增加参数, 父类构造方法不会被自 ...

  2. Python学习笔记之类与对象

    这篇文章介绍有关 Python 类中一些常被大家忽略的知识点,帮助大家更全面的掌握 Python 中类的使用技巧 1.与类和对象相关的内置方法 issubclass(class, classinfo) ...

  3. Python 学习笔记(下)

    Python 学习笔记(下) 这份笔记是我在系统地学习python时记录的,它不能算是一份完整的参考,但里面大都是我觉得比较重要的地方. 目录 Python 学习笔记(下) 函数设计与使用 形参与实参 ...

  4. python学习笔记整理——字典

    python学习笔记整理 数据结构--字典 无序的 {键:值} 对集合 用于查询的方法 len(d) Return the number of items in the dictionary d. 返 ...

  5. VS2013中Python学习笔记[Django Web的第一个网页]

    前言 前面我简单介绍了Python的Hello World.看到有人问我搞搞Python的Web,一时兴起,就来试试看. 第一篇 VS2013中Python学习笔记[环境搭建] 简单介绍Python环 ...

  6. python学习笔记之module && package

    个人总结: import module,module就是文件名,导入那个python文件 import package,package就是一个文件夹,导入的文件夹下有一个__init__.py的文件, ...

  7. python学习笔记(六)文件夹遍历,异常处理

    python学习笔记(六) 文件夹遍历 1.递归遍历 import os allfile = [] def dirList(path): filelist = os.listdir(path) for ...

  8. python学习笔记--Django入门四 管理站点--二

    接上一节  python学习笔记--Django入门四 管理站点 设置字段可选 编辑Book模块在email字段上加上blank=True,指定email字段为可选,代码如下: class Autho ...

  9. python学习笔记--Django入门0 安装dangjo

    经过这几天的折腾,经历了Django的各种报错,翻译的内容虽然不错,但是与实际的版本有差别,会出现各种奇葩的错误.现在终于找到了解决方法:查看英文原版内容:http://djangobook.com/ ...

随机推荐

  1. [UE4]蓝图使用GameMode重构

    GameMode的生命周期贯穿整个游戏,当然也包括各个关卡.因此可以把各个关卡都需要的功能放置在GameMode,以达到功能共享.重复利用的目的!

  2. vi/vim 光标移动命令(转载)

    转载至:https://www.cnblogs.com/Jacklovely/p/6015037.html vi/vim 光标移动命令 移动光标上:k nk:向上移动n行 9999k或gg可以移到第一 ...

  3. 不曾忘记的Vue.js

    马上2017年就结束了,虽然我因为目前的项目用不上你vue,但是我不曾忘记你,在时间缝隙的某一刹那,我再次将你拾起. vue.js全家桶:vue+ vuex+axios+vue-router+webp ...

  4. Linux RPS/RFS 实现原理浅析

    本文快速解析一下RPS/RFS的基本原理. RPS-Receive Packet Steering 下面这个就是RPS的原理:  其实就是一个软件对CPU负载重分发的机制.其使能的作用点在CPU开始处 ...

  5. C# 如何提取字符串中的数字(小技巧)

    下面讲解如何在字符串当中抓取到数字 方法一.使用正则表达式 1.纯数字提取 1 string str = "提取123abc提取"; //我们抓取当前字符当中的123 2 stri ...

  6. 「2017 山东一轮集训 Day6」子序列(矩阵快速幂)

    /* 找出了一个dp式子 是否能够倍增优化 我推的矩阵不太一样 是 1 0 0 0 0 0 0 0 0 -1 0 0 1 0 0 0 0 0 1 0 0 1 0 0 2 求得逆矩阵大概就是 1 0 0 ...

  7. 由echarts想到的js中的时间类型

    在工作中使用echarts时,偶然发现折线图中对时间类型变量的用法: now前面的+号何解? now = new Date(+now + oneDay); 后来查阅资料,看到一篇博客,解释如下:这是对 ...

  8. 【Selenium-WebDriver问题篇】Selenium实现元素的拖拽(java版)(转)

    https://blog.csdn.net/u010503127/article/details/51381284 Selenium实现元素的拖拽(java版) [前言] 自从淘宝网登陆页出现滑块验证 ...

  9. 【Jmeter自学】Jmeter脚本录制(二)

    ==================================================================================================== ...

  10. android 开发 实现一个ListView套嵌GirdView的滚动布局

    效果图 实现思维: 首先要处理管理好需要导入的数据,我们这里创建class来处理这些数据并且便于管理它们. 创建一个主activity的布局,里面需要一个ListView控件. 创建一个class继承 ...