python 面向对象总结
(1)面向对象(OOP)概念
面向过程:早期的编程概念,类似于函数,但只能执行,没有返回值,将功能独立的代码封装成一个个函数,最后顺序地调用不同的函数
函数式编程:不仅能执行,还可以返回结果
面向对象: 面向对象是更大的封装,根据职责在一个对象里封装多个方法,顺序地让不同的对象调用不同的方法
类和对象
类和对象是面向对象编程的两个核心概念
类是一群具有相同特征或者行为的事物的统称,是抽象的,不能直接使用,特征被称为属性,行为被称为方法
类相当于一个一个模板,是负责创建对象的
对象是类创建出来的一个具体的存在,可以直接使用,由什么类创建的对象,就拥有那个类中定义的属性和方法
在程序开发中,先有类再有对象
名词解析:
类——具有相同属性的对象的抽象。
属性——一类事物的特征。
方法——一类事物的技能。
实例(对象)——一个类的实例化后实例
实例化——一个类实例或成对象的过程。
面向对象的三大特征:
封装
对类的数据的赋值、内部调用对外部的用户都是透明的,这使得类成为一个容器,里面包含着类的数据和方法。
继承
一个类可以派生出子类,这个父类的属性、方法自动被子类继承。
多态
一个接口、多种实现。一个父类派生出不同的子类,且每个子类在继承父类的方法的同时,又对父类的方法做了不同的实现,这就是同一种事物表现出多种形态。
(2)类的定义与使用:
python 中使用class关键字来定义类,class键字之后是一个空格,接下来是类的名字,如果派生其他基类的话则把所有基类放到一对圆括号中并使用逗号隔开。
然后是一个冒号,最后换行并定义类的内部实现。类名首字母一般要大写,当然液可以按照自己的习惯定义类名,但是一般推荐参考惯例来命名。例如:
class Car(object): #定义一个类,类名Car,派生自object类
def infor(self): #定义成员方法
print("This is a car")
定义了类之后,就可以用来实例化对象,并通过“对象名 . 成员名”的方式访问其中的数据成员方法。列如:
>>>car=Car() #实例化对象
>>>car.infor() #调用对象的方法
This is a car
私有成员和公有成员:
在定义类的成员的时候,如果成员以两个下划线(_ _)开头则表示 私有成员,但是python并没有对私有成员提供严格的访问机制。私有成员在外部不能直接访问,
一般是在 类的内部进行访问和操作,或在类外部调用对象的公有成员方法访问。另外python 提供了一种特殊方式“对象名 . _类名_ _xxx可以访问 私有成员,
但这会破坏类的封装性。
>>>class A:
def _ _init_ _(self ,value1= 0,value2= 0) #构造函数
self._value1=value1
self._ _value2=value2 #私有成员
def setValue(self, value1,value 2):
self._value1=value
self._ _value2=value2 #在类中可以直接访问私有成员
def show(self): #成员方法
print(self._value1)
print(self._ _value2)
>>>a=A()
>>>a._value1 #在外部可以直接访问非私有成员
0
>>>a._A _value2 #在外部可以访问对象的私有数据成员
0
数据成员:
数据成语可以大致分为两类:属于对象的数据成员和类的数据成员。属于对象的数据成员主要指在构造函数_ _init()中定义(当然也可以在其他成员中方法定义你),
定义和使用时必须以self作为前缀(这一点是必须的),同一个类的不同对象之间的数据成员互不影响,属于类的数据成员是该所有对象共享的,不属于任何一个
一个对象。对象数据成员只能通过对象名访问;而类数据成员属于类,可以通过类名或对象名访问。
class Car(object):
price=10000 #属于类的数据成员
def_ _init_ _(self,c):
self.color=c #属于对象的数据的成员
car1=Car("red") #实例化对象
car2=Car("blue")
方法:
在类的定义方法可以粗略分为四大类:公有方法,私有方法,静态方法和类方法
类的所有实例方法都必须至少有一个名为self的函数,并且必须是方法的第一个形参,self参数代表对象自身
(3)类的继承
面向对象编程 (OOP) 语言的一个主要功能就是“继承”。继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。
通过继承创建的新类称为“子类”或“派生类”,被继承的类称为“基类”、“父类”或“超类”,继承的过程,就是从一般到特殊的过程。在某些 OOP 语言中,一个子类可以继承多个基类。但是一般情况下,一个子类只能有一个基类,要实现多重继承,可以通过多级继承来实现。
继承概念的实现方式主要有2类:实现继承、接口继承。
- 实现继承是指使用基类的属性和方法而无需额外编码的能力。
- 接口继承是指仅使用属性和方法的名称、但是子类必须提供实现的能力(子类重构爹类方法)。
在考虑使用继承时,有一点需要注意,那就是两个类之间的关系应该是“属于”关系。例如,Employee 是一个人,Manager 也是一个人,因此这两个类都可以继承 Person 类。但是 Leg 类却不能继承 Person 类,因为腿并不是一个人。
OO开发范式大致为:划分对象→抽象类→将类组织成为层次化结构(继承和合成) →用类与实例进行设计和实现几个阶段。
继承的定义
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
class Person( object ): # 定义一个父类 def talk( self ): # 父类中的方法 print ( "person is talking...." ) class Chinese(Person): # 定义一个子类, 继承Person类 def walk( self ): # 在子类中定义其自身的方法 print ( 'is walking...' ) c = Chinese() c.talk() # 调用继承的Person类的方法 c.walk() # 调用本身的方法 # 输出 person is talking.... is walking... |
构造函数的继承
如果我们要给实例 c 传参,我们就要使用到构造函数,那么构造函数该如何继承,同时子类中又如何定义自己的属性?
继承类的构造方法:
1.经典类的写法: 父类名称.__init__(self,参数1,参数2,...)
2. 新式类的写法:super(子类,self).__init__(参数1,参数2,....)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
class Person( object ): def __init__( self , name, age): self .name = name self .age = age self .weight = 'weight' def talk( self ): print ( "person is talking...." ) class Chinese(Person): def __init__( self , name, age, language): # 先继承,在重构 Person.__init__( self , name, age) #继承父类的构造方法,也可以写成:super(Chinese,self).__init__(name,age) self .language = language # 定义类的本身属性 def walk( self ): print ( 'is walking...' ) class American(Person): pass c = Chinese( 'bigberg' , 22 , 'Chinese' ) |
如果我们只是简单的在子类Chinese中定义一个构造函数,其实就是在重构。这样子类就不能继承父类的属性了。所以我们在定义子类的构造函数时,要先继承再构造,这样我们也能获取父类的属性了。
子类构造函数基础父类构造函数过程如下:
实例化对象c ----> c 调用子类__init__() ---- > 子类__init__()继承父类__init__() ----- > 调用父类 __init__()
子类对父类方法的重写
如果我们对基类/父类的方法需要修改,可以在子类中重构该方法。如下的talk()方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
class Person( object ): def __init__( self , name, age): self .name = name self .age = age self .weight = 'weight' def talk( self ): print ( "person is talking...." ) class Chinese(Person): def __init__( self , name, age, language): Person.__init__( self , name, age) self .language = language print ( self .name, self .age, self .weight, self .language) def talk( self ): # 子类 重构方法 print ( '%s is speaking chinese' % self .name) def walk( self ): print ( 'is walking...' ) c = Chinese( 'bigberg' , 22 , 'Chinese' ) c.talk() # 输出 bigberg 22 weight Chinese bigberg is speaking chinese |
(4)类的属性
1.类定义后就存在,而且不需要实例化
2.类属性使得相同类的不同实例共同持有相同变量
属性的定义:python中的属性其实是普通方法的衍生。
操作类属性有三种方法:
1.使用@property装饰器操作类属性。
2.使用类或实例直接操作类属性(例如:obj.name,obj.age=18,del obj.age)
3.使用python内置函数操作属性。
属性存在的意义:
1、访问属性时可以制造出和访问字段完全相同的假象,属性由方法衍生而来,如果Python中没有属性,方法完全可以代替其功能。
2、定义属性可以动态获取某个属性值,属性值由属性对应的方式实现,应用更灵活。
3、可以制定自己的属性规则,用于防止他人随意修改属性值。
下面详细介绍三种操作类属性的方法:
1.使用@property装饰器操作类属性。
定义时,在普通方法的基础上添加@property装饰器;属性仅有一个self参数,调用时无需括号;
优点:
1) @property装饰器可以实现其他语言所拥有的getter,setter和deleter的功能(例如实现获取,设置,删除隐藏的属性)
2) 通过@property装饰器可以对属性的取值和赋值加以控制,提高代码的稳定性。
实例代码1:
#encoding=utf-8 class Goods(): #新式类 @property def price(self): #查看属性值 print ('@property ') @price.setter #修改、设置属性 def price(self, value): print ('@price.setter' ) @price.deleter #删除属性 def price(self): print ('@price.deleter') obj = Goods(50) obj.price # 自动执行 @property 修饰的 price 方法,并获取方法的返回值 obj.price = 2000 # 自动执行 @price.setter 修饰的 price 方法,并将2000赋值给方法的参数 del obj.price # 自动执行 @price.deleter 修饰的 price 方法
结果输出:
@property
@price.setter
@price.deleter
(5)设计一个三维向量类,并实现向量的加法、减法以及向量与标量的乘法和除法运算。
代码如下:
class Vecter3:
def __init__(self, x=0, y=0, z=0):
self.X = x
self.Y = y
self.Z = z
def __add__(self, n):
r = Vecter3()
r.X = self.X + n.X
r.Y = self.Y + n.Y
r.Z = self.Z + n.Z
return r
def __sub__(self, n):
r = Vecter3()
r.X = self.X - n.X
r.Y = self.Y - n.Y
r.Z = self.Z - n.Z
return r
def __mul__(self, n):
r = Vecter3()
r.X = self.X * n
r.Y = self.Y * n
r.Z = self.Z * n
return r
def __truediv__(self, n):
r = Vecter3()
r.X = self.X / n
r.Y = self.Y / n
r.Z = self.Z / n
return r
def __floordiv__(self, n):
r = Vecter3()
r.X = self.X // n
r.Y = self.Y // n
r.Z = self.Z // n
return r
def show(self):
print((self.X,self.Y,self.Z))
v1 = Vecter3(1,2,3)
v2 = Vecter3(4,5,6)
v3 = v1+v2
v3.show()
v4 = v1-v2
v4.show()
v5 = v1*3
v5.show()
v6 = v1/2
v6.show()
结果是:
(5, 7, 9)
(-3, -3, -3)
(3, 6, 9)
(0.5, 1.0, 1.5)
(6)编写一个程序(类),用户输入一段英文,然后输出这段英文中所有长度为3个字母的单词井且如果单词如果有连续 复了2次,只输出一个【例: This isis a desk,程序输出 his is a desk】,(提示,有re正则匹配来做)
代码如下:
import re
x = input(" input a string:")
pattern = re.compile(r'[a-zA-Z]{3}')
list1=pattern.findall(x)
list2 = sorted(set(list1), key=list1.index)
list2.sort(key=list1.index)
print(list2)
# compile函数根据包含的正则表达式的字符串创建模式对象。
#findall()返回的是括号所匹配到的结果
import re
x = input(" input a string:")
pattern = re.compile(r'[a-zA-Z]{3}')
list1=pattern.findall(x)
list2 = set(list1)
print(list2)