python是函数式的编程语言,也是面向对象的编程语言,在python中,解释器的执行顺序是从上到下,定义类的关键字是
class,其中类名字的首字是大写,在python中,面向对象执行的步骤为:
1、定义类
class class_name:
def 方法名(self):
pass
2、依据类创建创建对象或者说创建对类进行实例化,使用对象去执行类中的方法
3、在类的方法中,self是形式参数,在python的内部进行传递。
如下我们定义一个类,来看类的定义以及它的使用
class F: def __init__(self,name): self.name=name def getName(self): return self.name def setName(self,name): self.name=name def info(self): print 'my name is {0}'.format(self.name) def __del__(self): print u'执行结束...'
在如上的类中,__init__是构造方法,__del__是析构方法,在一个python的类当中,类都是具有构造方法的,它的执行顺序是对类
进行实例化的对象后,调用类中的方法,是先执行构造方法,再执行类中的方法,再执行析构方法,比如我们调用info()方法,来看
类执行的顺序,见实现的代码和执行顺序的结果:
#!/usr/bin/env python #-*- coding:utf-8 -*- class F: def __init__(self,name): self.name=name print u'类开始执行...' def getName(self): return self.name def setName(self,name): self.name=name def info(self): print 'my name is {0}'.format(self.name) def __del__(self): print u'执行结束...' f=F(u'无涯') print f.info()
见该代码执行后的输出内容:
C:\Python27\python.exe D:/git/Python/Day/day1/index.py 类开始执行... my name is 无涯 None 执行结束...
依据如上我们可以看到,执行的顺序是先执行__init__,下来执行info方法,最后执行__del__方法。
构造方法在某些时候,可以理解为是对对象的另外一种封装的方式,一个类进行实例化的时候,如果它的构造方法的参数是什么,
对类进行实例化的时候,得填写相应的参数,比如我们定义如下的类,它的构造方法的参数是名字,年龄,地址,地址默认是西安,
我们然后输出这些信息,见该类的代码和它的输出:
#!/usr/bin/env python #-*- coding:utf-8 -*- class F: def __init__(self,name,age,address='西安'): self.name=name self.age=age self.address=address def show(self): return 'my name is :{0} , and my age is:{1},and my address is:{2}'.format(self.name,self.age,self.address) f=F('无涯',20) print f.show()
见执行如上的代码后输出的内容:
C:\Python27\python.exe D:/git/Python/Day/day1/index.py my name is :无涯 , and my age is:20,and my address is:西安 Process finished with exit code 0
在python的类中,一个类可以继承单个类,也可以继承多个类,下面我们首先来看python类的继承实现的方式,
定义一个动物类,每个动物都有名字,每个动物只是有不同的属性,比如狗是汪汪,小猫是喵~,那么对于狗和猫
来说,它都需要名字,就不需要单独的写方法了,直接继承动物的类,下面我们来实现这样的一个过程,见代码:
#!/usr/bin/env python #-*- coding:utf-8 -*- class Animal(object): def __init__(self,name): self.name=name def eat(self): print '{0}开始吃饭...'.format(self.name) def drink(self): print '{0}开始喝水...'.format(self.name) class Dog(Animal): def __init__(self,name): Animal.__init__(self,name) def wang(self): print '{0}汪汪的叫'.format(self.name) class Cat(Animal): def __init__(self,name): Animal.__init__(self,name) def jiao(self): print '{0}喵喵的叫'.format(self.name) dog=Dog('狗') dog.eat() dog.drink() dog.wang() cat=Cat('猫') cat.eat() cat.drink() cat.jiao()
如上的类中,不管是狗还是猫,它都得吃饭和喝水,我们写在Animal类中,直接继承它调用就可以了,在面向对象中,
Animal叫父类,也叫基类,Dog和Cat叫子类,也叫派生类。派生类可以继承基类中所有的功能,派生类和基类同时存
在,优先找派生类,我们通过一个案例来实现这样的一个过程,见代码:
#!/usr/bin/env python #-*- coding:utf-8 -*- class Animal(object): def __init__(self,name): self.name=name def eat(self): print '{0}开始吃饭...'.format(self.name) def drink(self): print '{0}开始喝水...'.format(self.name) class Dog(Animal): def __init__(self,name): Animal.__init__(self,name) def wang(self): print '{0}汪汪的叫'.format(self.name) def drink(self): print '小狗开始喝水了,哈哈哈哈' dog=Dog('狗') dog.eat() dog.drink()
在如上的代码中,父类和子类都存在drink的方法,也就是说子类对父类的drink()方法进行了覆写,那么调用的时候,
调用的是父类的方法了还是子类的方法了,答案肯定是子类的方法,见执行的输出内容:
C:\Python27\python.exe D:/git/Python/Day/day1/index.py
狗开始吃饭...
小狗开始喝水了,哈哈哈哈
Process finished with exit code 0
如上我们说到,在python中,一个类可以继承N个类,那么它执行顺序是怎么样的,其实它执行的顺序是:优先从自己找,如果
自己没有,从继承的类从左到右进行寻找,我们来看这样的一个过程,见实现的代码:
#!/usr/bin/env python #-*- coding:utf-8 -*- class Animal1(object): def drink(self): print '第一个类的方法开始执行' class Animal2(object): def drink(self): print '第二类的方法开始执行' class Dog(Animal1,Animal2): def drink(self): print '小狗开始喝水了,哈哈哈哈' dog=Dog() dog.drink()
如上的代码执行后,执行的是子类Dog中的drink()方法,下面再来看继承的类从左到右的执行顺序案例代码:
#!/usr/bin/env python #-*- coding:utf-8 -*- class Animal1(object): def drink(self): print '第一个类的方法开始执行' class Animal2(object): def drink(self): print '第二类的方法开始执行' class Dog(Animal1,Animal2): pass dog=Dog() dog.drink()
如上的代码执行后,执行的是Animal1类中的drink()方法,见输出的结果内容:
C:\Python27\python.exe D:/git/Python/Day/day1/index.py
第一个类的方法开始执行
Process finished with exit code 0
下面利用结合反射和类,来查找类中的方法是否存在,具体见如下实现的代码:
#!/usr/bin/env python #-*- coding:utf-8 -*- class Obj(object): def __init__(self,name): self.name=name def show(self): pass obj=Obj('wuya') print u'通过反射获取成员名称:',getattr(obj,'name') print u'通过反射查看类中的方法是否存在:',hasattr(obj,'show') print u'通过反射查看类中的成员名称是否存在:',hasattr(obj,'name')
见如上的代码执行后的结果:
C:\Python27\python.exe D:/git/Python/Day/day1/index.py
通过反射获取成员名称: wuya
通过反射查看类中的方法是否存在: True
通过反射查看类中的成员名称是否存在: True
Process finished with exit code 0
下面通过反射结合模块来查找类中的方法是否存在,以及获取类成的成员名称,也就是说我们在OOP.py的模块
编写了一个类,类中有方法,我们在index.py模块中,结合反射的方式来判断该模块中的类方法是否存在,获取
类中的成员变量结果,OOP.py的代码为:
#!/usr/bin/env python #-*- coding:utf-8 -*- class Obj(object): def __init__(self,name): self.name=name def show(self): pass
index.py模块的代码为(该代码实现获取OOP.py模块中的类,然后判断方法和获取类成员方法),见代码:
#!/usr/bin/env python #-*- coding:utf-8 -*- def exists(moduleName,className): m=__import__(moduleName,fromlist=True) #判断模块中的类是否存在 if hasattr(m,className): #获取模块中的类 class_name=getattr(m,className) #实例化类 obj=class_name('wuya') print u'通过反射获取类中的成员方法:',getattr(obj,'name') print u'通过反射判断类中的show()方法是否存在:',hasattr(obj,'show') else: print u'Sorry,类不存在' exists('OOP','Obj')
在python的面向对象编程中,存在静态成员这么一个说法,静态字段,简单的理解就是在一个对象中,把每一个重复的东西
类中只存在一份,我们来看一个简单的案例,打印每个省份,每个省份它有一个共同的对象,就是china,那么我们可以把china定
义为类的静态字段,见实现的案例代码:
#!/usr/bin/env python #-*- coding:utf-8 -*- class Province(object): country='china' def __init__(self,name): self.name=name def show(self): print u'国籍:{0},属于哪个省:{1}'.format(self.country,self.name) per=Province(u'*') per.show()
#!/usr/bin/env python #-*- coding:utf-8 -*- class Province(object): country='china' def __init__(self,name): self.name=name def show(self): print u'国籍:{0},属于哪个省:{1}'.format(self.country,self.name) per=Province(u'*') per.show()
见代码执行后的结果:
C:\Python27\python.exe D:/git/Python/FullStack/Study/oopTest.py
国籍:china,属于哪个省:*
Process finished with exit code 0
静态字段,其实使用类也可以直接的调用,比如上面的,我们可以使用Province.country这样来调用,它的输出结果是*,静态字段属于类,
那么既然存在静态字段,是否存在动态字段了,我们叫普通字段,普通字段属于对象,我们接着上面的例子定义一个普通字段,来演示下静态
字段字段以及普通字段的调用,见案例代码:
#!/usr/bin/env python #-*- coding:utf-8 -*- class Province(object): #静态字段,属于类 country='china' def __init__(self,name): #普通字段,属于对象 self.name=name p=Province(u'*') #调用静态字段 print u'类的静态字段是:',Province.country print u'对象的普通字段是:',p.name
见执行如上的代码后的结果:
C:\Python27\python.exe D:/git/Python/FullStack/Study/oopTest.py
类的静态字段是: china
对象的普通字段是: *
Process finished with exit code 0
在类中,方法有普通方法,静态方法,以及类方法,下面我们分别来看这些方法是怎么编写以及如何调用的,这些方法和类,以及对象
之间的关系是什么?见案例代码:
#!/usr/bin/env python #-*- coding:utf-8 -*- class Province(object): #静态字段,属于类 country='china' def __init__(self,name): #普通字段,属于对象 self.name=name def show(self): print u'我就是个普通方法' @staticmethod def f1(): print u'我是静态方法,我存在的意义就是类不需要创建对象就可以直接调用' @classmethod def f2(cls): print u'我是类方法'
在上面的例子中定义了普通方法,静态方法,以及类方法,那么对它进行分类,普通方法它是属于对象,类方法以及静态方法
它是属于类,由类直接调用,而普通方法需要对象去调用,这样我们可以总结为:类调用静态字段,静态方法,以及类方法,
对象调用普通字段,普通方法,我们对如上的代码进行构造进行调用下,看执行的结果:
#!/usr/bin/env python #-*- coding:utf-8 -*- class Province(object): #静态字段,属于类 country='china' def __init__(self,name): #普通字段,属于对象 self.name=name def show(self): print u'我就是个普通方法' @staticmethod def f1(): print u'我是静态方法,我存在的意义就是类不需要创建对象就可以直接调用' @classmethod def f2(cls): print u'我是类方法' p=Province(u'无涯') print u'对象调用普通字段:',p.name print u'对象调用普通方法:',p.show() print u'类调用静态字段:',Province.country print u'类调用静态方法:',Province.f1() print u'类调用类方法:',Province.f2() print u'静态字段也可以被对象调用:',p.country
见如上的代码执行后的结果:
C:\Python27\python.exe D:/git/Python/FullStack/Study/oopTest.py
对象调用普通字段: 无涯
对象调用普通方法: 我就是个普通方法
None
类调用静态字段: china
类调用静态方法: 我是静态方法,我存在的意义就是类不需要创建对象就可以直接调用
None
类调用类方法: 我是类方法
None
静态字段也可以被对象调用: china
Process finished with exit code 0
特性方法,也就是说在一个类中,该方法不能有参数,可以@property,调用特性方法的时候就不需要加()了,我们来编写
一个案例,来进行调用,看执行的结果:
#!/usr/bin/env python #-*- coding:utf-8 -*- class Province(object): #静态字段,属于类 country='china' def __init__(self,name): #普通字段,属于对象 self.name=name def show(self): print u'我就是个普通方法' @staticmethod def f1(): print u'我是静态方法,我存在的意义就是类不需要创建对象就可以直接调用' @classmethod def f2(cls): print u'我是类方法' @property def end(self): print 'name is {0}'.format(self.name) p=Province('无涯') p.end
见调用后代码执行的结果:
C:\Python27\python.exe D:/git/Python/FullStack/Study/oopTest.py name is 无涯 Process finished with exit code