本章内容
- 经典类与新式类
- 静态方法、类方法、属性方法
- 类的特殊成员方法
- 反射
- 异常处理
一、经典类与新式类
Python中分为经典类和新式类:
经典类:
class A():
新式类:
class A(object):
经典类和新式类的区别就是,在声明类的时候,新式类需要加上object关键字。
Python的类可以继承多个类,Java和C#中则只能继承一个类
Python的类如果继承了多个类,那么其寻找方法有两种:
当类是经典类时,多继承情况下,会按照深度优先(纵向)方式查找
当类是新式类时,多继承情况下,会按照广度优先(横向)方式查找
在python3.x 和 python2.x中运行以下代码:
1 #!/usr/bin/env python
2 # -*- coding:utf-8 -*-
3 # Author:Lyon
4
5 class A:
6 def __init__(self):
7 self.n = 'A'
8 print("In the A")
9
10 class B(A):
11 def __init__(self):
12 self.n = 'B'
13 print("In the B")
14
15 class C(A):
16 def __init__(self):
17 self.n = 'C'
18 print("In the C")
19
20 class D(B,C):
21 # def __init__(self):
22 # self.n = 'D'
23 print("In the D")
24 #创建一个实例obj1,注释掉D()中的构造方法之后,继承B、C中的一个看结果
25 obj1 = D()
26 #打印obj1中的n
27 print(obj1.n)
28 #用B()来做比较
29 obj2 = B()
30 #打印obj2中的n
31 print(obj2.n)
32
33
34 #输出:In the D
35 # In the B
36 # B #这里我们发现D()中没有构造方法所以往B、C中找,为什么继承了B()?
37 # In the B
38 # B
在python2.x和3.x中:
Python 2.x 中默认都是经典类,只有显示继承了object才是新式类
Python 3.x 中默认都是新式类,不必显示的继承object
class A():
def __init__(self):
pass
def save(self):
print "This is from A"
class B(A):
def __init__(self):
pass
class C(A):
def __init__(self):
pass
def save(self):
print "This is from C"
class D(B,C):
def __init__(self):
pass
fun = D()
fun.save()
#经典类的答案: This is from A
#新式类的答案: This is from C
super的用法:
在python2中没有此用法,只有在3中才有。此方法大大降低了代码的维护量。
语法:super(B,self).__init__()
1 #!/usr/bin/env python
2 # -*- coding:utf-8 -*-
3 # Author:Lyon
4 #调用基类方法
5
6 # 一、 明确指定
7 class P():
8 print("In the P")
9
10 class C(P):
11 def __init__(self):
12 P.__init__(self)
13 print("In the C")
14
15 c = C()
16
17 # 二、 super()方法
18
19 class P():
20 print("In the P")
21
22 class C():
23 def __init__(self):
24 super(C,self).__init__()
25 print("In the C")
26
27 c =C()
28
29 #以上两种方法的结果都一样
30 # In the P
31 # In the C
二、静态方法、类方法、属性方法
静态方法:
通过@staticmethod装饰器即可把其他装饰的方法边变成一个静态方法。静态方法就是,普通的方法,可以在实例化后直接调用,并且在方法里可以通过 self. 调用实例变量或类变量,但静态方法是不可以访问实例变量或类变量的,一个不能访问实例变量和类变量的方法,其实相当于跟类本身已经没什么关系了,它与类唯一的关联就是需要通过类名来调用这个方法:
1 #!/usr/bin/env python
2 # -*- coding:utf-8 -*-
3 # Author:Lyon
4
5 class Dog(object):
6 def __init__(self,name):
7 self.name=name
8
9
10 @staticmethod
11 def eat(self):
12 print("%s is eating %s"%(self.name,'food'))
13
14 def talk(self):
15 print("%s is talking"%self.name)
16
17
18 d=Dog("Chengronghua")
19 # d.eat()eat方法已经通过@staticmethod变成了一个静态方法,所以已经不能像之前那样调用了
20 #静态方法不能访问实例变量或类变量,此时它与类唯的关联就是需要通过类名来调用这个方法
21
22 #这里调用有两种方法
23 #第一种就是调用时传递实例本身给eat方法,如下
24 d.eat(d)
25 #第二种就是把eat方法中的self参数给删掉,当然这也就意味着在eat中不能用self,调用实例中的其他变量了
26 d.talk()
类方法:
类方法是通过@classmethod装饰器实现,类方法和普通方法的区别是,类方法只能访问类变量,不能访问实例变量:
1 #!/usr/bin/env python
2 # -*- coding:utf-8 -*-
3 # Author:Lyon
4 class Dog(object):
5
6 name = "Gouziwei"
7 def __init__(self,name):
8 self.name=name
9
10 @classmethod #eat方法将无法访问实例变量,类方法只能访问类变量
11 def eat(self):
12 print("%s is eating %s"%(self.name,'baozi'))
13 def talk(self):
14 print("%s is talking"%self.name)
15
16 d=Dog("Chengronghua")
17 d.eat()#没有类变量就会报错
18 d.talk()
以上执行结果如果把 name = "Gouziwei" 给注释掉,就会报错:
Traceback (most recent call last):
File "D:/Users/Desktop/python/day7/类方法.py", line 17, in <module>
d.eat()#没有类变量就会报错
File "D:/Users/Desktop/python/day7/类方法.py", line 12, in eat
print("%s is eating %s"%(self.name,'baozi'))
AttributeError: type object 'Dog' has no attribute 'name'
- 类方法无法访问实例变量,只能访问类变量。
也就是说类方法中,只能用类内部存在的变量,无法与外部的实例变量连接起来。
属性方法:
属性方法的作用就是通过@property把一个方法变成一个静态属性:
1 #!/usr/bin/env python
2 # -*- coding:utf-8 -*-
3 # Author:Lyon
4 class Dog(object):
5 def __init__(self,name):
6 self.name = name
7
8 @property
9 def eat(self):
10 print("%s is eating "%self.name)
11
12 d = Dog("ChengRongHua")
13 #出现报错:TypeError: 'NoneType' object is not callable,因为这里已经不是方法了,它变成了一个静态属性,调用直接加.eat就行,不需要加括号
14 #d.eat()
15 d.eat
- @property.setter可以对其中的属性进行修改。
- @property.deleter可以将属性删除
属性方法有什么作用呢?到这里我发现属性方法好像没什么卵用,把方法变成一个静态属性,那我还不如直接定义静态属性来实现。很多情况下,很多需求是不能简单通过定义静态属性来实现的,现在只要先学着就行了,以后再慢慢体会该作用把。如下是一个航班查询的例子:
1 #!/usr/bin/env python
2 # -*- coding:utf-8 -*-
3 # Author:Lyon
4 class Flight(object):
5
6 def __init__(self,name):
7 self.flight_name = name
8
9 def checking_status(self):
10 print("checking flight %s status"%self.flight_name)
11 return 1
12
13 @property
14 def flight_status(self):
15 status = self.checking_status()
16 if status == 0:
17 print("flight got canceled.....")
18 elif status == 1:
19 print("flight has departured already...")
20 else:
21 print("cannot confirm the flight status....please check later")
22
23 f = Flight("CA980")
24 f.flight_status
实现修改flight_status属性版本:
1 #!/usr/bin/env python
2 # -*- coding:utf-8 -*-
3 # Author:Lyon
4 class Flight(object):
5
6 def __init__(self,name):
7 self.flight_name = name
8
9 def checking_status(self):
10 print("checking flight %s status"%self.flight_name)
11 return 1
12
13 @property
14 def flight_status(self):
15 status = self.checking_status()
16 if status == 0:
17 print("flight got canceled.....")
18 elif status == 1:
19 print("flight has departured already...")
20 else:
21 print("cannot confirm the flight status....please check later")
22
23 @flight_status.setter
24 def flight_status(self,status):
25 status_dic = {
26 0:"canceled",
27 1:"arrived",
28 2:"departured",
29 }
30 print("Has changed the flight status to" ,status_dic.get(status))
31
32 @flight_status.deleter
33 def flight_status(self):
34 print("status got removed......")
35
36 #创建实例
37 f = Flight("CA980")
38 #返回结果
39 f.flight_status
40 #触发@flight_status.setter
41 f.flight_status = 2
42 #触发@flight_status.delter
43 del f.flight_status
三、类的特殊成员方法
1.__doc__ 表示类的描述信息
1 class Foo:
2 '''描述类的信息'''
3 def func(self):
4 pass
5
6 print(Foo.__doc__) #输出:描述类的信息
2.__module__ 和 __class__
__module__ 表示当前操作的对象在那个模块
__class__ 表示当前操作的对象的类是什么
1 class C():
2 def __init__(self,name):
3 self.name= name
4 print("in the C....")
1 from aa import C
2
3 obj = C("Lyon")
4 print(obj.__module__) #输出:aa
5 print(obj.__class__) #输出:<class'aa.C'>
3.__init__ 构造方法,通过类创建对象时,自动触发执行。
4.__del__ 析构方法,当对象在内存中被释放时,自动触发执行。
注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。
5.__call__ 对象后面加括号,触发执行。
注:构造方法的执行是由创建对象触发的,即:对象 = 类名():而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象()或者类()()
1 #!/usr/bin/env python
2 # -*- coding:utf-8 -*-
3 # Author:Lyon
4
5 class Foo:
6
7 def __init__(self):
8 print("__init__")
9
10 def __call__(self, *args, **kwargs):
11 print("__call__")
12
13 obj = Foo() #执行__init__
14 obj() #执行__call__
6.__dict__ 查看类或对象中的所有成员
1 #!/usr/bin/env python
2 # -*- coding:utf-8 -*-
3 # Author:Lyon
4
5 class Province:
6 country = "China"
7
8 def __init__(self,name,count):
9 self.name = name
10 self.count = count
11
12 def func(self,*args,**kwargs):
13 print("func")
14 #获取类的成员,即:静态字段、访法、
15 print(Province.__dict__)
16 #输出:{'func': <function Province.func at 0x000002826C0199D8>, '__dict__': <attribute '__dict__' of 'Province' objects>, '__doc__': None, 'country': 'China', '__init__': <function Province.__init__ at 0x000002826C019950>, '__module__': '__main__', '__weakref__': <attribute '__weakref__' of 'Province' objects>}
17
18 obj1 = Province("HeBei",10000)
19 #获取对象obj的成员
20 print(obj1.__dict__)
21 #输出:{'name': 'HeBei', 'count': 10000}
22
23 obj2 = Province("HeNan",3888)
24 #获取obj2的成员
25 print(obj2.__dict__)
26 #输出:{'count': 3888, 'name': 'HeNan'}
7.__str__ 如果一个类中定义了__str__方法,那么在打印对象时,默认输出该方法的返回值。
1 class Foo:
2
3 def __str__(self):
4 return "Lyon"
5
6 obj = Foo()
7 print(obj)
8 #输出:Lyon
8.__getitem__、__setitem__、__delitem__ 用于索引操作,如字典。以上分别表示获取、设置、删除数据。
1 class Foo:
2
3 def __getitem__(self, item):
4 print("__getitem__",item)
5
6 def __setitem__(self, key, value):
7 print("__setitem__",key,value)
8
9 def __delitem__(self, key):
10 print("__delitem__",key)
11
12 obj = Foo()
13 #自动触发执行 __getitem__
14 result = obj['k1']
15 #自动触发执行 __setitem__
16 obj['k2'] = "Lyon"
17 #触发__defitem__
18 del obj['k1']
9.__new__ 和 __metaclass__
__new__()方法是在类准备将自身实例化时调用。
__new__()方法始终都是类的静态方法,即使没有被加上静态方法装饰器。
1 class Foo():
2
3 def __new__(self,name):
4 self.name = name
5 print(self.name)
6
7 obj = Foo("Lyon")
更多关于__new__的详细介绍,向这里戳。
在Python中一切皆对象,上述代码中不仅obj是对象,Foo类也是一个对象,而obj是由Foo类的构造方法创建而来,Foo类则是有type类创建而来的,看下:
1 class Foo():
2
3 def __init__(self,name):
4 self.name = name
5
6 obj = Foo("Lyon")
7 print(type(obj)) #输出:<class '__main__.Foo'>
8 print(type(Foo)) #输出:<class 'type'>
创建类有两种方法:
1)普通方式
1 class Foo(object):
2
3 def func(self):
4 print("Hello Lyon")
2)特殊方法(利用type类创建)
1 def func(self):
2 print("Hello Lyon")
3
4 Foo = type("Foo",(object,),{"func":func})
5 # type第一个参数:类名
6 # type第二个参数:当前类的基类
7 # type第三个参数:类的成员
8
9 obj = Foo()
10 obj.func() #输出:Hello Lyon
加上构造方法:
1 def func(self):
2 print("Hello %s "%self.name)
3
4 def __init__(self,name,age):
5 self.name = name
6 self.age = age
7
8 Foo = type("Foo",(object,),{'func':func,'__init__':__init__})
9 f = Foo("Lyon",21)
10 f.func()
所以类是由type类实例化产生的,那么type类又是由什么产生的呢?
类中有一个属性__metaclass__,其用来表示该类由谁来实例化创建,所以可以认为__metaclass__设置一个type类的派生类,从而查看类创建的过程。
类的生成调用顺序依次是__new__ ----> __init__ -----> __calll__
更多关于metaclass(元类)的资料,---->>
四、反射
通过字符串映射或修改程序运行时的状态、属性、方法,有一下4个方法
- getattr(object,name,default=None)
- hasattr(object,name)
- setattr(x,y,v)
- delattr(x,y)
方法如下:
1 #!/usr/bin/env python
2 # -*- coding:utf-8 -*-
3 # Author:Lyon
4
5 class Foo(object):
6
7 def __init__(self):
8 self.name = 'Lyon'
9
10 def func(self):
11 return 'func'
12
13 obj = Foo()
14 #检查是否含有成员
15 hasattr(obj,'name')
16 hasattr(obj,'func')
17 print(obj.__dict__) #输出:{'name': 'Lyon'}
18 #获取成员
19 getattr(obj,'name')
20 getattr(obj,'func')
21 print(obj.__dict__) #输出:{'name': 'Lyon'}
22 #设置成员
23 setattr(obj,'age',18)
24 setattr(obj,'show',lambda num:num+1)
25 print(obj.__dict__) #输出:{'show': <function <lambda> at 0x000001C5AC8097B8>, 'age': 18, 'name': 'Lyon'}
26 #删除成员
27 delattr(obj,'name')
28 delattr(obj,'show')
29 delattr(obj,'age')
30 print(obj.__dict__) #输出:{}
动态导入模块
1 import importlib
2
3 #这是解释器自己内部用的
4 __import__('import_lib.metaclass')
5
6 #与上面这句效果一样,官方建议用这个
7 importlib.import_module('import_lib.metaclass')
五、异常处理
1.异常基础
在编程过程中当遇到问题报错时,我们一般不会将错误信息显示给用户,而是显示一个提示的 页面,通俗来说就是不让用户看见大黄页。
1 try:
2 pass
3 except Exception:
4 pass
2.异常种类
Python中的异常种类非常多,每个异常专门用于处理某一项异常:
AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x
IOError 输入/输出异常;基本上是无法打开文件
ImportError 无法引入模块或包;基本上是路径问题或名称错误
IndentationError 语法错误(的子类) ;代码没有正确对齐
IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5]
KeyError 试图访问字典里不存在的键
KeyboardInterrupt Ctrl+C被按下
NameError 使用一个还未被赋予对象的变量
SyntaxError Python代码非法,代码不能编译(个人认为这是语法错误,写错了)
TypeError 传入对象类型与要求的不符合
UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量,导致你以为正在访问它
ValueError 传入一个调用者不期望的值,即使值的类型是正确的
1 ArithmeticError
2 AssertionError
3 AttributeError
4 BaseException
5 BufferError
6 BytesWarning
7 DeprecationWarning
8 EnvironmentError
9 EOFError
10 Exception
11 FloatingPointError
12 FutureWarning
13 GeneratorExit
14 ImportError
15 ImportWarning
16 IndentationError
17 IndexError
18 IOError
19 KeyboardInterrupt
20 KeyError
21 LookupError
22 MemoryError
23 NameError
24 NotImplementedError
25 OSError
26 OverflowError
27 PendingDeprecationWarning
28 ReferenceError
29 RuntimeError
30 RuntimeWarning
31 StandardError
32 StopIteration
33 SyntaxError
34 SyntaxWarning
35 SystemError
36 SystemExit
37 TabError
38 TypeError
39 UnboundLocalError
40 UnicodeDecodeError
41 UnicodeEncodeError
42 UnicodeError
43 UnicodeTranslateError
44 UnicodeWarning
45 UserWarning
46 ValueError
47 Warning
48 ZeroDivisionError
实例:
1 dic = ["wupeiqi", 'alex']
2 try:
3 dic[10]
4 except IndexError, e:
5 print e
1 dic = {'k1':'v1'}
2 try:
3 dic['k20']
4 except KeyError, e:
5 print e
1 s1 = 'hello'
2 try:
3 int(s1)
4 except ValueError, e:
5 print e
上述的异常类只能用来处理指定的异常情况,还有非指定异常处理:
1 # 未捕获到异常,程序直接报错
2
3 s1 = 'hello'
4 try:
5 int(s1)
6 except IndexError,e:
7 print e
我们还可以这样写
1 s1 = 'hello'
2 try:
3 int(s1)
4 except IndexError,e:
5 print e
6 except KeyError,e:
7 print e
8 except ValueError,e:
9 print e
万能异常,在python的异常中,有一个万能异常:Exception,它可以捕获任意异常,即:
1 s1 = 'hello'
2 try:
3 int(s1)
4 except Exception,e:
5 print e
在我们实际应用中,对于特殊处理或提醒的异常需要先定义,最后定义Exception来确保程序正常运行。如下:
1 s1 = 'hello'
2 try:
3 int(s1)
4 except KeyError,e:
5 print '键错误'
6 except IndexError,e:
7 print '索引错误'
8 except Exception, e:
9 print '错误'
3.异常其他结构
1 try:
2 # 主代码块
3 pass
4 except KeyError,e:
5 # 异常时,执行该块
6 pass
7 else:
8 # 主代码块执行完,执行该块
9 pass
10 finally:
11 # 无论异常与否,最终执行该块
12 pass
4.主动触发异常
1 try:
2 raise Exception('错误了。。。')
3 except Exception,e:
4 print e
5.自定义异常
1 class WupeiqiException(Exception):
2
3 def __init__(self, msg):
4 self.message = msg
5
6 def __str__(self):
7 return self.message
8
9 try:
10 raise WupeiqiException('我的异常')
11 except WupeiqiException,e:
12 print e
6.断言
1 # assert 条件
2
3 assert 1 == 1
4
5 assert 1 == 2
断定1等于1,为True则继续往下运行,为False则执行中断
注:本文仅为学习笔记、摘要。
详细来源:http://www.cnblogs.com/alex3714/articles/5213184.html
http://www.cnblogs.com/wupeiqi/articles/5017742.html