一. 面向过编程成及面向对象编程
面向过程概念
面向过程编程依赖 - 你猜到了- procedures,一个procedure包含一组要被进行计算的步骤, 面向过程又被称为top-down languages, 就是程序从上到下一步步执行,一步步从上到下,从头到尾的解决问题 。基本设计思路就是程序一开始是要着手解决一个大的问题,然后把一个大问题分解成很多个小问题或子过程,这些子过程再执行的过程再继续分解直到小问题足够简单到可以在一个小步骤范围内解决。
面向对象概念
OOP编程是利用“类”和“对象”来创建各种模型来实现对真实世界的描述,使用面向对象编程的原因一方面是因为它可以使程序的维护和扩展变得更简单,并且可以大大提高程序开发效率 ,另外,基于面向对象的程序可以使它人更加容易理解你的代码逻辑,从而使团队开发变得更从容。
面向对象的几个核心特性如下
Class 类
一个类即是对一类拥有相同属性的对象的抽象、蓝图、原型。在类中定义了这些对象的都具备的属性(variables(data))、共同的方法
Object 对象
一个对象即是一个类的实例化后实例,一个类必须经过实例化后方可在程序中调用,一个类可以实例化多个对象,每个对象亦可以有不同的属性,就像人类是指所有人,每个人是指具体的对象,人与人之前有共性,亦有不同
Encapsulation 封装
在类中对数据的赋值、内部调用对外部用户是透明的,这使类变成了一个胶囊或容器,里面包含着类的数据和方法,防止数据被随意修改,使外部程序不需要关注程序内部结构,只需要通过此对象对外的外部接口进项访问即可;
Inheritance 继承
一个类可以派生出子类,在这个父类里定义的属性、方法自动被子类继承
通过父类到子类的方式实现,不同角色有不同功能
Polymorphism 多态
多态是面向对象的重要特性,简单点说:“一个接口,多种实现”,指一个基类中派生出了不同的子类,且每个子类在继承了同样的方法名的同时又对父类的方法做了不同的实现,这就是同一种事物表现出的多种形态。
编程其实就是一个将具体世界进行抽象化的过程,多态就是抽象化的一种体现,把一系列具体事物的共同点抽象出来, 再通过这个抽象的事物, 与不同的具体事物进行对话。
对不同类的对象发出相同的消息将会有不同的行为。比如,你的老板让所有员工在九点钟开始工作, 他只要在九点钟的时候说:“开始工作”即可,而不需要对销售人员说:“开始销售工作”,对技术人员说:“开始技术工作”, 因为“员工”是一个抽象的事物, 只要是员工就可以开始工作,他知道这一点就行了。至于每个员工,当然会各司其职,做各自的工作。
多态允许将子类的对象当作父类的对象使用,某父类型的引用指向其子类型的对象,调用的方法是该子类型的方法。这里引用和调用方法的代码编译前就已经决定了,而引用所指向的对象可以在运行期间动态绑定
二. 类
类的实例化
class test(object):
count = 10 #静态字段,共有属性,每个对象中保存相同东西时,可以用到
def __init__(self, name): #构建函数,初始化方法
self.NAME = name
def func(self): #类的方法
print 'my name is ', self.NAME
me = test('func') #实例化类
me.func() #调用类的方法
类的封装
封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。
私有属性 : __private_name = value
class test(object):
def __init__(self, name):
self.NAME = name
self.__age = '19' #定义私有属性
def func(self):
print('my name is ', self.NAME)
print(self.__age)
me = test('func') #实例化类
me.func() #调用类的方法
print(me.__age) #这种是错误的写法,在类的外部无法调用私有属性
print(me._test__age) #强制访问定义的私有属性
只读私有属性,外部无法修改
class test(object):
def __init__(self, name):
self.NAME = name
self.__age = '19' #定义私有属性
def func(self):
print 'my name is ', self.NAME
print self.__age
def get_age(self): #对外提供只读接口
return self.__age
me = test('func') #实例化类
me.func() #调用类的方法
print(me.get_age()) #查看私有方法的数据
共有属性,所有属于我这个类的对象都可以访问;
在类里面直接定义的属性就是共有属性,代码如下:
class test(object):
shengfen = 'sx' #设置共有属性
def __init__(self, name):
self.NAME = name
self.__age = '19' #定义私有属性
def func(self):
print 'my name is ', self.NAME
print self.__age
def get_age(self):
return self.__age
me = test('func')
me1 = test('ru')
me.func()
test.shengfen = 'sh' #修改全局共有属性
me.shengfen = 'bj' #修改某一个对象共有属性
print(me.shengfen)
print(me1.shengfen)
def fun(self): #自己在外部定义一个属性
print('your name is ', self.NAME)
me.func = fun
print(me.func(me1))
析构函数
'__init__' 构建函数, __del__ 析构函数
当使用del 删除对象时,会调用他本身的析构函数,另外当对象在某个作用域中调用完毕,在跳出其作用域的同时析构函数也会被调用一次,这样可以用来释放内存空间。
class test(object):
shengfen = 'sx' #设置共有属性
def __init__(self, name):
self.NAME = name
self.__age = '19' #定义私有属性
def func(self):
print 'my name is ', self.NAME
print self.__age
def get_age(self):
return self.__age
def __del__(self):
print('del..')
me = test('func')
继承
它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。
通过继承创建的新类称为“子类”或“派生类”。
被继承的类称为“基类”、“父类”或“超类”。
继承的过程,就是从一般到特殊的过程。
要实现继承,可以通过“继承”(Inheritance)和“组合”(Composition)来实现。
class SchoolNumber(object):
Number = 0
def __init__(self, name, age, role):
self.name = name
self.age = age
self.role = role
self.enrool()
def enrool(self):
'''注册'''
SchoolNumber.Number += 1
print('just enrol a new school number %s,学员号: %s'%(self.name, self.Number))
def tell(self):
print('-------init %s-------'%self.name)
for k,v in self.__dict__.items():
print('\t',k,v)
def __del__(self):
print('fdsafdsafdsa %s'%self.name)
SchoolNumber.Number -= 1
print(SchoolNumber.Number)
class Teacher(SchoolNumber): #继承父类
def __init__(self,name, age, role, salary, cou):
SchoolNumber.__init__(self,name, age, role) #经典类写法
#super(Teacher, self).__init(name, age, role) #新式类写法
self.salary = salary
self.cou = cou
def teaching(self):
print('teacher %s is teanching %s'%(self.name, self.cou))
class xuesheng(SchoolNumber):
def __init__(self,name,age,role, cou, tuiting):
SchoolNumber.__init__(self, name, age, role)
self.cou = cou
self.tuiting = tuiting
self.amount = 0
def pay_cou(self, amount):
print('std%s, %s'%(self.name, amount))
self.amount += amount
t1 = Teacher('dawei', 18, 'ter', 3000, 'python')
t2 = Teacher('dawei1', 18, 'ter', 3000, 'python')
t3 = Teacher('dawei2', 18, 'ter', 3000, 'python')
t1.tell()
t2.tell()
t3.tell()
三 面向对象的使用场景
1. 如果多个函数传入多个共同参数时,可使用面向对象;
2. 根据一个模板创建某些数据时;
四 类的特殊方法
内部__call__函数
一个类实例也可以变成一个可调用对象,只需要实现一个特殊方法__call__()。
我们把 Person 类变成一个可调用对象:
class Person(object):
def __init__(self, name, gender):
self.name = name
self.gender = gender
def __call__(self, friend):
print 'My name is %s...' % self.name
print 'My friend is %s...' % friend
现在可以对 Person 实例直接调用:
>>> p = Person('Bob', 'male')
>>> p('Tim')
My name is Bob...
My friend is Tim...
__str__
__str__和__repr__
如果要把一个类的实例变成 str,就需要实现特殊方法__str__():
class Person(object):
def __init__(self, name, gender):
self.name = name
self.gender = gender
def __str__(self):
return '(Person: %s, %s)' % (self.name, self.gender)
现在,在交互式命令行下用 print 试试:
>>> p = Person('Bob', 'male')
>>> print p
(Person: Bob, male)
但是,如果直接敲变量 p:
>>> p
<main.Person object at 0x10c941890>
似乎__str__() 不会被调用。
因为 Python 定义了__str__()和__repr__()两种方法,__str__()用于显示给用户,而__repr__()用于显示给开发人员。
有一个偷懒的定义__repr__的方法:
class Person(object):
def __init__(self, name, gender):
self.name = name
self.gender = gender
def __str__(self):
return '(Person: %s, %s)' % (self.name, self.gender)
__repr__ = __str__
任务
请给Student 类定义__str__和__repr__方法,使得能打印出<Student: name, gender, score>:
class Student(Person):
def __init__(self, name, gender, score):
super(Student, self).__init__(name, gender)
self.score = score
?不会了怎么办
只要为Students 类加上__str__()和__repr__()方法即可。
参考代码:
class Person(object):
def __init__(self, name, gender):
self.name = name
self.gender = gender
class Student(Person):
def __init__(self, name, gender, score):
super(Student, self).__init__(name, gender)
self.score = score
def __str__(self):
return '(Student: %s, %s, %s)' % (self.name, self.gender, self.score)
__repr__ = __str__
s = Student('Bob', 'male', 88)
print s
五 反射
hasattr(obj,name_job) ,判断一个对象obj里面是否有相应的name_job字符串
getattr(obj,name_job) 根据字符串去获取obj对象里对应的方法内存地址
setattr(object, name, values) 给对象的属性赋值,若属性不存在,先创建再赋值
class Dog(object):
def __init__(self, name):
self.name = name
def eat(self):
print('%s is eating' %self.name)
d = Dog('kaila')
choice = raw_input('>>:')
if hasattr(d, choice):
getattr(d, choice)()
else:
setattr(d, choice)
# #### 设置成员 ####
setattr(obj, 'age', 18)
setattr(obj, 'show', lambda num: num + 1)
# #### 删除成员 ####
delattr(obj, 'name')
delattr(obj, 'func')
六 异常处理
常见错误
AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x
IOError 输入/输出异常;基本上是无法打开文件
ImportError 无法引入模块或包;基本上是路径问题或名称错误
IndentationError 语法错误(的子类) ;代码没有正确对齐
IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5]
KeyError 试图访问字典里不存在的键
KeyboardInterrupt Ctrl+C被按下
NameError 使用一个还未被赋予对象的变量
SyntaxError Python代码非法,代码不能编译(个人认为这是语法错误,写错了)
TypeError 传入对象类型与要求的不符合
UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量,
导致你以为正在访问它
ValueError 传入一个调用者不期望的值,即使值的类型是正确的
try:
# 主代码块
pass
except KeyError,e:
# 异常时,执行该块
pass
else:
# 主代码块执行完,执行该块
pass
finally:
# 无论异常与否,最终执行该块
pass
自定义异常
class ffException(Exception):
def __init__(self, msg):
self.message = msg
def __str__(self):
return self.message
try:
raise ffException('我的异常')
except ffException,e:
print e
七 动态导入模块
将字符串导入成模块
import importlib
a = importlib.import_module('lib.cc')
print(a.B().name)