今天先讲了random模块的使用
这个模块的作用其实就是随机生数字,它下面有是三个方法
import random print random.random() #默认方法是在0和1之间取一个随机带小数点的随机数 print random.randint(1,2) #在1和2之间随机取数字,可能是1也可能是2 print random.randrange(1,2) #在大于等于1切小于2的范围内取随机数,本例来说只能取到1这个值 0.240756960152 2 1
既然通过random模块可以取随机数,那么根据ascii码表的规则。从65以上到127的范围内就包含了从A-y的26个字母的大小写格式。通过chr()函数就可以将输入的数字转换成对应的ascii字符。
import random num=random.randint(65,90) print 'number is %d ASCII is %s' %(num,chr(num)) number is 85 ASCII is U
下个列子就死利用上述原理产生一个4位的包含大写字母和0-9随机数字的验证码
import random #创建一个空字符串 checkcode='' #循环4次 for i in range(4): #获取一个0-3之间的随机数 current=random.randrange(0,4) #如果循环的次数与产生的随机数不相等 if current != i: #就生成一个大写的英文字母 temp=chr(random.randint(65,90)) #如果循环次数与产生的随机数相等 else: #就产生一个0-9的随机数 temp=random,range(0,9) #不管产生的是字母还是数字都追加到checkcode字符串中 checkcode+=str(temp) #打印字符串 print checkcode EU31
面向对象
面向对象编程有三大特性 封装、继承、多态
封装的特性
封装其实就是将多个函数都需要用到的参数打包到类里面,赋值一次就可以给其他方法一直调用了。
例如下面两个函数,都需要要调用name来完成输出,需要重复给name赋值
def sayhi(name): print '%s say hi'%name def drink(name): print '%s drink water'%name sayhi('wgw') drink('wgw') wgw say hi wgw drink water
如果我们使用类的封装特性,来实现就是如下的代码效果。只需要把name封装到类里面就好了。以后再调用类里面的方法就是实现打印输出,不需要反复赋值name了
class test_class(): def __init__(self,name): self.name=name def sayhi(self): print '%s say hi'%self.name def drink(self): print '%s drink water'%self.name obj=test_class('wgw') obj.sayhi() obj.drink() wgw say hi wgw drink water
上面只是简单的例子,如果我们有几十个函数,每个函数可能有像name一样的3-5个都要用到的参数。那样的话通过面向对象的方法,就会显得优势更加明显。代码更加简练了。
要调用被封装的name可以通过对象调用
class test_class(): def __init__(self,name): self.name=name def sayhi(self): print '%s say hi'%self.name def drink(self): print '%s drink water'%self.name obj=test_class('wgw') #类在实例化的时候会把obj赋值给self print obj.name #这个obj.name 其实就是self.name wgw
python的封装条件
a.多个方法共用一组变量,变相封装到对象中
b.通过模板创建多个对象 例如游戏
继承的特性
继承顾名思义,比如我们创建了上面的test_class()这个类。后来又创建了一个test_class2()类,新建的类里主要是是包含一些人物喜欢参加的运动。但是我们希望在这个类里输入name之后也可以通过sayhi()方法和大家打个招呼。这时候我们可以在新建的test_class()类里面再重写一遍sayhi()方法。当然这样是很low的作法。那么最高效的就是让test_class2继承wgwclass这类里面的方法。然后在wgwclass2里面就直接用父类的方法了。
class test_class(): def __init__(self,name): self.name=name def sayhi(self): print '%s say hi'%self.name def drink(self): print '%s drink water'%self.name class test_class2(test_class): #继承父类的方法 def __init__(self,name,age): test_class.__init__(self,name) #调用父类的__init__方法 self.name=name self.age=age def basketball(self): print '%s %d years old like basketball'%(self.name,self.age) obj=test_class2('lucy',18) obj.sayhi() obj.drink() obj.basketball() lucy say hi lucy drink water lucy 18 years old like basketball
通过结果看到新人物lucy不仅可以使用子类里的篮球方法,也可以继承使用父类里的sayhi()方法。
多继承
经典类 和 新式类
经典类和新式类在创建方式上所有不同
class old_class(): #旧式经典类 pass class new_class(object): #新式类,主要是就是创建的时候要加个object pass
经典类的子类也是经典类 新式类的子类也是新式类
经典类和新式类在使用上没有多大的区别,主要区别就是在多继承时候,查找父类方法的侧重点不一样。例如经典类
class A: #父类是一个经典类 def f(self): print 'This A' class B(A): pass #class B 里面没有f()方法 class C(A): def f(self): print 'This C' class D(B,C): #class D 同时继承了B,C两个类 pass obj=D() obj.f() #经典类是深度优先,class B里面没有就去B的父类A里面找 This A
新式类
class A(object): #父类是一个新式类 def f(self): print 'This A' class B(A): pass #class B 里面没有f()方法 class C(A): def f(self): print 'This C' class D(B,C): #class D 同时继承了B,C两个类 pass obj=D() obj.f() #新式类是广度优先,class B里面没有就去同级别的class C()里面找 This C
但是要注意,所谓的深度优先和广度优先都是建立在class B 和 class C 都继承了class A的前提下的。如果class B没有继承 class A 那么当class B里没有f()方法时候,不管什么类都会去class C里面找。
多态的特性
老师说python1的多态功能相当差,跟没有差不多。所以基本没有实用价值。
以上就是面向对象的三大特性,老师说为了提升逼格有两点要注意:
第一、尽量使用新式类 这是以后的趋势
第二、别老说父类子类,听着就土。要改说基类、派生类。
类和对象在内存中如何保存
老师的说法是:类以及类中的方法在内存中只有一份,而根据类创建的每一个对象都在内存中需要存一份
听着是不是特别绕口?简单来说就就是,假设我们有一个叫person的类模版。那么这个模版就要占一份内存。下一步我们用person()创造了两个人物 wgw 和lucy 。那么每创建一个新人物就又单独占用一份内存空间。
类的成员
类的成员由三大部分组成:字段、方法、属性
字段
普通字段
我们创建类的时候,会使用__init__方法构造类。并且将参数赋值与self.xxx 其实这个self.xxx就类的字段,是类的普通字段
class wgw(): def __init__(self,name): self.name=name #定义一个普通字段 obj=wgw('test') #实例化 print obj.name #通过对象+字段名 就可以访问普通字段 test
静态字段
应用场景: 通过类创建对象时,如果每个对象都具有相同的字段,那么就使用静态字段
静态字段是又一层的重用
class wgw(): country='china' #定义静态字段 def __init__(self,name): self.name=name print wgw.country #静态字段通过类名+地段名的当时调用 china
普通字段属于:对象
静态字段属于:类
方法 普通方法 类方法 静态方法
普通方法
在创建的时候必须要有一个self参数,被调用的时候把对象名称赋值给self
class wgw(object): def __init__(self): pass def saihi(self): #普通方法,由对象触发,可以加参数至少有一个self print 'hi everybody'
类方法
class wgw(object): def __init__(self): pass def saihi(self): #普通方法必须有个self print 'hi everybody' @classmethod #通过添加classmethod装饰器定义类方法 def saybye(cls): #类方法,类方法触发的时候是把类自身赋值给cls传入方法,只能有一个cls 不能加其他参数 print 'bye bye' wgw.saybye() #通过类名+方法名调用类方法
类方法相当于对方法进行了一个约束,一个方法只能有一个参数。调用的时候不需要在init里面定义字段和创建对象。节约内存开销
静态方法
class wgw(object): def __init__(self): pass def saihi(self): #普通方法,由对象触发,可以加参数至少有一个self print 'hi everybody' @classmethod #通过添加classmethod装饰器定义类方法 def saybye(cls): #类方法,类方法触发的时候是把类自身赋值给cls传入方法,只能有一个cls 不能加其他参数 print 'bye bye' @staticmethod #通过添加staticmethod装饰器定义类方法 def sayhello(name,age): #静态方法,由类触发。不需要加self 可以传入任意参数 print 'hello' wgw.sayhello('wgw',18) #通过类名+方法名调用静态方法
类里面使用静态方法,就相当于在类里创建个函数。因为不用在init里面定义字段,也不用创建对象了。节约内存开销
属性
属性的功能是把一个方法伪造成一个字段,对运行结果没有影响 和方法是一样的
属性也是方法的一种,只是被改造成一种字段形式被访问。
class wgw(object): def __init__(self,name): self.name=name pass @property #通过添加property装饰器定义将方法定义成属性 def goodboy(self): #属性只能有一个self参数 return 'haha' obj=wgw('lala') print obj.name #调用函数的字段 print obj.goodboy #调用设置为属性的goodboy()方法
从上面的调用方法上看,属性的确把一个方法伪装成了字段。并且调用方式都和字段一样。
类成员修饰符
类的成员上文都介绍过,包含字段、方法、属性
这些成员也有公有成员和私有成员
普通字段
class wgw(object): def __init__(self,name,age): self.name=name #公有字段 self.age=age def sayhi(self): print '%s is %d years old'%(self.name,self.age) obj=wgw('lala',18) print obj.name #在类外面直接可以调用 obj.sayhi() lala lala is 18 years old
如果有人从外部对字段重新赋值,就会影响方法的运行结果
class wgw(object): def __init__(self,name,age): self.name=name #公有字段 self.age=age def sayhi(self): print '%s is %d years old'%(self.name,self.age) obj=wgw('lala',18) obj.age=30 #在外部可以直接修改字段的值 obj.sayhi() lala is 30 years old #运行的结果被修改了
如果要杜绝这种情况的发生,可以将该字段设置为私有
class wgw(object): def __init__(self,name,age): self.__name=name #在字段名前面加两个下划线表示将该字段设置为私有 self.age=age
设置为私有之后,该字段在就只能在类内部被调用,外部就访问不了了。而且这个类的派生类也不能再访问这个字段了。
方法和属性也都可以设置为私有的,同样是设置为私有之后就不能够被外部和派生类访问了。
最后附上一张python面向对象的全景图
本文出自 “霹雳豆包” 博客,谢绝转载!