python基础6
一.面向对象简介
1.面向对象的特性:
1.1封装:
封装是面向对象的特征之一,是对象和类概念的主要特性。
封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。
1.1继承:
面向对象编程 (OOP) 语言的一个主要功能就是“继承”。继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。
通过继承创建的新类称为“子类”或“派生类”。
被继承的类称为“基类”、“父类”或“超类”。
继承的过程,就是从一般到特殊的过程。
要实现继承,可以通过“继承”(Inheritance)和“组合”(Composition)来实现。
在某些 OOP 语言中,一个子类可以继承多个基类。但是一般情况下,一个子类只能有一个基类,要实现多重继承,可以通过多级继承来实现。
继承概念的实现方式主要有2类:实现继承、接口继承。
OO开发范式大致为:划分对象→抽象类→将类组织成为层次化结构(继承和合成) →用类与实例进行设计和实现几个阶段。
继承示例:
#!_*_coding:utf-8_*_
#__author__:"Alex Li"
class
SchoolMember(
object
):
members
=
0
#初始学校人数为0
def
__init__(
self
,name,age):
self
.name
=
name
self
.age
=
age
def
tell(
self
):
pass
def
enroll(
self
):
'''注册'''
SchoolMember.members
+
=
1
print
(
"\033[32;1mnew member [%s] is enrolled,now there are [%s] members.\033[0m "
%
(
self
.name,SchoolMember.members))
def
__del__(
self
):
'''析构方法'''
print
(
"\033[31;1mmember [%s] is dead!\033[0m"
%
self
.name)
class
Teacher(SchoolMember):
def
__init__(
self
,name,age,course,salary):
super
(Teacher,
self
).__init__(name,age)
self
.course
=
course
self
.salary
=
salary
self
.enroll()
def
teaching(
self
):
'''讲课方法'''
print
(
"Teacher [%s] is teaching [%s] for class [%s]"
%
(
self
.name,
self
.course,
's12'
))
def
tell(
self
):
'''自我介绍方法'''
msg
=
'''Hi, my name is [%s], works for [%s] as a [%s] teacher !'''
%
(
self
.name,'Oldboy',
self
.course)
print
(msg)
class
Student(SchoolMember):
def
__init__(
self
, name,age,grade,sid):
super
(Student,
self
).__init__(name,age)
self
.grade
=
grade
self
.sid
=
sid
self
.enroll()
def
tell(
self
):
'''自我介绍方法'''
msg
=
'''Hi, my name is [%s], I'm studying [%s] in [%s]!'''
%
(
self
.name,
self
.grade,'Oldboy')
print
(msg)
if
__name__
=
=
'__main__'
:
t1
=
Teacher(
"Alex"
,
22
,
'Python'
,
20000
)
t2
=
Teacher(
"TengLan"
,
29
,
'Linux'
,
3000
)
s1
=
Student(
"Qinghua"
,
24
,
"Python S12"
,
1483
)
s2
=
Student(
"SanJiang"
,
26
,
"Python S12"
,
1484
)
t1.teaching()
t2.teaching()
t1.tell()
1.3多态
#_*_coding:utf-8_*_
class
Animal(
object
):
def
__init__(
self
, name):
# Constructor of the class
self
.name
=
name
def
talk(
self
):
# Abstract method, defined by convention only
raise
NotImplementedError(
"Subclass must implement abstract method"
)
class
Cat(Animal):
def
talk(
self
):
print
(
'%s: 喵喵喵!'
%
self
.name)
class
Dog(Animal):
def
talk(
self
):
print
(
'%s: 汪!汪!汪!'
%
self
.name)
def
func(obj):
#一个接口,多种形态
obj.talk()
c1
=
Cat(
'小晴'
)
d1
=
Dog(
'李磊'
)
func(c1)
func(d1)
2.领域模型
领域模型有两个主要的作用:
- 发掘重要的业务领域概念
- 建立业务领域概念之间的关系
领域建模的三字经方法:找名词、加属性、连关系。
二.面向对象高级语法部分
1.经典类vs新式类
- 经典类:深度优先
- 新式类:广度优先
- super()用法
2.抽象接口
2.1静态方法
通过@staticmethod装饰器即可把其装饰的方法变为一个静态方法,什么是静态方法呢?其实不难理解,普通的方法,可以在实例化后直接调用,并且在方法里可以通过self.调用实例变量或类变量,但静态方法是不可以访问实例变量或类变量的,一个不能访问实例变量和类变量的方法,其实相当于跟类本身已经没什么关系了,它与类唯一的关联就是需要通过类名来调用这个方法。
class
Dog(
object
):
def
__init__(
self
,name):
self
.name
=
name
@staticmethod
#把eat方法变为静态方法
def
eat(
):
print
(
"is eating"
)
d
=
Dog(
"ChenRonghua"
)
d.eat()
2.2类方法
类方法通过@classmethod装饰器实现,类方法和普通方法的区别是, 类方法只能访问类变量,不能访问实例变量
class
Dog(
object
):
name
=
"我是类变量" #要定义成类变量
def
__init__(
self
,name):
self
.name
=
name
@classmethod #调用类变量
def
eat(
cls
):
print
(
"%s is eating"
%
cls
.name)
d
=
Dog(
"ChenRonghua"
)
d.eat()
#执行结果
我是类变量
is
eating
2.3属性方法
属性方法的作用就是通过@property把一个方法变成一个静态属性
class
Dog(
object
):
def
__init__(
self
,name):
self
.name
=
name
@property
def
eat(
self
):
print
(
" %s is eating"
%
self
.name)
d
=
Dog(
"ChenRonghua"
)
d.eat
输出
ChenRonghua
is
eating
好吧,把一个方法变成静态属性有什么卵用呢?既然想要静态变量,那直接定义成一个静态变量不就得了么?well, 以后你会需到很多场景是不能简单通过 定义 静态属性来实现的,
比如 ,你想知道一个航班当前的状态,是到达了、延迟了、取消了、还是已经飞走了, 想知道这种状态你必须经历以下几步:
1. 连接航空公司API查询
2. 对查询结果进行解析
3. 返回结果给你的用户
因此这个status属性的值是一系列动作后才得到的结果,所以你每次调用时,其实它都要经过一系列的动作才返回你结果,但这些动作过程不需要用户关心, 用户只需要调用这个属性就可以,明白 了么?
class Flight(object):
def __init__(self,name):
self.flight_name = name
def checking_status(self):
print("checking flight %s status " % self.flight_name)
return 1
@property
def flight_status(self):
status = self.checking_status()
if status == 0 :
print("flight got canceled...")
elif status == 1 :
print("flight is arrived...")
elif status == 2:
print("flight has departured already...")
else:
print("cannot confirm the flight status...,please check later")
f = Flight("CA980")
f.flight_status
那现在我只能查询航班状态, 既然这个flight_status已经是个属性了, 那我能否给它赋值呢?试试吧
f
=
Flight(
"CA980"
)
f.flight_status
f.flight_status
=
2
checking flight CA980 status
flight
is
arrived...
Traceback (most recent call last):
File
"/Users/jieli/PycharmProjects/python基础/自动化day7面向对象高级/属性方法.py"
, line
58
,
in
<module>
f.flight_status
=
2
AttributeError: can't
set
attribute
class Flight(object): def __init__(self,name): self.flight_name = name def checking_status(self): print("checking flight %s status " % self.flight_name) return 1 @property def flight_status(self): status = self.checking_status() if status == 0 : print("flight got canceled...") elif status == 1 : print("flight is arrived...") elif status == 2: print("flight has departured already...") else: print("cannot confirm the flight status...,please check later") @flight_status.setter #修改 def flight_status(self,status): status_dic = { 0 : "canceled", 1 :"arrived", 2 : "departured" } print("\033[31;1mHas changed the flight status to \033[0m",status_dic.get(status) ) @flight_status.deleter #删除 def flight_status(self): print("status got removed...") f = Flight("CA980") f.flight_status f.flight_status = 2 #触发@flight_status.setter del f.flight_status #触发@flight_status.deleter
注意以上代码里还写了一个@flight_status.deleter, 是允许可以将这个属性删除
3.类的特殊成员方法
3.1. __doc__ 表示类的描述信息
class
Foo:
""" 描述类信息,这是用于看片的神奇 """
def
func(
self
):
pass
print
Foo.__doc__
#输出:类的描述信息
3.2. __module__ 和 __class__
__module__ 表示当前操作的对象在那个模块
__class__ 表示当前操作的对象的类是什么
class C:
def __init__(self):
self.name = 'wupeiqi'
from lib.aa import C
obj = C()
print obj.__module__ # 输出 lib.aa,即:输出模块
print obj.__class__ # 输出 lib.aa.C,即:输出类
3.3. __init__ 构造方法,通过类创建对象时,自动触发执行
3.4.__del__
析构方法,当对象在内存中被释放时,自动触发执行。
注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,
所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的
3.5.__call__ 对象后面加括号,触发执行。
注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()
class
Foo:
def
__init__(
self
):
pass
def
__call__(
self
,
*
args,
*
*
kwargs):
print
'__call__'
obj
=
Foo()
# 执行 __init__
obj()
# 执行 __call__
3.6. __dict__ 查看类或对象中的所有成员
class
Province:
country
=
'China'
def
__init__(
self
, name, count):
self
.name
=
name
self
.count
=
count
def
func(
self
,
*
args,
*
*
kwargs):
print
'func'
# 获取类的成员,即:静态字段、方法、
print
Province.__dict__
# 输出:{'country': 'China', '__module__': '__main__', 'func': <function func at 0x10be30f50>, '__init__': <function __init__ at 0x10be30ed8>, '__doc__': None}
obj1
=
Province(
'HeBei'
,
10000
)
print
obj1.__dict__
# 获取 对象obj1 的成员
# 输出:{'count': 10000, 'name': 'HeBei'}
obj2
=
Province(
'HeNan'
,
3888
)
print
obj2.__dict__
# 获取 对象obj1 的成员
# 输出:{'count': 3888, 'name': 'HeNan'}
3.7.__str__ 如果一个类中定义了__str__方法,那么在打印 对象 时,默认输出该方法的返回值。
class
Foo:
def
__str__(
self
):
return
'alex li'
obj
=
Foo()
print
obj
# 输出:alex li
3.8.__getitem__、__setitem__、__delitem__
用于索引操作,如字典。以上分别表示获取、设置、删除数据
class
Foo(
object
):
def
__getitem__(
self
, key):
print
(
'__getitem__'
,key)
def
__setitem__(
self
, key, value):
print
(
'__setitem__'
,key,value)
def
__delitem__(
self
, key):
print
(
'__delitem__'
,key)
obj
=
Foo()
result
=
obj[
'k1'
]
# 自动触发执行 __getitem__
obj[
'k2'
]
=
'alex'
# 自动触发执行 __setitem__
del
obj[
'k1'
]
3.9. __new__ \ __metaclass__
class
Foo(
object
):
def
__init__(
self
,name):
self
.name
=
name
f
=
Foo(
"alex"
)
print
type
(f)
# 输出:<class '__main__.Foo'> 表示,obj 对象由Foo类创建
print
type
(Foo)
# 输出:<type 'type'> 表示,Foo类对象由 type 类创建
所以,f对象是Foo类的一个实例,Foo类对象是 type 类的一个实例,即:Foo类对象 是通过type类的构造方法创建。
那么,创建类就可以有两种方式:
a). 普通方式
class
Foo(
object
):
def
func(
self
):
print
'hello alex'
def
func(
self
):
print
'hello wupeiqi'
Foo
=
type
(
'Foo'
,(
object
,), {
'func'
: func})
#type第一个参数:类名
#type第二个参数:当前类的基类
#type第三个参数:类的成员
def func(self):
print("hello %s"%self.name)
def __init__(self,name,age):
self.name = name
self.age = age
Foo = type('Foo',(object,),{'func':func,'__init__':__init__})
f = Foo("jack",22)
f.func()
So ,孩子记住,类 是由 type 类实例化产生
那么问题来了,类默认是由 type 类实例化产生,type类中如何实现的创建类?类又是如何创建对象?
答:类中有一个属性 __metaclass__,其用来表示该类由 谁 来实例化创建,所以,我们可以为 __metaclass__ 设置一个type类的派生类,从而查看 类 创建的过程。
自定义元类:
1 class MyType(type):
2 def __init__(self,*args,**kwargs):
3
4 print("Mytype __init__",*args,**kwargs)
5
6 def __call__(self, *args, **kwargs):
7 print("Mytype __call__", *args, **kwargs)
8 obj = self.__new__(self)
9 print("obj ",obj,*args, **kwargs)
10 print(self)
11 self.__init__(obj,*args, **kwargs)
12 return obj
13
14 def __new__(cls, *args, **kwargs):
15 print("Mytype __new__",*args,**kwargs)
16 return type.__new__(cls, *args, **kwargs)
17
18 print('here...')
19 class Foo(object,metaclass=MyType):
20
21
22 def __init__(self,name):
23 self.name = name
24
25 print("Foo __init__")
26
27 def __new__(cls, *args, **kwargs):
28 print("Foo __new__",cls, *args, **kwargs)
29 return object.__new__(cls)
30
31 f = Foo("Alex")
32 print("f",f)
33 print("fname",f.name)
类的生成 调用 顺序依次是 __new__ --> __init__ --> __call__
4.其他相关
4.1. isinstance(obj, cls) #检查是否obj是否是类 cls 的对象
class
Foo(
object
):
pass
obj
=
Foo()
isinstance
(obj, Foo)
class
Foo(
object
):
pass
class
Bar(Foo):
pass
issubclass
(Bar, Foo)
import
importlib
__import__
(
'import_lib.metaclass'
)
#这是解释器自己内部用的
#importlib.import_module('import_lib.metaclass') #与上面这句效果一样,官方建议用这个
三、异常处理
1、异常基础
try
:
pass
except
Exception,ex:
pass
while True:
num1 = raw_input('num1:')
num2 = raw_input('num2:')
try:
num1 = int(num1)
num2 = int(num2)
result = num1 + num2
except Exception, e:
print '出现异常,信息如下:'
print e
AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x
IOError 输入/输出异常;基本上是无法打开文件
ImportError 无法引入模块或包;基本上是路径问题或名称错误
IndentationError 语法错误(的子类) ;代码没有正确对齐
IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5]
KeyError 试图访问字典里不存在的键
KeyboardInterrupt Ctrl+C被按下
NameError 使用一个还未被赋予对象的变量
SyntaxError Python代码非法,代码不能编译(个人认为这是语法错误,写错了)
TypeError 传入对象类型与要求的不符合
UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量,
导致你以为正在访问它
ValueError 传入一个调用者不期望的值,即使值的类型是正确的
ArithmeticError
AssertionError
AttributeError
BaseException
BufferError
BytesWarning
DeprecationWarning
EnvironmentError
EOFError
Exception
FloatingPointError
FutureWarning
GeneratorExit
ImportError
ImportWarning
IndentationError
IndexError
IOError
KeyboardInterrupt
KeyError
LookupError
MemoryError
NameError
NotImplementedError
OSError
OverflowError
PendingDeprecationWarning
ReferenceError
RuntimeError
RuntimeWarning
StandardError
StopIteration
SyntaxError
SyntaxWarning
SystemError
SystemExit
TabError
TypeError
UnboundLocalError
UnicodeDecodeError
UnicodeEncodeError
UnicodeError
UnicodeTranslateError
UnicodeWarning
UserWarning
ValueError
Warning
ZeroDivisionError
示例:
dic = ["wupeiqi", 'alex'] try: dic[10] except IndexError, e: print e
dic = {'k1':'v1'}
try:
dic['k20']
except KeyError, e:
print e
s1 = 'hello'
try:
int(s1)
except ValueError, e:
print e
对于上述实例,异常类只能用来处理指定的异常情况,如果非指定异常则无法处理。
# 未捕获到异常,程序直接报错
s1
=
'hello'
try
:
int
(s1)
except
IndexError,e:
print
e
s1
=
'hello'
try
:
int
(s1)
except
IndexError,e:
print
e
except
KeyError,e:
print
e
except
ValueError,e:
print
e
s1
=
'hello'
try
:
int
(s1)
except
Exception,e:
print
e
接下来你可能要问了,既然有这个万能异常,其他异常是不是就可以忽略了!
答:当然不是,对于特殊处理或提醒的异常需要先定义,最后定义Exception来确保程序正常运行s1
=
'hello'
try
:
int
(s1)
except
KeyError,e:
print
'键错误'
except
IndexError,e:
print
'索引错误'
except
Exception, e:
print
'错误'
try
:
# 主代码块
pass
except
KeyError,e:
# 异常时,执行该块
pass
else
:
# 主代码块执行完,执行该块
pass
finally
:
# 无论异常与否,最终执行该块
pass
try
:
raise
Exception(
'错误了。。。'
)
except
Exception,e:
print
e
class
WupeiqiException(Exception):
def
__init__(
self
, msg):
self
.message
=
msg
def
__str__(
self
):
return
self
.message
try
:
raise
WupeiqiException(
'我的异常'
)
except
WupeiqiException,e:
print
e
# assert 条件
assert
1
=
=
1
assert
1
=
=
2
四.反射
python中的反射功能是由以下四个内置函数提供:hasattr、getattr、setattr、delattr,改四个函数分别用于对对象内部执行:检查是否含有某成员、获取成员、设置成员、删除成员。
getattr(object,name,default=none) #检查是否含有某成员
hasattr(object,name) #判断object中有没有一个name字符串对应的方法或属性
setattr(x,y,v) #设置成员
delattr(x,y) 删除成员
示例:
class Foo(object):
def __init__(self):
self.name = 'wupeiqi'
def func(self):
return 'func'
obj = Foo()
# #### 检查是否含有成员 ####
hasattr(obj, 'name')
hasattr(obj, 'func')
# #### 获取成员 ####
getattr(obj, 'name')
getattr(obj, 'func')
# #### 设置成员 ####
setattr(obj, 'age', 18)
setattr(obj, 'show', lambda num: num + 1)
# #### 删除成员 ####
delattr(obj, 'name')
delattr(obj, 'func')