python3与django中@property详解
django提供了内置装饰器
@staticmethod\@classmethod\property
在OSQA中,@property的使用频率是非常高的。下面就是它的使用方法:
@property 可以将python定义的函数“当做”属性访问,从而提供更加友好访问方式,和java中的setter和getter类似。
models.py中如下:
from django.db import models class Person(models.Model):
G=(('chen','jian'),('hong','yi'),('rt','ju'))
gender=models.CharField(max_length=20,choices=G) @property
def Gender(self):
return self.gender @Gender.setter
def Gender(self,new_value):
self.gender=new_value
在views.py中使用:
from django.http import HttpResponse
from mytest.models import *
def index(request):
print Person.objects.all()[0].Gender
b=Person.objects.all()[0]
b.Gender='adfasfasd'
print b.Gender
b.save()
return HttpResponse(Person.objects.all()[0].Gender)
@property提供的是一个只读的属性,如果需要对属性进行修改,那么就需要定义它的setter。
#########python3中
@staticmethod:静态方法,静态方法是不可以访问实例变量或类变量的,这个类方法实际上跟类没有什么关系,它只是类下面的一个函数,跟类本身没关系,只是名义上归类管。
它与类唯一的关联就是需要通过类名来调用这个方法
如果非要传参数,只有传自己
@classmethod:类方法只能访问类变量,不能访问实例变量
@property :属性方法,属性方法的作用就是通过@property把一个方法变成一个静态属性
例如:

1 class Dog(object):
2 def __init__(self,name):
3 self.name=name
4 @property #把一个方法变成一个静态属性
5 def eat(self):
6 print('%s is eating %s' %(self.name,'包子'))
7 d1=Dog('Jack')
8 d1.eat #不加(),输出:Jack is eating 包子

1 #如果要传参数
2 class Dog(object):
3 def __init__(self,name):
4 self.name=name
5 self.__food=None
6 @property
7 def eat(self):
8 print('%s is eating %s' %(self.name,self.__food))
9
10 @eat.setter
11 def eat(self,food):
12 print('要传的参数:',food)
13 self.__food=food
14 d1=Dog('Jack')
15 d1.eat
16 d1.eat='包子'
17 d1.eat #self.__food=food把参数传值了再执行属性方法
摘自其他人笔记
定义类Student,拥有变量名name和score
1 class Student(object):
2 def __init__(self,name,score):
3 self.name = name
4 self.score = score
但是,上述这样定义score是不会进行参数检查的,也就意味着我们不能执行必要的参数以及错误处理。
我们可以定义相应的set和get成员函数来访问成员变量score,并且进行参数检查。如下所示:

