python中面向对象编程
编程范式:
编程是 程序 员 用特定的语法+数据结构+算法组成的代码来告诉计算机如何执行任务的过程 , 一个程序是程序员为了得到一个任务结果而编写的一组指令的集合,正所谓条条大路通罗马,
实现一个任务的方式有很多种不同的方式, 对这些不同的编程方式的特点进行归纳总结得出来的编程方式类别,即为编程范式。 不同的编程范式本质上代表对各种类型的任务采取的不同的解决问题的思路,
大多数语言只支持一种编程范式,当然也有些语言可以同时支持多种编程范式。 两种最重要的编程范式分别是面向过程编程和面向对象编程。
1.函数式:
将某功能封装到函数中,日后便无需重复编程,仅调用函数即可。
2.面向过程
procedure-oriented Programming :根据业务逻辑从上到下写代码,函数是Python内建支持的一种封装,我们通过把大段代码拆成函数,通过一层一层的函数调用,
就可以把复杂任务分解成简单的任务,这种分解可以称之为面向过程的程序设计。函数就是面向过程的程序设计的基本单元
3.面向对象:
对函数进行分类和封装,让开发“更快更好更强",Object Oriented Programming,简称OOP,是一种程序设计思想。OOP把对象作为程序的基本单元,
一个对象包含了数据和操作数据的函数。
python中面向对象的基本概念
1.类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
2.类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
3.数据成员:类变量或者实例变量用于处理类及其实例对象的相关的数据。
4.方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。
5.实例变量:定义在方法中的变量,只作用于当前实例的类。
6.继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。
例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟"是一个(is-a)"关系(例图,Dog是一个Animal)。实例化:创建一个类的实例,类的具体对象。
7.方法:类中定义的函数。
8.对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法
创建一个类:
'''类的属性'''
class_suite # 类体
类的帮助信息可以通过ClassName.__doc__开查看
class_suite 由类成员,方法,数据属性组成。
构造函数:对实例化的对象进行初始化操作
实例:
定义一个员工类:
#!/usr/bin/env python # -*- coding: UTF-8 -*- class Employee(object): '所有员工的基类' empCount = 0 ) def __init__(self, name, salary): self.name = name self.salary = salary Employee.empCount += 1 def displayCount(self): print "Total Employee %d" % Employee.empCount def displayEmployee(self): print "Name : ", self.name, ", Salary: ", self.salary
empCount变量是一个类变量,它的值将在这个类的所有实例之间共享。你可以在内部类或外部类使用Employee.empCount访问
第一种方法__init__()方法是一种特殊的方法,被称为类的构造函数或初始化方法,当创建了这个类的实例时就会调用该方法
理解此处的self是什么意思? self 接收的是创建的对象 ,
析构函数:
其中的“__del__”就是一个析构函数了,当使用del 删除对象时,会调用他本身的析构函数,另外当对象在某个作用域中调用完毕,
在跳出其作用域的同时析构函数也会被调用一次,这样可以用来释放内存空间。
例子:
class People: def __init__(self,name,self.name = name self.age = self.sex = sex def eat(self): print("%s 开始吃饭了!" %self.name) def __del__(self): # 析构函数,程序即将提出时要执行的 print("程序就要开始退出了,请保存!") p1 = People("alex",12,"man") p1.eat()
执行结果为:
/usr/bin/python3.4 /home/sm/python/day06/testOriented_Object.py alex 开始吃饭了! 程序就要开始退出了,请保存!
创建对象:
要创建一个类的实例,你可以使用类的名称,并通过__init__方法接受参数。
"创建 Employee 类的第一个对象"
emp1 = Employee("Zara", 2000)
"创建 Employee 类的第二个对象"
emp2 = Employee("Manni", 5000)
访问属性:
您可以使用点(.)来访问对象的属性。使用如下类的名称.访问类变量:
emp1.displayEmployee()
emp2.displayEmployee()
print "Total Employee %d" % Employee.empCount
你可以添加,删除,修改类的属性:
emp1.age = 7 # 添加一个 'age' 属性
emp1.age = 8 # 修改 'age' 属性
del emp1.age # 删除 'age' 属性
你也可以使用以下函数的方式来访问属性:
getattr(obj, name[, default]) : 访问对象的属性。
hasattr(obj,name) : 检查是否存在一个属性。
setattr(obj,name,value) : 设置一个属性。如果属性不存在,会创建一个新属性。
delattr(obj, name) : 删除属性。
类变量和成员变量的区别
类方法和成员方法的,静态方法的区别?
类方法:是类对象所拥有的方法,需要用修饰器"@classmethod"来标识其为类方法,对于类方法,第一个参数必须是类对象,
一般 以"cls"作为第一个参数(当然可以用其他名称的变量作为其第一个参数,但是大部分人都习惯以'cls'作为第一个参数的名字,
就最好用'cls' 了),能够通过实例对象和类对象去访问。
静态方法:需要通过修饰器"@staticmethod"来进行修饰,静态方法不需要多定义参数。
实例方法:在类中最常定义的成员方法,它至少有一个参数并且必须以实例对象作为其第一个参数,一般以名为'self'的变量作为第一个参数
(当然可以以其他名称的变量作为第一个参数)。在类外实例方法只能通过实例对象去调用,不能通过其他方式去调用
例如:
class people(object): __country = "china" # 列、类变量 # 类方法通过 classmethod修饰 @classmethod # 类方法 def getCountry(cls): return cls.__country @classmethod def SetCountry(cls,country): cls.__country = country # 静态方法通过 staticmethod修饰 @staticmethod def getCountry2(): return people.getCountry() #实例方法 def say(self): print("My country is %s" %people.getCountry2()) print(people.getCountry()) people.SetCountry("Japan") print(people.getCountry()) print(people.getCountry2()) p1 = people() p1.say()
运行结果为:
1 china 2 Japan 3 Japan 4 My country is Japan
对于类属性和实例属性,如果在类方法中引用某个属性,该属性必定是类属性,而如果在实例方法中引用某个属性(不作更改),
并且存在同名的类属 性,此时若实例对象有该名称的实例属性,则实例属性会屏蔽类属性,即引用的是实例属性,若实例对象没有
该名称的实例属性,则引用的是类属性;如果在实例方 法更改某个属性,并且存在同名的类属性,此时若实例对象有该名称的实例属性,
则修改的是实例属性,若实例对象没有该名称的实例属性,则会创建一个同名称的 实例属性。想要修改类属性,如果在类外,
可以通过类对象修改,如果在类里面,只有在类方法中进行修改。
从类方法和实例方法以及静态方法的定义形式就可以看出来,类方法的第一个参数是类对象cls,那么通过cls引用的必定是类对象的属性和方法;
而实例方法的第一个参数是实例对象self,那么通过self引用的可能是类属性、也有可能是实例属性(这个需要具体分析),不过在存在相同名称的类属性 和实例属性的情况下,
实例属性优先级更高。静态方法中不需要额外定义参数,因此在静态方法中引用类属性的话,必须通过类对象来引用。
python中的继承:
1)在Python中,如果父类和子类都重新定义了构造方法__init( )__,在进行子类实例化的时候,子类的构造方法不会自动调用父类的构造方法,必须在子类中显示调用。
2)如果需要在子类中调用父类的方法,需要以 父类名.方法 这种方式调用,以这种方式调用的时候,注意要传递self参数过去。
对于继承关系,子类继承了父类所有的公有属性和方法,可以在子类中通过父类名来调用,而对于私有的属性和方法,子类是不进行继承的,因此在子类中是无法通过父类名来访问的。
此时有一个问题就是如果SubClass没有重新定义构造方法,它会自动调用哪个父类的构造方法?这里记住一点:以第一个父类为中心。如果 SubClass重新定义了构造方法,
需要显示去调用父类的构造方法,此时调用哪个父类的构造方法由你自己决定;若SubClass没有重新定义构造方 法,则只会执行第一个父类的构造方法。并且若SuperClass1和SuperClass2中有同名的方法,
通过子类的实例化对象去调用该方法时调用的 是第一个父类中的方法。
例如:
class test1(object): def test(self): print("in the test1!") class university(object): student_list = [] tearcher_list = [] def __init__(self,name): self.name = name def show_teacher(self): for index,teacher in enumerate(university.tearcher_list): print(index,teacher) def show_student(self): for index,student in enumerate(university.student_list): print(index,student) # 父类 class universityMember(object): def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex def getName(self): return self.name def getAge(self): return self.age def getSex(self): return self.sex def test(self): print("in the universityNumber") # 子类 学生 class student(test1,universityMember): def __init__(self,name,age,sex,stu_id): super(student,self).__init__(name,age,sex) self.stu_id = stu_id def getStu_id(self): return self.stu_id def showInfo(self): print(""" =========Student %s information is================== name:%s age:%s sex:%s stu_id:%s """%(self.name,self.name,self.age,self.sex,self.stu_id)) # 子类老师 class teacher(universityMember): def __init__(self,name,age,sex,salary): super(teacher,self).__init__(name,age,sex) self.salary = salary def teach(self,course): print("%s teach course!" %self.name) def getSalary(self): return self.salary def showInfo(self): print(""" =========Student %s information is================== name:%s age:%s sex:%s salary:%s """%(self.name,self.name,self.age,self.sex,self.salary)) s1 = student("alex",23,"男",1002) s1.test() s1.showInfo()
运行结果为:
1 Testing started at 下午11:14 ... 2 in the test1! 3 4 =========Student alex information is================== 5 name:alex 6 age:23 7 sex:男 8 stu_id:1002
python2经典类是按照深度优先继承的。
python2新式类是按照广度优先继承的。
python3中经典类、新式类是按照广度优先搜索进行的。
python中的多态:
多态性(polymorphisn)是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。
简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。
那么,多态的作用是什么呢?我们知道,封装可以隐藏实现细节,使得代码模块化;继承可以扩展已存在的代码模块(类);它们的目的都是为了——代 码重用。
而多态则是为了实现另一个目的——接口重用!多态的作用,就是为了类在继承和派生的时候,保证使用“家谱”中任一类的实例的某一属性时的正确调用。Pyhon不直接支持多态,但可以间接实现
1 #!/usr/bin/env python 2 # _*_ encoding:utf-8 _*_ 3 # author:snate 4 5 class Animal: 6 def __init__(self, name): # Constructor of the class 7 self.name = name 8 9 def talk(self): # Abstract method, defined by convention only 10 raise NotImplementedError("Subclass must implement abstract method") 11 12 13 class Cat(Animal): 14 def talk(self): 15 return 'Meow!' 16 17 18 class Dog(Animal): 19 def talk(self): 20 return 'Woof! Woof!' 21 22 23 animals = [Cat('Missy'), 24 Dog('Lassie')] 25 26 for animal in animals: 27 print(animal.name + ': ' + animal.talk())