python&&面向对象&&学习笔记
python&&面向对象&&学习笔记
反射
反射的应用示例一:便捷、灵活的模块函数导入
#!/usr/bin/env python
#coding:utf-8
#反射示例
#仅使用内置函数执行demo模块下的foo函数
#定义字符串形式的demo模块以及demo模块下的foo函数
str1 = 'demo'
str2 = 'foo'
#使用'__import__'导入模块,等同于'import demo'
module = __import__(str1)
#使用'getattr(object, 字符串形式的foo函数)'导入模块demo下的foo函数,并将返回值foo函数赋值给'func'
func = getattr(module, str2)
#执行函数
func()
#常用于简化并灵活的调用xx模块下的xx函数的场景,如web框架中点击打开不同网页时调用不同文件夹下不同模块下的内部函数。省略了路径的if判断。
##当import为'import backend.account'形式时
'''
str3 = 'account'
str4 = 'login'
userSpace = __import__('backend.'+str3)#使用'+'拼接符导入完整模块
module2 = getattr(userSpace,str3)#导入文件
func2 = getattr(module2,str4)#导入函数
func2()
'''
如下图所示,反射方法经典示例
如下图所示,是可读性强的url匹配切换模块代码,较上面所学之反射方法而言,具有较强的代码可调式性、可读性。
装饰器
简单装饰器示例一
#!/usr/bin/env python
#coding:utf-8
#定义一个装饰器函数
def outer(fun):
#使用'arg'传递形参
def wrapper(arg):
print('前置验证')
#通过将fun函数的返回值赋值给result,通过再次'rturn'返回fun函数的返回值
result = fun(arg)
return result
return wrapper()
#装饰器示例
#常适用于因为客户的特殊需求,导致需要对大部分代码手动修改的场景
#定义部分简单函数
#使用'@outer'将定义的装饰器函数与要操作的函数建立联系。'@outer' 等用于 'outer(foo1)'
@outer
def foo1():
print('这是demo模块下foo1函数')
return 'return'
@outer
def foo2(arg):
print('这是demo模块下foo2函数',arg)
def foo3():
print('这是demo模块下foo3函数')
response = foo2('alex')
print(response)
简单装饰器示例二
向装饰器传递任意函数
如下图所示,可以对装饰器传递参数(函数),实现在执行原始函数前执行任意函数,或在执行原始函数后执行任意函数。
面向对象编程
对象是类的实例化
#!/usr/bin/env python
#coding:utf-8
#创建类person,定义类的字段name等
#令类person继承object,实现可读特性和可写特性的功能
class person(object):
#在类的初次缩进内声明的变量'live'等,皆属于类本身的
live = '地球,目前人类可以生存的唯一星球'
#'__init__' 为 '实例化 '这个动作提供函数,该函数可用于接收name参数值等
#形式: def 方法(self,xxx) 如 ,def __init__(self,name),也被称为类的方法
def __init__(self,name,flag):
#在函数'__init__'中声明的变量'Name'为局部变量,皆属于对象本身的
#形式: self.字段 = 形参 如 self.Name = name,也被称为动态字段
self.Name = name
#定义私有字段Thailand,私有字段无法通过'personOne.__Thailand'的方式输出属性值
self.__Thailand = flag
#对象的方法
def learn(self,subject):
print(self.Name + '正在学习' + subject)
#如下所示,将动态方法转为静态方法
#使用装饰器'staticmethod',将动态方法变成静态方法。因为'self'指代对象,因此该方法不保留参数'self'
#静态方法常适用于(不实例化类)舍弃创建对象的步骤,直接使用'类.静态方法'的方式直接使用类的方法
@staticmethod
def foo():
print('you you zhen shuai')
#如下所示,将方法变化为特性。
#特性可以实现将方法的访问形式(xxx.方法())变成字段的访问形式(xxx.特性)。即没有了括号'()'
#使用装饰器'property',将方法变化为特性
@property
def today(self):
print(self.Name)
return self.Name
#如下所示,定义show方法,通过show方法在类内部输出私有字段(属性)的值。
def show(self):
print(self.__Thailand)
#如下所示,首先定义一个私有 方法'__selfFun'
def __selfFun(self):
print('this is a self function')
#其次定义一个公有方法shareFun,在公有方法内部调用私有方法可以实现对私有方法的访问
def shareFun(self):
self.__selfFun()
#只读特性和只写特性
#推荐以以下方式访问和修改私有字段
#使用装饰器'@property',实现只读私有字段
@property
def Thailand(self):
return self.__Thailand
#使用装饰器'@函数名称.setter',实现更改(可写)私有字段
@Thailand.setter
def Thailand(self,value):
self.__Thailand = value
#实例化类,形成对象
personOne = person('dfq','this is a 私有字段')
print(personOne)
print(personOne.Name)
print(type(personOne))
#形式: 类.字段 如 person.live,也被称为静态字段
print(person.live)
#输出对象的方法的执行结果
personOne.learn('python')
#输出类的静态方法的执行结果
person.foo()
#访问类的特性
personOne.today
#调用show函数输出类内部私有字段的值
personOne.show()
#或使用'_类名称__私有字段名称'的方式输出类内部私有字段的值
print(personOne._person__Thailand)
#调用公有方法shareFun,实现间接的对私有方法的调用
personOne.shareFun()
#输出只读私有字段的值
print(personOne.Thailand)
#更改可写私有字段的值
personOne.Thailand = 'ha ha,更改了私有字段的值'
print(personOne.Thailand)
#输出对象全部字段的值(以'key':'value'的形式)
#print(对象.__dict__)
#输出对象全部方法、字段、property等的值
#print(dir(对象))
1.类的特性 :类具有封装性(类的属性赋值封装形成对象)
2.‘self’ : 指代未封装完成的对象,self接收对象的属性和值
3._init_ : 类的__init__函数实现对 对象 属性的赋值
4.静态字段属于类,动态字段属于对象
5.类不能访问动态字段,对象可以访问静态字段
使用类的静态方法与使用模块.函数名的方法的区别:对于内存来说,这两种方法是一样的。仅从逻辑上不同,一个的身份属于类的静态方法,一个的身份属于模块下面定义的函数。静态方法是专门针对面向对象编程的方法。使用静态方法可以在面向对面编程时不需要创建对象(开辟大的内存空间),以较小的内存空间实现功能。同时出现这两种方法是源于python在整合面向对象编程与模块化编程时产生的历史遗留问题。
面向对象具有一个特性:多态。是面向对象编程仍然存在使用的核心原因之一,可以避免重复的代码。
反射机制+函数式编程 可以完美复制面向对象编程
私有方法和是私有字段:私有字段和私有方法在类外面无法直接访问,可以通过调用类的公有方法间接的实现对私有方法或私有字段的访问。
常适用于对类内部一些非必需暴露的方法、字段等,将其隐藏的场景。不但可以让类看起来更加简洁,同时也更加安全。
当类中不存在私有字段时,此时基本用不到property功能;当类中存在私有字段时,由于需要设置读写功能,此时需要用到property功能。
构造对象与析构函数
#!/usr/bin/env python
#coding:utf-8
class foo:
#构造函数
def __init__(self):
pass
#析构函数
def __del__(self):
print('解释器要销毁对象啦,这是我能说的最后一句话')
__init__方法是构造函数
析构函数:当解释器在销毁对象时,会在销毁对象前执行析构函数;构造函数:通过类中的构造函数’_init_'创建对象
特殊的__call__方法
#!/usr/bin/env python
#coding:utf-8
class foo:
#构造函数
def __init__(self):
pass
#析构函数
def __del__(self):
print('解释器要销毁对象啦,这是我能说的最后一句话')
#定义__call__方法
def __call__(self):
print('__call__方法被执行了')
#实例化对象。通过'类( )'的形式执行类foo里面的__init__构造函数实例化成为对象
fooObj = foo()
#通过'对象( )'的形式执行类foo里面的__call__方法,等同于'fooObj.__call__()'
fooObj()
类的继承与多继承
#!/usr/bin/env python
#coding:utf-8
#定义一个类father作为父类
#当类father继承自object时,该类属于新式类。非继承自object的类属于经典类。
class father(object):
def __init__(self):
self.Fname = "father"
def func(self):
print('father.func')
def notNecessary(self):
print('a not necessary function')
#定义一个类son作为子类
#通过'class 子类(父类)'的形式,实现子类继承父类.
#若需要同时继承多个父类,可以使用','逗号符号隔开。
class son(father):
def __init__(self):
self.Sname = 'son'
#通过'father.__init__(self)'调用父类的构造函数'__init__',此时类son实例化的对象才具有Fname字段
father.__init__(self)
#通过'super(son).__init__()'同样可以实现调用父类构造函数的功能
super(son,self).__init__()
def sonFunc(self):
print('son.sonFunc')
def notNecessary(self):
father.notNecessary(self)
print('son agree it is a not necessary function')
#实例化对象
bigSon = son()
#对于继承了父类的子类,子类拥有父类的方法func
print(bigSon.Sname)
print(bigSon.Fname)
bigSon.func()
#对于继承的父类中与子类中相同部分的方法notNecessary(),子类中的notNecessary()方法会重写(覆盖)父类中的notNecessary()方法
#常适用于子类对父类功能的加工、完善的场景。
bigSon.notNecessary()
新式类与经典类的区别:新式类添加了部分新功能,推荐使用新式类。在python2.2之后,出现了新式类;python2.2之前,都是经典类。新式类兼容经典类的功能,且在此基础上额外添加了新的功能(如使用xx功能限制仅能调用类中的某个方法、_name_、_file_、__doc__等)。经典类存在广度1-深度n(深度优先)查找引起的问题,即经典类在多继承时会出现老类中方法优先新类中方法生效的问题,而新式类已经解决了该问题。此处应有详细文章单独解释经典类与新式类的区别问题。
经典类中的特性全部都是可读可写(没有只读功能),新式类中的特性默认都是只读,如果想要设置,那么就需要再创建一个被装饰@xxx.setter修饰的特性。
抽象类
抽象类 + 抽象方法 = 接口规范
#!/usr/bin/env python
#coding:utf-8
#定义一个抽象类
from pip._vendor.pkg_resources import __metaclass__
from _py_abc import ABCMeta
from abc import abstractmethod
class alert:
__metaclass__ = ABCMeta
#定义抽象方法
@abstractmethod
def send(self):
pass
#继承抽象类后,需要安装接口规范操作,需要定义send方法
class func(alert):
def __init__(self):
print('我已经继承了接口规范alert,我开始调接口了')
def send(self):
print('send')
funcObj = func()
funcObj.send()
异常处理
- AttributeError : 试图访问一个对象没有的属性
- IOError :输入/输出异常;基本上是无法打开文件
- ImportError :无法引入模块或包;基本上是路径问题或名称错误
- IndentationError : 语法错误(的子类);代码没有正确对齐
- IndexError :下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5]
- KeyError :试图访问字典不存在的键
- KeyboardInterrupt : Ctrl+C被按下
- NameError :使用一个还未被赋予对象的变量
- SyntaxError :Python代码非法,代码不能编译(个人认为这是语法错误,写错了)
- TypeError :传入对象类型与要求的不符合
- UnboundLocalError : 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全部变量导致你以为正在访问它
- ValueError :传入一个调用者不期望的值,即使值的类型是正确的
捕捉异常并处理异常示例
#!/usr/bin/env python
#coding:utf-8
#使用try捕捉错误异常
from symbol import except_clause
try:
#此处为
#有异常错误的代码段
#捕捉ImportError类型错误,若能捕捉到相应类型的错误,则把e当做'ImportError'这个对象输出
except ImportError,e:
print(e)
print('捕捉到模块导入错误,正在跳转到自定义的404')
except (AttributeError,ValueError),e:
print(e)
print('捕捉到属性或值类型错误,正在跳转到自定义的404')
#使用'except Exception,e:'捕捉全部类型的错误
except Exception,e:
print('捕捉到某类型错误,正在跳转到自定义的404')
#若try没有捕捉到错误,则执行以下代码
else:
print('你的代码杠杠的')
#捕捉动作完成后,将执行以下代码
finally:
print('错误异常捕捉完成,请及时检查日志')
一旦捕捉到异常错误,则直接跳转到’except’内执行,程序不再往下执行。
自定义异常和手动触发异常
#!/usr/bin/env python
#coding:utf-8
#自定义异常过程
#自定义一个类myExcept,继承自Exception
class myExcept(Exception):
#一旦捕捉到错误,则将错误信息进过msg传入
def __init__(self,msg):
self.error = msg
#一旦在类内部定义重写'__str__'方法,则通过'print(exceptObj)'使用时,则直接返回'__str__'的值
def __str__(self, *args, **kwargs):
print('自定义信息')
return self.error
#实例化对象
exceptObj = myExcept('错误')
#因为类内部定义重写'__str__'方法,此处直接输出'__str__'的值
print(exceptObj)
#手动触发异常
raise myExcept('我正在手动触发异常')