1 class Student(object):
2 def __init__(self,name,score):
3 self.name = name
4 self.score = score
5 def get_score(self):
6 return self.score
7 def set_score(self,score):
8 if not isinstance(score, int):
9 raise ValueError(”invalid score!!!”)
10 if score < 0 or score > 100:
11 raise ValueError(”score must be between [0,100]!!!”)
12 self._score = score
上述代码定义了score成员的set和get函数。(可能实际应用时,修改分数比较常见)
现在,我们改变参数的代码是这样的:
1 s1 = Student()
2 s1.set_score(9999) #这里会抛出异常
上述的第二种方式实现了set函数的参数检查,但是修改score的代码从简单的 s1.score = 90 变成了 s1.set_score(90) .我们怎么样才能做到既检验输入的参数又使得修改score的代码不变呢?
@Property便是这个作用。
下面,我们讨论Python的高级特性 @Property。简单的说@Properyty就是将成员函数的调用变成属性赋值。
于是有了下面的代码:
1 class Student(object):
2 def __init__(self,name,score):
3 self._name = name
4 self._score = score
5 @property
6 def score(self):
7 return self._score
8 @score.setter
9 def score(self,score):
10 if not isinstance(score,int):
11 raise ValueError(”invalid score!!!”)
12 if score < 0 or score > 100:
13 raise ValueError(”score must be between [0,100]!!!”)
14 self._score = score
15 @property
16 def name(self):
17 return self._name
18
19 s1 = Student(”Lily”, 90)
20 s1.name = ”Luly”
21 s1.score = 100
关于上述代码的说明:
- 可能你已经发现了,我的成员变量改成了_name 与 _score,这里首先是为了增加可读性,这两个变量是私有的。其次的原因见下面的误区分析。
- 上述代码中的 s1.name = “Luly” 行会出现编译错误 AttributeError: can’t set attribute ,也就是说这里不能直接这样改变,这是为什么呢?可以看到,在代码中,我并没有提供名称为name的set函数, 这里值得注意的是,s1._name = “Lucy” 是可以运行通过的。但是我们之前说过了,假设用户足够自觉,不会去操作 _xxx 或者 __xxx这样的变量名。
- 按照上述代码的初衷,也就是说name是类的只读的属性。score是可修改的。
- 关于@property 修饰的函数 score 就是个简单的get函数,该函数不需要任何参数(self不需要传入值),因此我们可以这样来调用这个函数 ,即 s1.score 即可。(这就是Property的用处,将函数调用转化为属性访问),相当于给score加了一层包裹。
- 关于@score.setter 便是针对与 score函数包裹的成员变量的的set函数。当我们需要修改_score的值时,使用score函数,但是就像score是类的成员属性一样使用,例如上面的: s1.score = 100,实际上等价于 s1.score(100).
注意,这里的函数名不一定要是score,可以是任何的字符串,这里只是为了方面说score函数是_score的包裹,例如下面的代码:我们将score改成了AA,但是这样在:
1 class Student(object):
2
3 def __init__(self,name,score):
4 self._name = name
5 self._score = score
6
7 @property
8 def AA(self):
9 return self._score
10 @AA.setter
11 def AA(self,score):
12 if not isinstance(score,int):
13 raise ValueError(“invalid score!!!”)
14 if score < 0 or score > 100:
15 raise ValueError(“score must be between [0,100]!!!”)
16 self._score = score
17 @property
18 def name(self):
19 return self._name
20
21 s1 = Student(”Lily”, 90)
22 s1.name = ”Luly”
23 s1.AA = 100 # 这里相当于是 s1.AA(100)好了,关于@Property的概念与用法就讲完了。本质上是定义了新的函数,该函数们执行set与get的功能,并且有@Property的包裹。并且将这些定义的函数当作属性一样来赋值。
可能存在的陷阱:
下面的代码是个大的陷阱,因为现在的函数已经不再是单纯的函数,而是可以直接用 = 来调用,例如上面的 score函数 的调用竟然是 s1.score = 100 .这样就会出现下面的问题:
1 class Student(object):
2 def __init__(self,name,score):
3 self.name = name
4 self.score = score
5 @property
6 def score(self):
7 return self.score
8 @score.setter
9 def score(self,score):
10 if not isinstance(score,int):
11 raise ValueError(”invalid score!!!”)
12 if score < 0 or score > 100:
13 raise ValueError(”score must be between [0,100]!!!”)
14 self.score = score
15 @property
16 def name(self):
17 return self.name
18 def func(self):
19 self.score = score
20
21 s1 = Student(”Lily”, 90)
22 s1.func()上面的代码有两个很大的错误,
- 你会发现,你无法定义Student的任何实例,为什么呢? 首先@property把score和name两个成员函数可以当作成员变量来访问,那么在定义实例时,调用init函数的时候,self.name = name,这一句,Python会将左端的self.name当作函数调用,然而我们并未给name变量 定义set函数,于是错误信息为:AttributeError: can’t set attribute.
- 好的,我们接下来注释掉
1 @property
2 def name(self):
3 return self.name这两行,那么接下来的运行还是错误的,为什么呢?是因为init函数代码的第二行 self.score = score, 很庆幸我们定义了score的set函数, 那么self.score调用score函数,当执行到score函数的最后一句self.score = score时, 我们回发现,式子的左端还是score函数调用, 如此往复,最终以函数递归深度达到上限退出程序。
这里其实是一个很好的代码习惯,那就是尽量不要让函数名与变量名同名,便可以避免这些错误。所以,比如说,这里的变量名self.score改为:self._score就可以避免递归错误。
python3与django中@property详解的更多相关文章
- django中模型详解-字段类型与约束条件
这片博文来详细说明django模型的使用,涉及到django模型的创建,字段介绍,以及django模型的crud操作,以及一对一等操作. 在使用模型之前,我们首先设置数据库选项,django的默认数据 ...
- Django中ModelForm详解
1.ModelForm组件介绍:这个组件的功能就是把model和form组合起来 2.ModelForm的使用 1.首先需要导入ModelForm from django.forms import M ...
- (转)python中@property详解
转:https://www.cnblogs.com/zhangfengxian/p/10199935.html
- Objective-C中的@Property详解
Objective-C中的@Property详解 @Property (属性) class vairs 这个属性有nonatomic, strong, weak, retain, copy等等 我把它 ...
- iOS中-Qutarz2D详解及使用
在iOS中Qutarz2D 详解及使用 (一)初识 介绍 Quartz 2D是二维绘图引擎. 能完成的工作有: 绘制图形 : 线条\三角形\矩形\圆\弧等 绘制文字 绘制\生成图片(图像) 读取\生成 ...
- Python中dict详解
from:http://www.cnblogs.com/yangyongzhi/archive/2012/09/17/2688326.html Python中dict详解 python3.0以上,pr ...
- Django入门基础详解
本次使用django版本2.1.2 安装django 安装最新版本 pip install django 安装指定版本 pip install django==1.10.1 查看本机django版本 ...
- 【转】angular中$parse详解教程
原文: https://yq.aliyun.com/ziliao/40516 ------------------------------------------------------------- ...
- 第五篇Django URL name 详解
Django URL name 详解 利用Django开发网站,可以设计出非常优美的url规则,如果url的匹配规则(包含正则表达式)组织得比较好,view的结构就会比较清晰,比较容易维护. Djan ...
随机推荐
- webapp一些样式记录
图片外面的div设置宽高自适应width: 100vw; max-width: 640px; display: block; height: 43.75vw; max-height: 280px; f ...
- 链接文字<a>保持原有的字体颜色
<style type="text/css"> #red {color: red;} #blue {color: blue;} #orange {color: oran ...
- .net密码找回
using System; using System.Collections.Generic; using System.Text; using System.Net.Mail; using Syst ...
- Google Authenticator加强ssh安全
一.安装依赖包 软件包可以在这个地址下载:https://pan.baidu.com/s/1r0CmwbtCfNiBqU9rh_TxtA yum -y install pam-devel tar jx ...
- NYOJ-22-素数求和问题
原题地址 素数求和问题 描述 现在给你N个数(0<N<1000),现在要求你写出一个程序,找出这N个数中的所有素数,并求和. 输入 第一行给出整数M(0<M<10)代表多少组测 ...
- 【BZOJ1029】[JSOI2007] 建筑抢修(堆优化贪心)
点此看题面 大致题意: 有N个受到严重损伤的建筑,对于每个建筑,修好它需要\(T1\)秒,且必须在\(T2\)秒之前修完(\(T1\)与\(T2\)不是固定值),问你最多能修好几个建筑. 题解 一看到 ...
- 【BZOJ1045】糖果传递(基于贪心的数学题)
点此看题面 大致题意: 有\(n\)个小朋友坐成一圈,每人有\(a[i]\)个糖果.每人只能给左右两人传递糖果,传递一个糖果代价为1,求使所有人获得均等糖果的最小代价. 数学转换 这题其实是一道带有浓 ...
- 2017.12.1 如何用java写出一个菱形图案
上机课自己写的代码 两个图形原理都是一样的 1.一共有仨个循环 注意搞清楚每一层循环需要做的事情 2.第一层循环:是用来控制行数 3.第二层循环控制打印空格数 4.第三层循环是用来循环输出星星 imp ...
- python_44_文件属性
#打印文件属性信息 import os#os.stat()返回的文件属性元组元素的含义 filestats=os.stat('yesterday')#获取文件/目录的状态 print(filestat ...
- DongDong坐飞机
题目连接:https://ac.nowcoder.com/acm/contest/904/D 第一次研究了一下这种题型,还是比较好理解的,因为有半价次数的限制,所以要把每一中情况都写出来,dp[现在的 ...