@property装饰器的用法
在绑定属性时,如果我们直接把属性暴露出去,虽然写起来很简单,但是,没办法检查参数,导致可以把成绩随便改:
1
2
|
s
=
Student()
s.score
=
9999
|
这显然不合逻辑。为了限制score的范围,可以通过一个set_score()方法来设置成绩,再通过一个get_score()来获取成绩,这样,在set_score()方法里,就可以检查参数:
1
2
3
4
5
6
7
8
9
10
11
|
class
Student(
object
):
def
get_score(
self
):
return
self
._score
def
set_score(
self
, value):
if
not
isinstance
(value,
int
):
raise
ValueError(
'score must be an integer!'
)
if
value <
0
or
value >
100
:
raise
ValueError(
'score must between 0 ~ 100!'
)
self
._score
=
value
|
现在,对任意的Student实例进行操作,就不能随心所欲地设置score了:
1
2
3
4
5
6
7
8
|
>>> s
=
Student()
>>> s.set_score(
60
)
# ok!
>>> s.get_score()
60
>>> s.set_score(
9999
)
Traceback (most recent call last):
...
ValueError: score must between
0
~
100
!
|
但是,上面的调用方法又略显复杂,没有直接用属性这么直接简单。
有没有既能检查参数,又可以用类似属性这样简单的方式来访问类的变量呢?对于追求完美的Python程序员来说,这是必须要做到的!
还记得装饰器(decorator)可以给函数动态加上功能吗?对于类的方法,装饰器一样起作用。Python内置的@property装饰器就是负责把一个方法变成属性调用的:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
class
Student(
object
):
@property
def
score(
self
):
return
self
._score
@score
.setter
def
score(
self
, value):
if
not
isinstance
(value,
int
):
raise
ValueError(
'score must be an integer!'
)
if
value <
0
or
value >
100
:
raise
ValueError(
'score must between 0 ~ 100!'
)
self
._score
=
value
|
@property的实现比较复杂,我们先考察如何使用。把一个getter方法变成属性,只需要加上@property就可以了,此时,@property本身又创建了另一个装饰器@score.setter,负责把一个setter方法变成属性赋值,于是,我们就拥有一个可控的属性操作:
1
2
3
4
5
6
7
8
|
>>> s
=
Student()
>>> s.score
=
60
# OK,实际转化为s.set_score(60)
>>> s.score
# OK,实际转化为s.get_score()
60
>>> s.score
=
9999
Traceback (most recent call last):
...
ValueError: score must between
0
~
100
!
|
注意到这个神奇的@property,我们在对实例属性操作的时候,就知道该属性很可能不是直接暴露的,而是通过getter和setter方法来实现的。
还可以定义只读属性,只定义getter方法,不定义setter方法就是一个只读属性:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
class
Student(
object
):
@property
def
birth(
self
):
return
self
._birth
@birth
.setter
def
birth(
self
, value):
self
._birth
=
value
@property
def
age(
self
):
return
2014
-
self
._birth
|
上面的birth是可读写属性,而age就是一个只读属性,因为age可以根据birth和当前时间计算出来。
小结
@property广泛应用在类的定义中,可以让调用者写出简短的代码,同时保证对参数进行必要的检查,这样,程序运行时就减少了出错的可能性。
join()函数的用法
函数:string.join()
Python中有join()和os.path.join()两个函数,具体作用如下:
join(): 连接字符串数组。将字符串、元组、列表中的元素以指定的字符(分隔符)连接生成一个新的字符串
os.path.join(): 将多个路径组合后返回
一、函数说明
1、join()函数
语法: 'sep'.join(seq)
参数说明
sep:分隔符。可以为空
seq:要连接的元素序列、字符串、元组、字典
上面的语法即:以sep作为分隔符,将seq所有的元素合并成一个新的字符串
返回值:返回一个以分隔符sep连接各个元素后生成的字符串
2、os.path.join()函数
语法: os.path.join(path1[,path2[,......]])
返回值:将多个路径组合后返回
注:第一个绝对路径之前的参数将被忽略
二、实例
#对序列进行操作(分别使用' '与':'作为分隔符) >>> seq1 = ['hello','good','boy','doiido'] >>> print ' '.join(seq1) hello good boy doiido >>> print ':'.join(seq1) hello:good:boy:doiido #对字符串进行操作 >>> seq2 = "hello good boy doiido" >>> print ':'.join(seq2) h:e:l:l:o: :g:o:o:d: :b:o:y: :d:o:i:i:d:o #对元组进行操作 >>> seq3 = ('hello','good','boy','doiido') >>> print ':'.join(seq3) hello:good:boy:doiido #对字典进行操作 >>> seq4 = {'hello':1,'good':2,'boy':3,'doiido':4} >>> print ':'.join(seq4) boy:good:doiido:hello #合并目录 >>> import os >>> os.path.join('/hello/','good/boy/','doiido') '/hello/good/boy/doiido'
字符串u和r的用法
1.u不是针对中文, 可以针对任何的字符串
它代表是对字符串进行unicode编码.
一般英文字符在使用各种编码下, 基本都可以正常解析, 所以一般也就不带u了
但是中文, 必须表明所需编码, 否则一旦编码转换就会出现乱码.建议所有编码方式采用utf8(即若是开头有
# -*- coding: utf-8 -*
的话就不需要加u了)
注:以上是在Python2.7.10中,如果是在Python3中,是有区别的。这是因为,Python 2里的Unicode字符串在Python 3里就是普通字符串而已,因为在Python 3里字符串总是Unicode形式的。
2.字符串前面加r,表示的意思是禁止字符串转义