今天学习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]Switch on String,根据字符串决定条件分支,类似于高级语言中的switch语句

  2. Html5弹幕视频播放器插件

    Danmmu Player是一个具备弹幕功能的Html5视频播放器.我们在观看视频的时候,可以对视频发表自己的观点,当点击发送按钮后,发表的内容会在视频屏幕上以彩弹的形式发出,并做滚动展示动画效果,即 ...

  3. 浏览器兼容java小程序配置说明

    最近在使用的一个web应用系统是内嵌了java小程序,遇到了各种浏览器兼容性问题,现梳理如下: 1.通过以下链接检测当前电脑是否已经安装有java https://java.com/zh_CN/dow ...

  4. CentOS之正则表达式

    支持linux正则表达式的工具有:grep:实现查找,sed,awk:都是流式编辑器,可以实现查找和替换,并且把替换的文本输出到屏幕上. grep工具 grep [-cinvABC] 'word' - ...

  5. python 实现排序算法(二)-合并排序(递归法)

    #!/usr/bin/env python2 # -*- coding: utf-8 -*- """ Created on Tue Nov 21 22:28:09 201 ...

  6. hive计算周一的日期

    ) FreeMarker --',-7)?date('yyyy-MM-dd'),'week')?string('yyyy-MM-dd')}'

  7. parameterized之unittest参数化

    unittest没有想testNG那么方便,可以进行参数化,但是有一个第三方库可是实现参数化 安装 pip install parameterized 该库可以在python的所有单元测试框架中使用 ...

  8. thinkphp 5 wherein

    $details = Db::name('food') -> alias('a') -> field('a.food_code,a.food_name,a.food_u1,a.food_p ...

  9. System.Data.DbType映射关系

    有如下类型的映射对照: System.Data.SqlClient.SqlDbType  System.Data.OleDb.OleDbType System.Data.Odbc.OdbcType S ...

  10. C#取整函数Math.Round、Math.Ceiling和Math.Floor

    1.Math.Round:四舍六入五取偶 引用内容 Math.Round(0.0) //0Math.Round(0.1) //0Math.Round(0.2) //0Math.Round(0.3) / ...