今天学习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. Android 获取手机内部信息,内核版本、基带版本、内部版本等

    TextView text = (TextView) findViewById(R.id.textView1); String phoneInfo = "Product: " + ...

  2. sas share 备忘录

    options comamid=tcp;libname payable 'E:\shouen';proc server authenticate=optional id=share1 msgnumbe ...

  3. CSS实现鼠标悬浮无限向下级展示的简单代码

    *{ margin:; padding:; } ul,li{ list-style: none; } .ui-slide-box{ width: 300px; } .ui-slide-item{ wi ...

  4. Android收发短信

    效果:点击发送短信开始发送短信 收到短信时将短信的内容显示出来 代码如下: 一.权限声明 <uses-permission android:name="android.permissi ...

  5. 11 vim文本编辑器

    和sed相比,sed为字处理器(行编辑器),将文本逐行放入到模式空间(也就是内存)中进行处理,并显示在屏幕上.而vim.vi以及nano都是全屏文本编辑器,而vim则是vi的加强版本,相对于vi,vi ...

  6. centos7 真实机安装后没有网卡解决办法

    我们在真实机安装完centos7版本后,会发现没有网卡,只有lo口 因为真实机不同你在虚拟机里面,这个时候我们不能连网,更加不要说配置什么静态ip了 是什么原因呢,是因为有些真实机安装了centos系 ...

  7. 在javascript中toString 和valueOf的区别

    1.toString()方法:主要用于Array.Boolean.Date.Error.Function.Number等对象转化为字符串形式.日期类的toString()方法返回一个可读的日期和字符串 ...

  8. DNS(bind)服务器安装和配置

    一.前言 DNS 域名系统(英文:Domain Name System,缩写:DNS)是因特网的一项服务.它作为将域名和IP地址相互映射的一个分布式数据库,能够使人更方便地访问互联网.DNS使用TCP ...

  9. 发送短信验证码倒计时,CountDownTimer;

    1.声明CountDownTimer的成员变量: private CountDownTimer countDownTimer; 2.设置倒计时总时间和间隔时间: countDownTimer = ne ...

  10. Html标签及各种属性(持续更新)

    <!--Html标签属性之:required (必须的)--> <input type="file" id="Images" required ...