今天学习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. 基于JMX动态配置Log4J日志级别

    先来看比较low的修改日志级别的方式,在写程序里面. http://blog.gssxgss.me/java%E8%BF%90%E8%A1%8C%E6%97%B6%E5%8A%A8%E6%80%81% ...

  2. React 懒加载组件

    //组件第一次初始化的时候加载. import React, {PropTypes} from 'react'; //import AppComposer from './views/App/AppC ...

  3. CRM 更新解决方案之注意事项

    一般需要开发新功能时,企业或者软件公司往往会先从生产环境克隆出一台测试用系统. 开发人员会在测试系统中对功能进行开发或者测试. 这时当新功能开发和测试完成之后,需要将新的解决方案导入生产环境. 导入时 ...

  4. virtual box + win7 + usb + share folder

    1.enable virtaulization on BIOS 2.new machine setup, memory, harddisk size 3. 4.install extension pa ...

  5. CS229 1 .线性回归与特征归一化(feature scaling)

    线性回归是一种回归分析技术,回归分析本质上就是一个函数估计的问题(函数估计包括参数估计和非参数估计),就是找出因变量和自变量之间的因果关系.回归分析的因变量是应该是连续变量,若因变量为离散变量,则问题 ...

  6. 使用vim时生成的.swp文件

    1. 在使用vim时,退出编辑后,发现生成了swp文件,如下: 发现用vim打开一个文件时,都会产生一个.swp的隐藏文件(即文件名.开头的),这个文件是一个临时交换文件,用来备份缓冲区中的内容,用于 ...

  7. day9笔记整理,记忆

    函数的使用:一 定义函数的三种形式 1.1 无参函数 1.2 有参函数 1.3 空函数二 调用函数的三种形式 2.1 语句形式    def foo():   print('from foo')    ...

  8. 微信小程序连接本地接口(转)

    原文地址 最近的一个项目就是微信小程序 第一次接触微信开发者工具,并进行小程序的后端开发, 于是想看一下小程序如何请求本地的后台服务接口 wx.request({ url: 'http://local ...

  9. mysql 替代Oracle instr

    在迁移项目时遇到的,原项目的数据库使用的Oracle,现在要迁移到MySQL中,而项目中用到了Oracle的instr函数,而MySQL只能查找子串是否在父串中,没法按照出现的次数进行查找. 先来介绍 ...

  10. Weblogic环境(JSP)文件下载问题(下载的文件与原文件大小不一致问题)

    最近发现一个问题有个download.jsp文件下载jsp在Tomcat下正常,在Weblogic下不太正常! Weblogic下载的文件比原文件大两个字节,查看文件像是文件内容最后多了空行 检查do ...