一、类与对象
1、什么是类?
类,顾名思义,就是具体相同属性的同一类事物的统称及抽象。
对象,指是就是具体的抽象类的实例
以上的说法是不是看起来有点云里来雾里去呢。没错,专业的解释总是让人难以理解,这就是专家。其实举个简单的例子大家就能理解了
如:牛马羊鸡鸭鹅,这些都是统称为 动物,没错吧。那动物就是上面所谓的类,而牛马羊鸡鸭鹅就是类中对应的实例,也就是对象。牛是对象,羊是对象,。。。现在明白了吧
python类是怎么定义和使用的,废话少说,上图,一目了然
2、类的成员:从上图可以看到,类包含了很多成员,那类中成员的分类是怎样的呢,看下图
3、类的三大特性:封装,继承,多态(python多态用得非常少)
何为封装:先来看个小问题,比如说要对数据库进行增删改查操作,那么我们可以定义4个函数用于实现这些功能。但每次调用这些函数时我们就必须给这些函数传参数,必须告诉这些函数要所边的数据库实例,用户名,密码,端口号等信息。这样一个,每一次的调用都是传这些相同的信息。1、是不是有更好的方法来使用这个重复的操作呢?2、另对于面向函数的调用,事实我们并不知道到底是谁用了函数。
对于面向对象来说,封装的概念实际上就是用于解决此类场景所产生的问题的。事实上我们可以这些公用的信息都放在构造函数中的参数中,即当实例化一个对象时就给这个对象赋予了这些信息,然后方法的调用就不用再重复在函数中传入这些参数了。调用方法时用指定的对象去调用这些方法,就知道是谁调用了,举个例子就清楚了
1 >>> #函数实现
2 ...
3 >>> def fetch(conn_info):
4 ... print "use %s conn to db for fetch" % conn_info
5 ...
6 >>> def modify(conn_info):
7 ... print "use %s conn to db for modify" % conn_info
8 ...
9 >>> #函数调用,每调用一次都需要传入参数
10 ... fetch('scott 123 127.0.0.1')
11 use scott 123 127.0.0.1 conn to db for fetch
12 >>> modify('scott 123 127.0.0.1')
13 use scott 123 127.0.0.1 conn to db for modify
14 >>>
15 >>> #类实现
16 ... class A:
17 ... def __init__(self,conn_info):
18 ... self.conn_info = conn_info
19 ... def fetch(self):
20 ... print "use %s conn to db for fetch" % self.conn_info
21 ... def modify(self):
22 ... print "use %s conn to db for modify" % self.conn_info
23 ...
24 >>> #类调用
25 ... #实例化一个对象,指明了谁(obj)调用,且公用参数只需要在实例化时传一次就行了
26 ... obj = A('scott 123 127.0.0.1')
27 >>> obj.fetch()
28 use scott 123 127.0.0.1 conn to db for fetch
29 >>> obj.modify()
30 use scott 123 127.0.0.1 conn to db for modify
31 >>>
4、类的继承
什么是继承?比如说两个人A和B,A可以行走吃喝,B也可以行走吃喝,且B还可以画画,而A却不会,那么我们就可以说B继承于A
#继承的定义
class A:
def func1(self):
print "func1"
class B(A):
def func2(self):
print "func2"
##实例化对象
obj2 = B()
##调用父类方法
obj2.func1()
以上代码就指明了B类继承于A类,是不是很简单,且继承了A类(父类后就可以通过对象调用你类的方法了)
5、多继承:那么一个类只能继承于另一个类吗,是否可以继承于多个类,答案是肯定了,这个是python特有,其它语言并没有这个特性。问题来了,如果一个类D继承于B,C两个类,B,C两个类均继承于A类,B类没有方法func,C类有方法func,A类也有方法func,那D类实例化后调用func方法到底是调用哪个类的方法呢?
举个例子就清楚了,在看例子之前,先说下python中类的分类(为什么?因为以上问题分两种情况,经典类与新式类是有所不同的),在python中类分为经典类和新式类,定义新式类只需要在定义指明该类继承于object类即可,如下
#经典类
class A:
pass
#新式类
class B(object):
pass
##经典类的多继承经典类与新式类方法调用顺序示例代码
class A:
def func(self):
print "funcA"
class B(A):
pass
class C(A):
def func(self):
print "funcC"
class D(B,C):
pass
#实例化对象
obj = D()
#函数调用,打印funcA
obj.func()
##新式类的多继承
class A(object):
def func(self):
print "funcA"
class B(A):
pass
class C(A):
def func(self):
print "funcC"
class D(B,C):
pass
#实例化对象
obj = D()
#新式类函数调用,打印funcC
obj.func()
执行结果:
1 >>> ##经典类的多继承
2 ... class A:
3 ... def func(self):
4 ... print "funcA"
5 ...
6 >>> class B(A):
7 ... pass
8 ...
9 >>> class C(A):
10 ... def func(self):
11 ... print "funcC"
12 ...
13 >>> class D(B,C):
14 ... pass
15 ...
16 >>> #实例化对象
17 ... obj = D()
18 >>> #函数调用,打印funcA
19 ... obj.func()
20 funcA
21 >>>
22 >>> ##新式类的多继承
23 ... class A(object):
24 ... def func(self):
25 ... print "funcA"
26 ...
27 >>> class B(A):
28 ... pass
29 ...
30 >>> class C(A):
31 ... def func(self):
32 ... print "funcC"
33 ...
34 >>> class D(B,C):
35 ... pass
36 ...
37 >>> #实例化对象
38 ... obj = D()
39 >>> #新式类函数调用,打印funcC
40 ... obj.func()
41 funcC
#从以上结果可以看出
经典类的查找是以深度优先为原则的,查询顺序:D->B->A,如果找不到,就报错,找到就调用
新式类的查询是以广度优先为原则的,查询顺序:D->B->C->A,如果找不到,就报错,找到就调用
6、类中常用的特殊成员
类名.__doc__ :打印类的注释信息(指用'''/"""引起来的注释信息)
类名/对象.__dict__: 返回类或对象包含的成员字典
__call__:在类中定义这个方法,事实上就是执行 对象() 调用的方法
__str__:如果一个类中定义了__str__方法,那么在打印 对象 时,默认输出该方法的返回值
7、其它相关
isinstance(obj, cls):检查是否obj是否是类 cls 的对象
issubclass(sub, super):检查sub类是否是 super 类的派生类
8、类的常用操作示例
class Person:类的常用操作示例代码
class_v = 'beautiful' #静态字段/类变量
salary = 10000
__private_v = 'you can\'t read me from outside' #私有类变量
def __init__(self,name,age):
self.name = name ##普通字段
self.age = age
__male = 'girl' #静态私有字段
self.favorite = 'cat'
def speak(self,des): ##普通方法
print "I'm {0},age {1},today is a {2} day!,so {3}".format(self.name,self.age,Person.class_v,des)
@staticmethod
def static_m(): #静态方法
print "This is a static method!"
@classmethod #类方法
def class_m(cls,*args,**kwargs):
print "This is a class method!"
@property
def attr_m(self): #属性,其实就是方法的变种
return self.favorite #这里只是个例子,实际应用中一般是通过一定的逻辑处理得到相应的值
@attr_m.setter #设置属性值
def attr_m(self,value):
self.favorite = value
return self.favorite
@attr_m.deleter #删除属性值
def attr_m(self):
del self.favorite
def read_private(self): ##普通方法
print Person.__private_v
class wo(Person): #继承
def __init__(self,name):
self.name = name
def des(self):
print "%s is a lovely girl!" % self.name
#类的实例化
obj = Person('min',18)
#访问类变量
print obj.salary
print Person.salary
obj.salary += 2000
print obj.salary
print Person.salary
Person.salary += 50000
print obj.salary
print Person.salary
##从上述结果可看出通过对象访问类变量并对其做修改并不影响在变量的值
#普通方法调用
obj.speak('nice')
#调用静态方法,必须通过类调用
Person.static_m()
#调用类方法,必须通过类调用
Person.class_m()
#访问属性
obj.attr_m
obj.attr_m = 'always cat!'
print obj.attr_m
del obj.attr_m
#测试私有类变量的打印
obj.read_private()
#访问继承类的方法
min = wo('min')
min.des()
#访问类变量
Person.class_v
#访问私有类变量
Person.__private_v ##无法访问
obj._Person__private_v #强制访问私有成员
执行结果:
1 >>> class Person:
2 ... class_v = 'beautiful' #静态字段/类变量
3 ... salary = 10000
4 ... __private_v = 'you can\'t read me from outside' #私有类变量
5 ... def __init__(self,name,age):
6 ... self.name = name ##普通字段
7 ... self.age = age
8 ... __male = 'girl' #静态私有字段
9 ... self.favorite = 'cat'
10 ... def speak(self,des): ##普通方法
11 ... print "I'm {0},age {1},today is a {2} day!,so {3}".format(self.name,self.age,Person.class_v,des)
12 ... @staticmethod
13 ... def static_m(): #静态方法
14 ... print "This is a static method!"
15 ... @classmethod #类方法
16 ... def class_m(cls,*args,**kwargs):
17 ... print "This is a class method!"
18 ... @property
19 ... def attr_m(self): #属性,其实就是方法的变种
20 ... return self.favorite #这里只是个例子,实际应用中一般是通过一定的逻辑处理得到相应的值
21 ... @attr_m.setter #设置属性值
22 ... def attr_m(self,value):
23 ... self.favorite = value
24 ... return self.favorite
25 ... @attr_m.deleter #删除属性值
26 ... def attr_m(self):
27 ... del self.favorite
28 ... def read_private(self): ##普通方法
29 ... print Person.__private_v
30 ...
31 >>> class wo(Person): #继承
32 ... def __init__(self,name):
33 ... self.name = name
34 ... def des(self):
35 ... print "%s is a lovely girl!" % self.name
36 ...
37 >>> #类的实例化
38 ... obj = Person('min',18)
39 >>> #访问类变量
40 ... print obj.salary
41 10000
42 >>> print Person.salary
43 10000
44 >>> obj.salary += 2000
45 >>> print obj.salary
46 12000
47 >>> print Person.salary
48 10000
49 >>> Person.salary += 50000
50 >>> print obj.salary
51 12000
52 >>> print Person.salary
53 60000
54 >>> ##从上述结果可看出通过对象访问类变量并对其做修改并不影响在变量的值
55 ...
56 >>> #普通方法调用
57 ... obj.speak('nice')
58 I'm min,age 18,today is a beautiful day!,so nice
59 >>> #调用静态方法,必须通过类调用
60 ... Person.static_m()
61 This is a static method!
62 >>> #调用类方法,必须通过类调用
63 ... Person.class_m()
64 This is a class method!
65 >>> #访问属性
66 ... obj.attr_m
67 'cat'
68 >>> obj.attr_m = 'always cat!'
69 >>> print obj.attr_m
70 always cat!
71 >>> del obj.attr_m
72 >>> #测试私有类变量的打印
73 ... obj.read_private()
74 you can't read me from outside
75 >>> #访问继承类的方法
76 ... min = wo('min')
77 >>> min.des()
78 min is a lovely girl!
79 >>>
80 >>> #访问类变量
81 ... Person.class_v
82 'beautiful'
83 >>> #访问私有类变量
84 ... Person.__private_v ##无法访问
85 Traceback (most recent call last):
86 File "<stdin>", line 2, in <module>
87 AttributeError: class Person has no attribute '__private_v'
88 >>> obj._Person__private_v #强制访问私有成员
89 "you can't read me from outside"
90 >>>