本节内容:html
见概述:http://www.cnblogs.com/linhaifeng/articles/6428835.htmlpython
面向过程的程序设计的核心是过程,过程即解决问题的步骤,面向过程的设计就比如精心设计好一条流水线,考虑周全何时处理什么东西。linux
优势是:极大的下降了程序的复杂度c++
缺点是:一套流水线或者流程就是用来解决一个问题,生产汽水的流水线没法生产汽车,即使是能,也得是大改,改一个组件,牵一发而动全身。git
应用场景:一旦完成基本不多改变的场景,著名的例子有Linux內核,git,以及Apache HTTP Server等。算法
面向对象的程序设计的核心是对象,要理解对象为什么物,必须把本身当成上帝,上帝眼里世间存在的万物皆为对象,不存在的也能够创造出来。面向对象的程序设计比如如来设计西游记,如来要解决的问题是把经书传给东土大唐,如来想了想解决这个问题须要四我的:唐僧,沙和尚,猪八戒,孙悟空,每一个人都有各自的特征和技能(这就是对象的概念,特征和技能分别对应对象的数据属性和方法属性),然而这并很差玩,因而如来又安排了一群妖魔鬼怪,为了防止师徒四人在取经路上被搞死,又安排了一群神仙保驾护航,这些都是对象。而后取经开始,师徒四人与妖魔鬼怪神仙交互着直到最后取得真经。如来根本不会管师徒四人按照什么流程去取。编程
面向对象的程序设计的app
优势是:解决了程序的扩展性。对某一个对象单独修改,会马上反映到整个体系中,如对游戏中一我的物参数的特征和技能修改都很容易。编程语言
缺点:可控性差,没法向面向过程的程序设计流水线式的能够很精准的预测问题的处理流程与结果,面向对象的程序一旦开始就由对象之间的交互解决问题,即使是上帝也没法预测最终结果。因而咱们常常看到一个游戏人某一参数的修改极有可能致使阴霸的技能出现,一刀砍死3我的,这个游戏就失去平衡。ide
应用场景:需求常常变化的软件,通常需求的变化都集中在用户层,互联网应用,企业内部软件,游戏等都是面向对象的程序设计大显身手的好地方
面向对象的程序设计并非所有。对于一个软件质量来讲,面向对象的程序设计只是用来解决扩展性。
python中一切皆为对象,且python3统一了类与类型的概念,类型就是类,因此,无论你信不信,你已经使用了很长时间的类了
>>> dict #类型dict就是类dict <class 'dict'> >>> d=dict(name='lijun') #实例化 >>> d {'name': 'lijun'} >>> d.pop('name') #向d发一条消息,执行d的方法pop,至关于调用dict类的一个属性,其中pop这个函数就是删除字典的指定内容而且回显 'lijun'
基于面向对象设计一个款游戏:英雄联盟,每一个玩家选一个英雄,每一个英雄都有本身的特征和和技能,特征即数据属性,技能即方法属性,特征与技能的结合体就一个对象。
从一组对象中提取类似的部分就是类,类也是特征与技能的结合体,特征即数据而且是全部对象共享的数据,技能即函数属性而且是全部对象共享的函数属性。
garen_hero.Q()称为向garen_hero这个对象发送了一条消息,让他去执行Q这个函数,完成一个功能,相似的有:
garen_hero.W()
garen_hero.E()
garen_hero.R()
一个英雄能够攻击另一个英雄,这就是对象之间的交互
garen_hero.attack(Riven)
#类有两个功能:实例化和属性引用 class Garen: #lol游戏人物盖伦 camp='Demacia' #阵营:德玛西亚 def __init__(self,nickname,aggresivity,life_value): #每一个玩家都有共同的属性:名字,攻击力,生命值 self.nickname = nickname self.aggresivity = aggresivity self.life_value = life_value def attack(self,enemy): #定义一个攻击的属性 print('is attacking....',self,enemy) #类的第一个功能:实例化 g1 = Garen('草丛伦',82,100) #实例化,至关于生成一个游戏玩家 g2 = Garen('hahaha',12,1020) #类的第二个功能:属性引用,包含数据属性和函数属性 print(Garen.camp) print(Garen.__init__) print(Garen.attack) #对于一个实例来讲,只有一种功能:属性引用 print(g1.nickname,g1.aggresivity,g1.life_value) # print(g1.attack,id(g1.attack)) #经过实例来调用类中的函数,根据显示的内容就是绑定方法 print(Garen.attack,id(Garen.attack)) #经过类来调用本身的函数属性 #总结: #对于类来讲就是数据(camp)和函数(attack)的结合体 #对于类的数据属性来讲,共享给因此实例 #对于类的函数来讲,绑定给实例用,绑定了就是为了给实例用的,实例能够传本身的参数 Garen.attack(1,2) g1.attack('lijun') #至关于:Garen.attack(g1,'lijun') 这就是绑定方法的牛逼用处,自动传值 print(g1.camp,id(g1.camp)) print(g2.camp,id(g2.camp)) print(Garen.camp,id(Garen.camp))
# -*- coding: UTF-8 -*- #blog:http://www.cnblogs.com/linux-chenyang/ # #类体现出对象与对象交互的概念 class Garen: #lol游戏人物盖伦 camp='Demacia' #阵营:德玛西亚 def __init__(self,nickname,aggresivity,life_value): #每一个玩家都有共同的属性:名字,攻击力,生命值 self.nickname = nickname self.aggresivity = aggresivity self.life_value = life_value def attack(self,enemy): #定义一个攻击的属性 print('is attacking....',self,enemy) class Riven: camp='Noxus' def __init__(self, nickname, aggresivity, life_value): # 每一个玩家都有共同的属性:名字,攻击力,生命值 self.nickname = nickname self.aggresivity = aggresivity self.life_value = life_value def attack(self, enemy): # 定义一个攻击的属性 print('is attacking....', self, enemy) enemy.life_value -= self.aggresivity #g1的最后生命值就是g1如今的生命值减去r1的攻击力 g1 = Garen('草丛伦',82,100) r1 = Riven('hahah',20,1000) #模拟riven英雄攻击garen英雄 r1.attack(g1) print(g1.life_value) #因此最后g1的生命值就是100-20
# -*- coding: UTF-8 -*- #blog:http://www.cnblogs.com/linux-chenyang/ # #写一个类的过程:举列,女娲造人 #第一步:先想下人(实例)有什么通用的属性,私有的属性,共同的技能,先站住实例的角度去想 #第二步:写的时候在开始写class,而后在生成实例 class Chinese: dang = 'gongchandang' #通用的属性 def __init__(self,name,age,gender): #私有的属性 self.name = name self.age = age self.gender = gender def talk(self): print('chifan shuijiao dadoudou......') #共同的技能 d=Chinese('lijun',18,'F')
查找方法:
在obj.name会先从obj本身的名称空间(__init__)里找name,找不到则去类中找,类也找不到就找父类...最后都找不到就抛出异常
4.1什么是继承
继承是一种建立新的类的方式,在python中,新建的类能够继承自一个或者多个父类,原始类称为基类或超类,新建的类称为派生类或子类。
python中类的继承分为:单继承和多继承
class ParentClass1: #定义父类 pass class ParentClass2: #定义父类 pass class SubClass1(ParentClass1): #单继承,基类是ParentClass1,派生是指subclass1类里本身独有的功能 pass class SubClass2(ParentClass1,ParentClass2): #python支持多继承,用逗号分隔开多个继承的类 pass
查看继承
>>> SubClass1.__bases__ (<class '__main__.ParentClass1'>,) >>> SubClass2.__bases__ (<class '__main__.ParentClass1'>, <class '__main__.ParentClass2'>)
提示:若是没有指定基类,python的类会默认继承object类,object是全部python类的基类,它提供了一些常见方法(如__str__)的实现。
只要继承为object,就被称为新式类
>>> ParentClass1.__bases__ (<class 'object'>,) >>> ParentClass2.__bases__ (<class 'object'>,)
4.2 继承与抽象
抽象即抽取相似或者说比较像的部分。
抽象分红两个层次:
1.将奥巴马和梅西这俩对象比较像的部分抽取成类;
2.将人,猪,狗这三个类比较像的部分抽取成父类。
抽象最主要的做用是划分类别(能够隔离关注点,下降复杂度)
继承:是基于抽象的结果,经过编程语言去实现它,确定是先经历抽象这个过程,才能经过继承的方式去表达出抽象的结构。
抽象只是分析和设计的过程当中,一个动做或者说一种技巧,经过抽象能够获得类
4.3 继承的重要性
在开发程序的过程当中,若是咱们定义了一个类A,而后又想新创建另一个类B,可是类B的大部份内容与类A的相同时
咱们不可能从头开始写一个类B,这就用到了类的继承的概念。
经过继承的方式新建类B,让B继承A,B会‘遗传’A的全部属性(数据属性和函数属性),实现代码重用
# -*- coding: UTF-8 -*- #blog:http://www.cnblogs.com/linux-chenyang/ class Hero: def __init__(self,nickname,aggresivity,life_value): #每一个玩家都有共同的属性:名字,攻击力,生命值 self.nickname = nickname self.aggresivity = aggresivity self.life_value = life_value def attack(self,enemy): #定义一个攻击的属性 print('is attacking....',self,enemy) enemy.life_value -= self.aggresivity class Garen(Hero): camp='Demacia' def fly(self): #盖伦本身的功能,会飞 print('is frying......') def attack(self): print('这个优先') class Riven(Hero): camp='Noxus' g1 = Garen('草丛伦',82,100) g1.fly() g1.attack() #假如重名会先到本身类里面找,找不到在去找父类
4.4 组合与重用性
组合指的是,在一个类中以另一个类的对象做为数据属性,称为类的组合
# -*- coding: UTF-8 -*- #blog:http://www.cnblogs.com/linux-chenyang/ #组合 #几个类之间没有共同之处,在一个类中以另一个类的对象做为数据属性 class Teacher: def __init__(self,name): self.name = name self.birth = Date(1994,8,18) self.course = Course('python','11000','5mons') class Course: def __init__(self,name,price,period): self.name = name self.price = price self.period = period class Date: def __init__(self,year,month,day): self.year = year self.month = month self.day = day t1 = Teacher('alex') print(t1.birth.year) #假如只调用出生的年
4.5 接口与归一化设计
继承有两种用途:
一:继承基类的方法,而且作出本身的改变或者扩展(代码重用)
二:声明某个子类兼容于某基类,定义一个接口类Interface,接口类中定义了一些接口名(就是函数名)且并未实现接口的功能,子类继承接口类,而且实现接口中的功能
# -*- coding: UTF-8 -*- #blog:http://www.cnblogs.com/linux-chenyang/ #运用场景:你去驾校考驾照,学会了就能够开宝马,开奥迪,学会了一种方法,其余的就都会了 #案例:inux一切皆文件 class AllFile: #接口类,接口类只定义要有什么功能,不去真实的实现 def read(self): #接口函数 pass def write(self): pass class Text(AllFile): def read(self): print('文件的读功能!') def write(self): print('文件的写功能!') class Sata(AllFile): def read(self): print('sata的读功能!') def write(self): print('sata的写功能!') t=Text() s=Sata()
为何要用接口:(这是一种设计思路)
接口提取了一群类共同的函数,能够把接口当作一个函数的集合。
而后让子类去实现接口中的函数。
这么作的意义在于归一化,什么叫归一化,就是只要是基于同一个接口实现的类,那么全部的这些类产生的对象在使用时,从用法上来讲都同样。
归一化,让使用者无需关心对象的类是什么,只须要的知道这些对象都具有某些功能就能够了,这极大地下降了使用者的使用难度。
好比:咱们定义一个动物接口,接口里定义了有跑、吃、呼吸等接口函数,这样老鼠的类去实现了该接口,松鼠的类也去实现了该接口,由两者分别产生一只老鼠和一只松鼠送到你面前,即使是你分别不到底哪只是什么鼠你确定知道他俩都会跑,都会吃,都能呼吸。
再好比:咱们有一个汽车接口,里面定义了汽车全部的功能,而后由本田汽车的类,奥迪汽车的类,大众汽车的类,他们都实现了汽车接口,这样就好办了,你们只须要学会了怎么开汽车,那么不管是本田,仍是奥迪,仍是大众咱们都会开了,开的时候根本无需关心我开的是哪一类车,操做手法(函数调用)都同样
4.6 抽象类和接口
# -*- coding: UTF-8 -*- #blog:http://www.cnblogs.com/linux-chenyang/ # # #刚才的那个接口例子,子类不写具体实现的功能也是能够的 # class AllFile: #接口类,接口类只定义要有什么功能,不去真实的实现 # def read(self): #接口函数 # pass # # def write(self): # pass # # class Text(AllFile): # pass # # # # t=Text() #假如我想控制子类必需要实现功能,必须重写read和write的函数,不然就报错 #这种方法就叫作抽象类 #概念:抽象类只是用来继承的,继承的人负责实现父类的功能 import abc class AllFile(metaclass=abc.ABCMeta): #抽象类 @abc.abstractclassmethod def read(self): pass @abc.abstractclassmethod def write(self): pass class Text(AllFile): def read(self): pass def write(self): pass t=Text()
4.7 继承顺序
class A(object): def test(self): print('from A') class B(A): def test(self): print('from B') class C(A): def test(self): print('from C') class D(B): def test(self): print('from D') class E(C): def test(self): print('from E') class F(D,E): # def test(self): # print('from F') pass f1=F() f1.test() print(F.__mro__) #只有新式才有这个属性能够查看线性列表,经典类没有这个属性 #新式类继承顺序:F->D->B->E->C->A #经典类继承顺序:F->D->B->A->E->C #python3中统一都是新式类 #pyhon2中才分新式类与经典类
继承原理:
python究竟是如何实现继承的,对于你定义的每个类,python会计算出一个方法解析顺序(MRO)列表,这个MRO列表就是一个简单的全部基类的线性顺序列表,例如
>>> F.mro() #等同于F.__mro__ [<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
为了实现继承,python会在MRO列表上从左到右开始查找基类,直到找到第一个匹配这个属性的类为止。
而这个MRO列表的构造是经过一个C3线性化算法来实现的。咱们不去深究这个算法的数学原理,它实际上就是合并全部父类的MRO列表并遵循以下三条准则:
1.子类会先于父类被检查
2.多个父类会根据它们在列表中的顺序被检查
4.8 子类调用父类的方法
# -*- coding: UTF-8 -*- #blog:http://www.cnblogs.com/linux-chenyang/ #假如子类想要调用父类中的test功能 # # class A: # def test(self): # print('from a.test') # # class B(A): # def test(self): # A.test(self) # print('from b.test') # # b1=B() # b1.test() #运用场景 class People: def __init__(self,name,age,gender): self.name = name self.age = age self.gender = gender def test(self): print('from a.test') class Teacher(People): def __init__(self,name,age,gender,level): # People.__init__(self,name,age,gender) super().__init__(name,age,gender) self.level = level t = Teacher('lijun',18,'female','高级讲师') print(t.level)
多态性的好处:
1.增长了程序的灵活性
以不变应万变,不论对象变幻无穷,使用者都是同一种形式去调用,如func(animal)
2.增长了程序额可扩展性
经过继承animal类建立了一个新的类,使用者无需更改本身的代码,仍是用func(animal)去调用
# -*- coding: UTF-8 -*- #blog:http://www.cnblogs.com/linux-chenyang/ #多态指的是一类事物有多种形态,(一个抽象类有多个子类,于是多态的概念依赖于继承) class Animal: def talk(self): pass class People(Animal): def talk(self): print('say hello') class Pig(Animal): def talk(self): print('say ao ao ao') class Dog(Animal): def talk(self): print('say wang wang wang') p1=People() pig=Pig() d1=Dog() #如下就是多态性,牛逼之处,假如在来个猫的类,下面的函数无需更改,直接传值 def func(obj): obj.talk() func(p1) func(pig) func(d1)
6.1 封装要装什么
你钱包的有多少钱(数据的封装)
你的性取向(数据的封装)
你撒尿的具体功能是怎么实现的(方法的封装)
6.2 为何要用封装
封装数据的主要缘由是:保护隐私(做为男人的你,脸上就写着:我喜欢男人,你惧怕么?)
封装方法的主要缘由是:隔离复杂度(快门就是傻瓜相机为傻瓜们提供的方法,该方法将内部复杂的照相功能都隐藏起来了,好比你没必要知道你本身的尿是怎么流出来的,你直接掏出本身的接口就能用尿这个功能)
你的身体没有一处不体现着封装的概念:你的身体把膀胱尿道等等这些尿的功能隐藏了起来,而后为你提供一个尿的接口就能够了(接口就是你的。。。,),你总不能把膀胱挂在身体外面,上厕所的时候就跟别人炫耀:hi,man,你瞅个人膀胱,看看我是怎么尿的。还有你的头把你的脑子封装到了脑袋里,而后提供了眼睛这个接口....
提示:在编程语言里,对外提供的接口(接口可理解为了一个入口),就是函数,称为接口函数,这与接口的概念还不同,接口表明一组接口函数的集合体。
# -*- coding: UTF-8 -*- #blog:http://www.cnblogs.com/linux-chenyang/ #封装有两个层面 #第一个层面:假入从另一个脚本执行这个函数,经过导入模块的方式,对于用户来讲这个函数是看不出来是怎么写的,直接调用就行了 # class Foo: # x=1 # def __init__(self,name): # self.name = name #第二个层面:self.__money class Foo: x=1 def __init__(self,name,money): self.name = name self.__money = money #实际就是变造成了_Foo__money def tell_info(self): print(self.__money) #在内部能够调用外部不能调用, def __spam(self): print('testtesttest') f = Foo('alex',2000000000) #print(f.__money) #若直接调用封装了的money的参数会报错 #print(f.__dict__) #用__dict__能够具体查看变了形的结果,其实类就是将里面的数据变成了字典的形式(经过.来从字典里获取数据)。 f.tell_info() #这时就能够调用money的函数了 print(f.__dict__) #对比实例和类的字典 print(Foo.__dict__)
插一嘴,类在定义的时候会执行一遍类里的内容,变形只会在定义的时候发生一次,之后都不会变形了。
class Foo: print('》》》》》》》》》》') def __init__(self,name,money): self.name = name self.__money = money #实际就是变造成了_Foo__money f = Foo('alex',2000000000) print(f.__dict__) f.__x = 1 #新加一个变量 print(f.__dict__) print(f.__x) #而后就能够调用了
6.3 特性protected
# -*- coding: UTF-8 -*- #blog:http://www.cnblogs.com/linux-chenyang/ #property做用就是将类的函数转换成类的属性,实例调用的时候就当作属性来用 #注意:property场景不能穿参数 # # import math # class Circle: # def __init__(self,radius): #圆的半径radius # self.radius=radius # # @property # def area(self): # return math.pi * self.radius**2 #计算面积 # # @property # def perimeter(self): # return 2*math.pi*self.radius #计算周长 # # c=Circle(10) # print(c.radius) # print(c.area) #能够向访问数据属性同样去访问area,会触发一个函数的执行,动态计算出一个值 # print(c.perimeter) #同上 import math class Circle: def __init__(self,radius): self.radius =radius def area(self): return math.pi * self.radius**2 def perimeter(self): return 2*math.pi*self.radius area = property(area) perimeter = property(perimeter) c = Circle(10) #若想要计算员的周长和面积,对于使用者来讲,必须调用两个函数 #print(c.area()) #print(c.perimeter()) #可是用了priperty后,就至关于将函数变成了变量,转换成了数据属性,对于使用者来讲就是数据属性 print(c.area) print(c.perimeter)
为何用protected?
将一个类的函数定义成特性之后,对象再去使用的时候obj.name,根本没法察觉本身的name是执行了一个函数而后计算出来的,这种特性的使用方式遵循了统一访问的原则
python并无在语法上把它们三个内建到本身的class机制中,在C++里通常会将全部的全部的数据都设置为私有的,而后提供set和get方法(接口)去设置和获取,在python中经过property方法能够实现
# -*- coding: UTF-8 -*- #blog:http://www.cnblogs.com/linux-chenyang/ # # class A: # def __init__(self,name): # self.__name = name # # @property #相似c++ get功能 # def name(self): # return self.__name # # @name.setter #相似C++ set功能 # def name(self,value): # self.__name=value # # @name.deleter # def name(self): # print('------') # # a=A('lijun') # print(a.name) # # a.name=2 # print(a.name) # # del a.name #用处:假如我穿个参数,a.name = 111,可是个人姓名必须是字符串,增长了对属性操做的灵活性 class A: def __init__(self,name): self.__name = name @property #相似c++ get功能 def name(self): return self.__name @name.setter #相似C++ set功能 def name(self,value): if not isinstance(value,str): #假如不是字符串我就抛出个异常 raise TypeError('%s must be str' %value) self.__name=value @name.deleter def name(self): #不让删除的提示 print('------') raise AttributeError(' bu neng shan chu ') a=A('lijun') print(a.name) # a.name=111111 # print(a.name) del a.name
一般状况下,在类中定义的全部函数(注意了,这里说的就是全部,跟self啥的不要紧,self也只是一个再普通不过的参数而已)都是对象的绑定方法,对象在调用绑定方法时会自动将本身做为参数传递给方法的第一个参数。除此以外还有两种常见的方法:静态方法和类方法,两者是为类量身定制的,可是实例非要使用,也不会报错,后续将介绍。
7.1 静态方法
是一种普通函数,位于类定义的命名空间中,不会对任何实例类型进行操做,python为咱们内置了函数staticmethod来把类中的函数定义成静态方法
class Foo: def spam(x,y,z): #类中的一个函数,千万不要懵逼,self和x啥的没有不一样都是参数名 print(x,y,z) spam=staticmethod(spam) #把spam函数作成静态方法
基于以前所学装饰器的知识,@staticmethod 等同于spam=staticmethod(spam),因而
class Foo: @staticmethod #装饰器 def spam(x,y,z): print(x,y,z)
使用演示
print(type(Foo.spam)) #类型本质就是函数 Foo.spam(1,2,3) #调用函数应该有几个参数就传几个参数 f1=Foo() f1.spam(3,3,3) #实例也可使用,但一般静态方法都是给类用的,实例在使用时丧失了自动传值的机制 ''' <class 'function'> 1 2 3 3 3 3 '''
应用场景:
import time class Date: def __init__(self,year,month,day): self.year=year self.month=month self.day=day @staticmethod def now(): #用Date.now()的形式去产生实例,该实例用的是当前时间 t=time.localtime() #获取结构化的时间格式 return Date(t.tm_year,t.tm_mon,t.tm_mday) #新建实例而且返回 @staticmethod def tomorrow():#用Date.tomorrow()的形式去产生实例,该实例用的是明天的时间 t=time.localtime(time.time()+86400) return Date(t.tm_year,t.tm_mon,t.tm_mday) a=Date('1987',11,27) #本身定义时间 b=Date.now() #采用当前时间 c=Date.tomorrow() #采用明天的时间 print(a.year,a.month,a.day) print(b.year,b.month,b.day) print(c.year,c.month,c.day)
7.2 类方法
类方法是给类用的,类在使用时会将类自己当作参数传给类方法的第一个参数,python为咱们内置了函数classmethod来把类中的函数定义成类方法
#类方法 # class A: # x=1 # @classmethod # def test(cls): # print(cls,cls.x) #cls就是类A # # A.test() #补充 # class A: # def __init__(self,name): # self.name = name # # def __str__(self): # return '%s' %self.name # # a=A('lijun') # print(a) #若是不定义__str__内置函数,那么打印的是a的内存地址 #类方法的应用场景,相比静态方法,比较灵活 import time class Date: def __init__(self,year,month,day): self.year=year self.month=month self.day=day @classmethod def now(cls): t=time.localtime() return cls(t.tm_year,t.tm_mon,t.tm_mday) d1=Date.now() print(d1.year,d1.month,d1.day)
两种类的区别和用处:
import time class Date: def __init__(self,year,month,day): self.year=year self.month=month self.day=day @staticmethod def now(): t=time.localtime() return Date(t.tm_year,t.tm_mon,t.tm_mday) class EuroDate(Date): def __str__(self): return 'year:%s month:%s day:%s' %(self.year,self.month,self.day) e=EuroDate.now() print(e) #咱们的意图是想触发EuroDate.__str__,可是结果为 ''' 输出结果: <__main__.Date object at 0x1013f9d68> '''
由于e就是用Date类产生的,因此根本不会触发EuroDate.__str__,解决方法就是用classmethod
import time class Date: def __init__(self,year,month,day): self.year=year self.month=month self.day=day # @staticmethod # def now(): # t=time.localtime() # return Date(t.tm_year,t.tm_mon,t.tm_mday) @classmethod #改为类方法 def now(cls): t=time.localtime() return cls(t.tm_year,t.tm_mon,t.tm_mday) #哪一个类来调用,即用哪一个类cls来实例化 class EuroDate(Date): def __str__(self): return 'year:%s month:%s day:%s' %(self.year,self.month,self.day) e=EuroDate.now() print(e) #咱们的意图是想触发EuroDate.__str__,此时e就是由EuroDate产生的,因此会如咱们所愿 ''' 输出结果: year:2017 month:3 day:3 '''
强调,注意注意注意:静态方法和类方法虽然是给类准备的,可是若是实例去用,也是能够用的,只不过实例去调用的时候容易让人混淆,不知道你要干啥
x=e.now() #经过实例e去调用类方法也同样可使用,静态方法也同样 print(x) ''' 输出结果: year:2017 month:3 day:3 '''
http://www.cnblogs.com/linhaifeng/articles/6182264.html#_label27
hasattr(容器,‘名称’) #以字符串的形式判断某个对象中是否含有指定的属性
getattr(容器,‘名称’) #以字符串的形式去某个对象中获取指定的属性
setattr(容器,‘名称’,值) #以字符串的形式去某个对象中设置指定的属性
delattr(容器,‘名称’) #以字符串的形式去某个对象中删除指定的属性
案例1:当前目录下有个test目录,test目录下有个account的模块,输入不一样的路径,执行不一样的结果,可是个人这些功能都在统一的目录下
# -*- coding: UTF-8 -*- #blog:http://www.cnblogs.com/linux-chenyang/ #案例:假若有一个网站,输入不一样的路径,执行不一样的结果,可是个人这些功能都在统一的目录下 #用户输入:account/login acccount/logout li = ['account/login','acccount/logout'] inp = input('》》》') m,n = inp.split('/') import sys,os sys.path.append(r'D:\pycharm\s16\day7\反射\test') import account if inp in li: if n == "login": res = account.login() elif n == 'logout': res = account.logout() else: print('没有这个功能。。。') print(res)
# -*- coding: UTF-8 -*- #blog:http://www.cnblogs.com/linux-chenyang/ def login(): return '请输入用户名和密码' def logout(): return '跳转页面'
案例2:以上的方法用反射来实现,getattr()
#反射:getattr() 专门去某个地方获取他的内部的东西,PS:获取的东西是字符串的形式 #用反射去实现以上的内容 import sys,os sys.path.append(r'D:\pycharm\s16\day7\反射\test') import account # v=getattr(account,'login') # print(v) action = input('>>') v = getattr(account,action) result = v() print(result)
# -*- coding: UTF-8 -*- #blog:http://www.cnblogs.com/linux-chenyang/ def login(): return '请输入用户名和密码' def logout(): return '跳转页面'
C:\Python35\python3.exe D:/pycharm/s16/day7/反射/反射.py >>login 请输入用户名和密码
案例3:hasattr()函数的用法,先判断我这个模块里有没有函数,有的话就执行,没有就报404
#反射:hasattr() 专门去某个地方获取他的内部的东西,PS:获取的东西是字符串的形式 import sys,os sys.path.append(r'D:\pycharm\s16\day7\反射\test') import account action = input('>>') # a = hasattr(account,action) # print(a) #假如account文件里有action那么就输出True不然false if(hasattr(account,action)): func = getattr(account,action) result = func() else: result = '404' print(result)
# -*- coding: UTF-8 -*- #blog:http://www.cnblogs.com/linux-chenyang/ def login(): return '请输入用户名和密码' def logout(): return '跳转页面'
C:\Python35\python3.exe D:/pycharm/s16/day7/反射/反射.py >>aaa 404 C:\Python35\python3.exe D:/pycharm/s16/day7/反射/反射.py >>logout 跳转页面
案例4:
#setattr和delattr的用法 import sys,os sys.path.append(r'D:\pycharm\s16\day7\反射\test') import account h = hasattr(account,'findpwd') print(h) setattr(account,'findpwd',lambda x:x+1) #增长findpwd函数 h = hasattr(account,'findpwd') #这时值就为True print(h) delattr(account,'findpwd') #删除 h = hasattr(account,'findpwd') print(h)
# -*- coding: UTF-8 -*- #blog:http://www.cnblogs.com/linux-chenyang/ def login(): return '请输入用户名和密码' def logout(): return '跳转页面'
C:\Python35\python3.exe D:/pycharm/s16/day7/反射/反射.py
False
True
False
案例5:深刻运用,假如同一个目录下有好的功能存在不一样的模块中(环境是在包中演示)
# -*- coding: UTF-8 -*- #blog:http://www.cnblogs.com/linux-chenyang/ #以字符串的形式导入模块 #import time #v = __import__('time') while True: # account/login # home/index inp=input('请输入url:') m,n = inp.split('/') module = __import__('controller.%s' %m,fromlist=True) # print(module) if hasattr(module,n): func = getattr(module,n) result = func() else: print('404') print(result)
# -*- coding: UTF-8 -*- #blog:http://www.cnblogs.com/linux-chenyang/ def login(): print('longin......') return 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' def logout(): print('longout......') return 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
# -*- coding: UTF-8 -*- #blog:http://www.cnblogs.com/linux-chenyang/ def index(): print('aaaaaa') return '这个是index函数' print('honme..........')
C:\Python35\python3.exe D:/pycharm/s16/day7/反射_package/反射.py 请输入url:home/index honme.......... aaaaaa 这个是index函数 请输入url:account/login longin...... aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 请输入url:account/laaaaaaaaaaaaaaaaaaaaaaaaa 404 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 请输入url:
案例6:继续优化脚本,假如输入没有的模块,也报错,可是程序不退出
# -*- coding: UTF-8 -*- #blog:http://www.cnblogs.com/linux-chenyang/ #以字符串的形式导入模块 #import time #v = __import__('time') while True: # account/login # home/index inp=input('请输入url:') m,n = inp.split('/') try: #假如导入没有的模块,就报401 module = __import__('controller.%s' %m,fromlist=True) # print(module) if hasattr(module,n): func = getattr(module,n) result = func() else: print('404') except Exception as e: result = 401 print(result)
C:\Python35\python3.exe D:/pycharm/s16/day7/反射_package/反射.py 请输入url:sss/sssss 401 请输入url:
1.__doc__ 表示类的描述信息
class Foo: """ 描述类信息,这是用于看片的神奇 """ def func(self): pass print(Foo.__doc__) # 输出: 描述类信息,这是用于看片的神奇
2.__module__ 和 __class__
__module__ 表示当前操做的对象在那个模块
__class__ 表示当前操做的对象的类是什么
class C: def __init__(self): self.name = 'wupeiqi'
from lib.aaa import C obj = C() print(obj.__module__) # 输出 lib.aaa,即:输出模块,字符串的形式 print(obj.__class__ ) # 输出 lib.aa.C,即:输出类
3. __call__ 对象后面加括号,触发执行。
注:构造方法的执行是由建立对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()
class Foo: def __init__(self): pass def __call__(self, *args, **kwargs): print '__call__' obj = Foo() # 执行 __init__ obj() # 执行 __call__
4. __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 类建立
上述代码中,obj 是经过 Foo 类实例化的对象,其实,不只 obj 是一个对象,Foo类自己也是一个对象,由于在Python中一切事物都是对象。
若是按照一切事物都是对象的理论:obj对象是经过执行Foo类的构造方法建立,那么Foo类对象应该也是经过执行某个类的 构造方法 建立。
因此,f对象是Foo类的一个实例,Foo类对象是 type 类的一个实例,即:Foo类对象 是经过type类的构造方法建立。
那么,建立类就能够有两种方式:
a)普通方式:
class Foo(object): def sayhi(self,name): print('hello ', name)
b)特殊方式:
def sayhi(self,name): print('hello ',name) f= type('Foo', (object,), {'func': sayhi}) # type第一个参数:类名 # type第二个参数:当前类的基类 # type第三个参数:类的成员 # # 上面f=的格式就和普通格式同样 print(f) print(type(f)) print(dir(f)) #查看类名下有哪些函数 #f.func('ddd') #若想要使用sayhi的函数 f_obj=f() #实例化 f_obj.func('lijun') #调用函数
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()
# -*- coding: UTF-8 -*- #blog:http://www.cnblogs.com/linux-chenyang/ # class Foo(object): # def __init__(self, name): # self.name = name # print('Foo __init__') # # def __new__(cls, *args, **kwargs): #init的触发都是由new来实现的,原来默认里有个new,你在写new方法会顶替 # print('Foo __new__') # # f = Foo("alex") #这时实例化后显示的不是'Foo __initclass Foo(object): #利用new方法实现调用init #new只是生成了一块内存空间,并无赋值,交给init赋值 class Foo(object): def __init__(self, name): self.name = name print('Foo __init__') def __new__(cls, *args, **kwargs): #整个类的实例化其实都是经过new来实现的 print('Foo __new__') obj = object.__new__(cls) print('obj:::',obj) return obj f = Foo("alex") print(f.name)
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)
动态导入模块
import importlib __import__('import_lib.metaclass') #这是解释器本身内部用的 #importlib.import_module('import_lib.metaclass') #与上面这句效果同样,官方建议用这个
http://www.cnblogs.com/wupeiqi/articles/5017742.html
1.异常基础
案例1:最简单的语法,假如一个程序出错了,不是立马就报错退出程序,下面的程序还会执行
#打印一个不存在的变量 try: print(name) except NameError as e: print(e) print('keep going.....') #输出 name 'name' is not defined #抓到的错误信息 keep going.....
2.异常种类
python中的异常种类很是多,每一个异常专门用于处理某一项异常!!!
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
names = ['a','b'] try: print(name) #走到这里就报错了,下面的就不执行了,直接跳到except print(names[3]) except NameError as e: print(e) print('keep going.....')
#能够抓到其中一个错误,可是不能同时抓住 names = ['a','b'] try: print(names[3]) print(name) except NameError as e: print(e) except IndexError as e: print(e) print('keep going.....')
#能够抓到其中一个错误,可是不能同时抓住 names = ['a','b'] try: print(names[3]) print(name) except (NameError,IndexError) as e: print(e) except IndexError as e: print(e) print('keep going.....')
备注:IndentationError和SyntaxError的错误信息是抓不到的,由于解释器根本就执行不了这两类的代码。
#Exception万能异常,通常不用,不方便调试 names = ['a','b'] try: print(names[3]) print(name) except Exception as e: print(e) print('keep going.....')
#else的用法 names = ['a','b'] try: print(names[1]) # print(name) except IndexError as e: print(e) except Exception as e: print(e) else: print('什么错都没有,就会执行')
#finally的用法 names = ['a','b'] try: print(names[1]) print(name) except IndexError as e: print(e) except Exception as e: print(e) else: print('什么错都没有,就会执行') finally: print('不管有没有错都执行')
3.自定义异常
class WupeiqiException(Exception): def __init__(self, msg): self.message = msg def __str__(self): return self.message try: raise WupeiqiException('个人异常') except WupeiqiException,e: print e
4.断言
# assert 条件 assert 1 == 1 assert 1 == 2