类的成员
类的成员可以分为三类:字段、方法、属性
一:字段:
普通字段和静态字段,他们在定义和使用中有所区别,而最本质的区别是内存中保存的位置不同
- 普通字段属于对象
- 静态字段属于类
字段的定义和使用
class Province: # 静态字段 country = '中国' def __init__(self,name): # 普通字段 self.name = name # 直接访问普通字段 obj = Province('北京') print obj.name # 直接访问静态字段 print Province.country
点睛:
1:谁来调用:
从上面可以看出普通字段需要通过对象来访问,静态字段通过类来调用。
2:存储的位置
- 静态字段只存在把内存中一份,存在类的内存中
- 普通字段在每个对象中都要创建一份。
通过类创建对象的时候,如果每个对象都具有相同的字段,那么就使用静态字段
二:方法
普通方法、静态方法、类方法。三种方法在内存中都属于类,区别在于调用方式不同
- 普通方法:由对象调用,至少一个self参数,执行普通方法时,自动将调用该方法的对象赋值给self
- 类方法:由类调用,至少一个cls参数,执行类方法时,自动将调用该方法的类赋值给cls
- 静态方法:由类调用,无默认参数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
class
Foo:
# 初始化类
def
__init__(
self
):
pass
# 定义普通方法,至少有一个self参数
def
p(
self
):
print
'普通方法'
# 定义类方法,至少有一个cls参数
@classmethod
def
q(
cls
):
print
'类方法'
# 定义静态方法
@staticmethod
def
w():
print
'静态方法'
# 调用普通方法
a
=
Foo()
ret
=
a.p()
# print ret
# 调用类方法
Foo.q()
# 调用静态方法
Foo.w()
|
点睛:
相同点:对于所有的方法而言,均属于类中,所以在内存中也之保存一份
不同点:方法调用者不同,调用方法时,自动传入的参数不同
三:属性
1:属性的基本使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
class
Foo:
def
func(
self
):
# print 'func'
return
'方法调用的返回值'
# 定义属性
@property
def
prop(
self
):
# print 'prop'
return
'属性调用的返回值'
# 调用方法
obj
=
Foo()
ret
=
obj.func()
print
ret
# 调用属性
ret1
=
obj.prop
print
ret1
|
点睛:
- 定义时,在普通方法的基础上在上面添加@property装饰器
- 属性仅有一个self参数
- 调用时,无需括号
方法:
obj = Foo()
ret = obj.func()
属性:
obj = Foo()
ret = obj.prop
属性存在的意义:访问属性时,可以制造出和访问字段完全相同的假象
实例:
对于主机列表页面,每次请求不可能把数据库中的所有内容都显示到页面上,而是通过分页的功能局部显示,所以在向数据库中请求数据时就要显示的指定获取从第M条到第N条的所有数据,这个分页功能包括:
- 根据用户请求的当前和总数据条数计算出m和n
- 根据m和n去数据库请求数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
class
Pager:
def
__init__(
self
,current_page):
# 用户当前请求的页面
self
.current_page
=
current_page
# 每页默认显示10条
self
.per_items
=
10
# 定义属性
@property
def
start(
self
):
val
=
(
self
.current_page
-
1
)
*
self
.per_items
return
val
@property
def
end(
self
):
val
=
self
.current_page
*
self
.per_items
return
val
# 调用属性
p
=
Pager(
2
)
print
p.start
print
p.end
# 结果:
# 10
# 20
|
2:属性的两种定义方式
装饰器、静态字段
装饰器:在方法上应用装饰器
静态字段:在类中定义值为property对象的静态字段
装饰器方式:
经典类,具有一种@property装饰器
# 定义类 class Foo: @property def fun(self): return 'caoxiaojian' # 调用属性 obj = Foo() ret = obj.fun print ret # 自动执行 @property修饰的fun方法,并获取方法的返回值
新式类,具有三种@property装饰器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
class
Goods(
object
):
@property
def
price(
self
):
print
'@property'
@price
.setter
def
price(
self
,value):
print
'@price.setter'
,value
@price
.deleter
def
price(
self
):
print
'@price.deleter'
# 调用
obj
=
Goods()
obj.price
# 自动执行@property修饰的price方法,并获取方法的返回值
obj.price
=
123
# 自动执行@price.setter修饰的price方法,并将123赋值给方法的参数
del
obj.price
# 自动执行@price.deleter修饰的price方法
执行结果:
@property
@price
.setter
123
@price
.deleter
|
注释:
经典类中的属性只用一种访问方式,其对应被@property修饰的方法
新式类中的属性有三种访问方式,并分别对应了三个被@property、@方法名.setter、@方法名.deleter修饰的方法
因为新式类有三种访问方式,我们可以根据他们几个属性的访问特点,分别将三个方法定义为同一个属性:获取、修改、删除
实例讲解:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
class
Goods(
object
):
def
__init__(
self
):
# 原价
self
.original_price
=
100
# 折扣
self
.discount
=
0.8
@property
def
price(
self
):
# 实际价格 = 原价 * 折扣
new_price
=
self
.original_price
*
self
.discount
return
new_price
@price
.setter
def
price(
self
,value):
# 设置原始价格
self
.original_price
=
value
@price
.deleter
def
price(
self
,value):
# 删除原始价格
del
self
.original_price
# 调用
obj
=
Goods()
# 获取商品价格
obj.price
# 设置原始价格
obj.price
=
3000
# 删除原始价格
del
obj.price
|
静态字段方式:
创建值为property对象的静态字段
当使用静态字段的方式创建属性时,经典类和新式类无区别
1
2
3
4
5
6
7
8
9
|
class
Foo:
def
get_bar(
self
):
return
'caoxiaojian'
BAR
=
property
(get_bar)
obj
=
Foo()
# 自动调用get_bar方法,并获取方法的返回值。
ret
=
obj.BAR
print
ret
|
property的构造方法中有个四个参数
- 第一个参数是方法名,调用对象.属性时自动触发执行方法
- 第二个参数是方法名,调用对象.属性 = xxx时自动触发执行方法
- 第三个参数是方法名,调用del 对象.属性时自动触发执行方法
- 第四个参数是字符串,调用对象.属性.__doc__此参数是该属性的描述信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
class
Foo:
def
get_bar(
self
):
return
'caoxiaojian'
# 必须有两个参数
def
set_bar(
self
):
return
'set value'
+
value
def
del_bar(
self
):
return
'caoxiaojian===2'
BAR
=
property
(get_bar, set_bar, del_bar,
'description......'
)
obj
=
Foo()
print
obj.BAR
# 自动调用第一个参数中定义的方法:get_bar
obj.BAR
=
"caogaotian"
# 自动调用第二个参数中定义的方法:set_bar方法,将"caogaotian" 当作参数传入
print
obj.BAR
del
obj.BAR
# 自动调用第三个参数中定义的方法:del_bar
print
obj.del_bar()
obj.BAR.__doc__
# 自动调用第三个参数中设置的值:'description......'
'''
结果输出:
caoxiaojian
caogaotian
caoxiaojian===2
'''
|
类成员的修饰符
两种形式:
- 私有成员:只有在类的内部才能访问的方法
- 公有成员:在任何地方都能访问
定义的不同:
私有成员命名时,前面两个字符是下划线。(特殊成员除外,例如:__init__等)
class C: def __init__(self): self.name = '公有字段' self.__name = '私有字段'
私有成员和公有成员的访问限制不同
静态字段
- 公有静态字段:类可以访问;类内部可以访问;派生类中可以访问
- 私有静态字段:仅类内部可以访问
公有静态字段
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
class
C:
name
=
'公有静态字段'
def
func(
self
):
print
C.name
class
D(C):
def
func_1(
self
):
print
C.name
# 直接使用类访问
C.name
# 类内部访问
obj
=
C()
obj.func()
# 派生类内部访问
obj_1
=
D()
obj_1.func_1()
'''
结果打印:
公有字段
公有字段
'''
|
私有静态字段
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
class
C:
__name
=
'公有静态字段'
def
func(
self
):
print
C.__name
class
D(C):
def
func_1(
self
):
print
C.__name
# 类中访问
# C.__name # 错误
# 类内部访问
obj
=
C()
obj.func()
# 派生类中访问
# obj_1 = D() # 错误
# obj_1.func_1()
|
普通字段
- 公有普通字段:对象、类、派生类都可以访问
- 私有普通字段:只能在类内部访问
公有普通字段
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
class
C:
def
__init__(
self
):
self
.foo
=
'公有字段'
def
func(
self
):
# 在类内部调用访问
print
self
.foo
class
D(C):
def
show(
self
):
# 在派生类中调用访问
print
self
.foo
obj
=
C()
# 通过对象访问
print
type
(obj.foo)
print
obj.foo
print
'==========='
# 类的内部访问
obj.func()
print
'==========='
obj_1
=
D()
# 在派生类中访问
obj_1.show()
'''
结果打印:
<type 'str'>
公有字段
===========
公有字段
===========
公有字段
'''
|
私有普通字段
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
class
C:
def
__init__(
self
):
self
.__foo
=
'私有普通字段'
def
func(
self
):
# 类的内部调用访问
print
self
.__foo
class
D(C):
def
show(
self
):
# 在派生类中调用访问
print
self
.__foo
obj
=
C()
# obj.__foo # 通过对象访问:报错
obj.func()
# 通过类内部访问
obj_1
=
D()
#obj_1.show() # 通过派生类调用访问: 报错
|
类的特殊成员
1:__doc__
表示类的描述信息
class C: """ 这是描述信息,你看什么看?? """ def func(self): pass print C.__doc__ # 输出:这是描述信息,你看什么看??
2:__module__和__class__
__module__:表示当前操作的对象在哪个模块
__class__: 表示当前操作的对象的类是哪一个
在tmp模块下面有test.py和test1.py
test.py
class C: def __init__(self): self.name = 'caoxiaojian'
test1.py
from test import C # 根据导入的C类创建对象 obj = C() # 获取对象中的模块名 print obj.__module__ # test # 获取对象中的类名 print obj.__class__ # test.C
3:__init__
构造方法,通过类创建对象时,自动触发执行
class C: def __init__(self,name): self.name = name self.age = 18 obj = C('caoxiaojian') # 自动执行类中的__init__方法 print obj.name
4:__call__
对象后面加括号,触发执行
点睛:
构造方法的执行是由创建对象触发的。即:对象名 = 类名()
__call__方法的执行由对象后面加括号触发的。即:对象()或者类名()()
class C: def __init__(self): pass def __call__(self, *args, **kwargs): print '__call__' obj = C() # 触发__init__ obj() # 触发__call__
5:__dict__
类或对象中的所有成员
点睛:
类的普通字段属于对象,类中的静态字段和方法等属于类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
class
Province:
country
=
'china'
def
__init__(
self
,name,count):
self
.name
=
name
self
.count
=
count
def
func(
self
,
*
args,
*
*
kwargs):
print
'func===func'
# 获取类中的成员:静态字段和方法
print
Province.__dict__
# {'country': 'china', '__module__': '__main__', 'func': <function func at 0x021DA7F0>, '__init__': <function __init__ at 0x021DA870>, '__doc__': None}
# 调用类创建obj对象
obj
=
Province(
'shandong'
,
100000
)
print
obj.__dict__
# {'count': 100000, 'name': 'shandong'}
# 调用类创建foo对象
foo
=
Province(
'beijing'
,
20000
)
print
foo.__dict__
# {'count': 20000, 'name': 'beijing'}
|
类的分类:
经典类和新式类
# 经典类 class func: def Foo(self): pass # 新式类 class func_new(object): def Foo_new(self): pass
点睛:
区别:就是在类的后面加个object
类的继承
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
# 新式类
class
D(
object
):
# 经典类
#class D:
def
bar(
self
):
print
'D.bar'
class
C(D):
def
bar(
self
):
print
'C.bar'
class
B(D):
pass
class
A(B,C):
pass
a
=
A()
a.bar()
'''
经典类:深度优先 D.bar
新式类:广度优先 C.bar
'''
|
点睛:
经典类:深度优化
新式类:广度优化