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详解的更多相关文章

  1. django中模型详解-字段类型与约束条件

    这片博文来详细说明django模型的使用,涉及到django模型的创建,字段介绍,以及django模型的crud操作,以及一对一等操作. 在使用模型之前,我们首先设置数据库选项,django的默认数据 ...

  2. Django中ModelForm详解

    1.ModelForm组件介绍:这个组件的功能就是把model和form组合起来 2.ModelForm的使用 1.首先需要导入ModelForm from django.forms import M ...

  3. (转)python中@property详解

    转:https://www.cnblogs.com/zhangfengxian/p/10199935.html

  4. Objective-C中的@Property详解

    Objective-C中的@Property详解 @Property (属性) class vairs 这个属性有nonatomic, strong, weak, retain, copy等等 我把它 ...

  5. iOS中-Qutarz2D详解及使用

    在iOS中Qutarz2D 详解及使用 (一)初识 介绍 Quartz 2D是二维绘图引擎. 能完成的工作有: 绘制图形 : 线条\三角形\矩形\圆\弧等 绘制文字 绘制\生成图片(图像) 读取\生成 ...

  6. Python中dict详解

    from:http://www.cnblogs.com/yangyongzhi/archive/2012/09/17/2688326.html Python中dict详解 python3.0以上,pr ...

  7. Django入门基础详解

    本次使用django版本2.1.2 安装django 安装最新版本 pip install django 安装指定版本 pip install django==1.10.1 查看本机django版本 ...

  8. 【转】angular中$parse详解教程

    原文: https://yq.aliyun.com/ziliao/40516 ------------------------------------------------------------- ...

  9. 第五篇Django URL name 详解

    Django URL name 详解 利用Django开发网站,可以设计出非常优美的url规则,如果url的匹配规则(包含正则表达式)组织得比较好,view的结构就会比较清晰,比较容易维护. Djan ...

随机推荐

  1. git 使用流程 命令

    克隆远程分支到本地 git clone <https://github.com/cqzyl/methods.js.git> 进入master分支 git checkout master 以 ...

  2. VC使用编译时间作为版本号

    常用方法分两步:1. 得到编译时间:2. 设置基准时间,以编译时间距基准时间的总天数的2倍作为版本号,适当情况还可加上初值: 其中第一步实现有两种方法: 1. 直接使用系统宏:CString OcxT ...

  3. TAS5508 output changing

    1.如果信号从3th通道输入,正常就是从PWM5,6输出,现在要想从PWM7,8输出,就按照以下红线部分选择DAP CH5和DAP CH6,然后写入相应寄存器产生的12 bytes的数组数据即可.

  4. warning: remote HEAD refers to nonexistent ref, unable to checkout.解决

    git branch -r origin/branch origin/hexo git checkout -b hexo origin/hexo

  5. 【转】ios输入框被键盘挡住的解决办法

    做IOS开发时,难免会遇到输入框被键盘遮掩的问题.上网上搜索了很多相关的解决方案,看了很多,但是由衷的觉得太麻烦了. 有的解决方案是将视图上的所有的东西都添加到一个滚动视图对象( UIScrollVi ...

  6. 3218: 字符串字符统计—C语言

    3218: 字符串字符统计—C语言 时间限制: 1 Sec  内存限制: 128 MB提交: 270  解决: 129[提交][状态][讨论版][命题人:smallgyy] 题目描述 编写一函数,由实 ...

  7. 2018.6.1 oracle数据库乱码问题

    执行select * from v$controlfile;为什么结果是未选定行? 显示连接了但是select * from dba_data_files; 显示中文乱码: shutdown star ...

  8. 2.安装VS Code

    1 打开网站 https://www.visualstudio.com/zh-hans/ 2. 安装 3.可以在程序目录命令行下 code .    用vscode 打开程序 4.下载插件 复制 ex ...

  9. 题解 CF20A 【BerOS file system】

    对于此题,我的心近乎崩溃 这道题,注意点没有什么,相信大佬们是可以自己写出来的 我是蒟蒻,那我是怎么写出来的啊 好了,废话少说,开始进入正题 这道题,首先我想到的是字符串的 erase 函数,一边运行 ...

  10. 完结篇OO总结

    目录 前言 一.第四单元两次架构设计 二.架构设计及OO方法理解的演进 三.测试理解与实践的演进 四.课程收获 五.改进建议 前言 持续了17周的OO终于走向了尾声,想想寒假的时候连类都不知道是什么, ...