python 学习笔记之@property
今天学习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的更多相关文章
- 【python学习笔记】9.魔法方法、属性和迭代器
[python学习笔记]9.魔法方法.属性和迭代器 魔法方法:xx, 收尾各有两个下划线的方法 __init__(self): 构造方法,创建对象时候自动执行,可以为其增加参数, 父类构造方法不会被自 ...
- Python学习笔记之类与对象
这篇文章介绍有关 Python 类中一些常被大家忽略的知识点,帮助大家更全面的掌握 Python 中类的使用技巧 1.与类和对象相关的内置方法 issubclass(class, classinfo) ...
- Python 学习笔记(下)
Python 学习笔记(下) 这份笔记是我在系统地学习python时记录的,它不能算是一份完整的参考,但里面大都是我觉得比较重要的地方. 目录 Python 学习笔记(下) 函数设计与使用 形参与实参 ...
- python学习笔记整理——字典
python学习笔记整理 数据结构--字典 无序的 {键:值} 对集合 用于查询的方法 len(d) Return the number of items in the dictionary d. 返 ...
- VS2013中Python学习笔记[Django Web的第一个网页]
前言 前面我简单介绍了Python的Hello World.看到有人问我搞搞Python的Web,一时兴起,就来试试看. 第一篇 VS2013中Python学习笔记[环境搭建] 简单介绍Python环 ...
- python学习笔记之module && package
个人总结: import module,module就是文件名,导入那个python文件 import package,package就是一个文件夹,导入的文件夹下有一个__init__.py的文件, ...
- python学习笔记(六)文件夹遍历,异常处理
python学习笔记(六) 文件夹遍历 1.递归遍历 import os allfile = [] def dirList(path): filelist = os.listdir(path) for ...
- python学习笔记--Django入门四 管理站点--二
接上一节 python学习笔记--Django入门四 管理站点 设置字段可选 编辑Book模块在email字段上加上blank=True,指定email字段为可选,代码如下: class Autho ...
- python学习笔记--Django入门0 安装dangjo
经过这几天的折腾,经历了Django的各种报错,翻译的内容虽然不错,但是与实际的版本有差别,会出现各种奇葩的错误.现在终于找到了解决方法:查看英文原版内容:http://djangobook.com/ ...
随机推荐
- [UE4]子控件Child Widget顶层容器选择
如果父级容器是Canvas,则可以直接设置尺寸.放到其他widget的时候也会保持设定好的尺寸(而不管父容器是什么类型).
- echarts饼图配置
js引用和配置div <div id="container" style="height: 100%"></div> <scrip ...
- Linux CentOS7.5上二进制安装MySQL5.7.23
1.下载二进制文件 cd /usr/local/src/ wget https://cdn.mysql.com//Downloads/MySQL-5.7/mysql-5.7.23-linux-glib ...
- Redis进阶实践之十三 Redis的Redis-trib.rb脚本文件使用详解
转载来源:http://www.cnblogs.com/PatrickLiu/p/8484784.html 一.简介 事先说明一下,本篇文章不涉及对redis-trib.rb源代码的分析,只是从使用的 ...
- 将.ipynb文件导入到另外的文件中
在定义函数或者类的.ipyter文件的末尾加上 try: !jupyter nbconvert --to python ppp.ipynb #ppp是文件的名称 except: pass 在需要导入到 ...
- C#语言正则用法
string phone =""; string pattern @"|\d{10}"; bool rusurt = false; Console.WriteL ...
- linux chown命令解除文件夹的root权限限制
sudo chown -R demouser file 这个命令可以解除linux文件的超级权限限制 摘录: chown将指定文件的拥有者改为指定的用户或组,用户可以是用户名或者用户ID:组可以是组名 ...
- redis参数改进建议
1.修改stop-writes-on-bgsave-error为no当前配置为yes,分别修改redis.conf和当前实例#redis.confstop-writes-on-bgsave-error ...
- Django实现瀑布流,组合搜索
Django中组合搜索功能 需求分析 很多电商网站中有组合搜索的功能,所谓组合搜索就是网页中组合多个条件,对数据库中进行查询,并且将结果显示在页面中,看个例子吧: 注意红框中的标识,我们可以根据URL ...
- 性能测试day01_性能基本概念
其实第一次接触性能是15年的时候,懵懵懂懂的被领导拉去做第一次做性能压测,如今有机会重新听一下云层大大讲解性能,于是打算以此博客记录下整个学习的过程,如若有不同意见者可以在下面留言指出,也欢迎大家一起 ...