核心概念
对象:现实存在的,是由属性和方法组成,具有唯一性。属性为静态的;方法为动态的,方法可以改变属性
类:抽象概念,就是一组相似事务的统称
特性
封装:就是把类的内部实现和使用分离开,只保留有限的接口与外部进行联系
继承:对于面向对象而言子类可以继承父类的属性和方法,并且可以重写和添加新的属性和方法,通过继承可以实现代码的重复利用
多态:同一事物的多种形态,在面向对象当中,如果都是来自同一继承,所以它们都有一个同名的方法,但是又是截然不同的两个方法,虽然调用的方法名是一样的但是实现过程是不一样的
定义类:class关键字
语法:
class ClassName: #类名规范要求每个单词首字母大写
'''类的帮助信息'''
statement #主要是由方法和属性等语句构成的
创建类的实例(对象)
语法:
ClassName(parameterlist)
#parameterlis:如果我们在创建类时没有创建__init()__方法那么这个参数可以省略;否则这个参数指定的就是__init()__方法当中需要传递的参数
创建__init__()方法
构造方法:在创建类的实例的时候会被自动执行,在这个方法当中可以定义一些进行初始化操作的代码
例:
class Geese: #定义类
'''大雁'''
def __init__(self): #定义构造方法且最多只能定义一个。必须定义一个参数如:self。而且这必须是第一个参数,还有其他参数写在它之后,表示指向实例本身的一个引用,通过它可以访问这个类当中定义的属性和方法。在实例化对象的时候会自动传递实际参数self
print("大雁类")
wildGoose = Geese() #定义对象(实例)
wildGoose1 = Geese()
print(wildGoose)
例2:多个参数
class Geese:
'''大雁'''
def __init__(self,mac,mm):
print("大雁类")
print(mac)
print(mm)
list = [1,2.3]
mm1 = "鸟类"
wildGoose = Geese(list,mm1)
创建类的成员并访问:主要包括实例方法和数据成员两部分
实例方法:就是面向对象当中的方法
创建实例方法语法:
def functionName(self,parameterlist):
block
#self:此参数可以随便定义名字担必须有
调用实例方法语法:
instanceName.functionName(parametervalue) #类名.实例方法名(参数)
#parametervalue:如果在self参数之外又传递了其他的参数,就需要制定对应的实例参数,个数要保持一致
例:
class Geese:
'''大雁'''
def __init__(self,mac,mm):
print("大雁类")
print(mac)
print(mm)
def num(self,nn = [3,8]): #创建实例方法,参数可以设置默认值
print(nn[1]+nn[0])
list = [1,2,3]
mm1 = "鸟类"
wildGoose = Geese(list,mm1)
wildGoose.num(list) #调用实例方法
数据成员:就是面向对象当中的属性,它是指在类当中定义的变量。根据它的定义位置又可以分为类属性和实例属性
类属性:定义在类中实例之外,可以在类的所有实例方法和构造方法中来使用这些类属性并共享值
类属性调用方法 :
实例内调用:类名.类属性名
实例外调用:类名.类属性名或实例名.类属性名
例:
class Geese:
'''大雁'''
list = [1,2] #定义类属性
mm1 = "鸟类" #定义类属性
def __init__(self):
print("大雁类")
print(Geese.list) #调用类属性
print(Geese.mm1) #调用类属性
wildGoose = Geese()
print(Geese.list) #查看类属性
print(wildGoose.list) #查看实例中的类属性
例2:所有实例可共享类属性
class Geese:
'''雁类'''
neck = "脖子较长" # 类属性(脖子)
wing = "振翅频率高" # 类属性(翅膀)
leg = "腿位于身份的中心支点,行走自如" # 类属性(腿)
number = 0 # 编号
def __init__(self): # 构造方法
Geese.number += 1 # 将编号加1
print("\n我是第"+str(Geese.number)+"只大雁,我属于雁类!我有以下特征:")
print(Geese.neck) # 输出脖子的特征
print(Geese.wing) # 输出翅膀的特征
print(Geese.leg) # 输出腿的特征
# 创建4个雁类的对象(相当于有4只大雁)
list1 = []
for i in range(4): # 循环4次
list1.append(Geese()) # 创建一个雁类的实例
print("一共有"+str(Geese.number)+"只大雁")
Geese.beak = "喙的基部较高,长度和头部的长度几乎相等" # 动态修改或添加类属性
print("第2只大雁的喙:",list1[1].beak) # 访问类属性
实例属性:定义在实例当中,只作用于当前实例
实例属性调用方法:
实例内调用:实例属性名字
实例外调用:实例名.实例属性名字
例:
class Geese:
'''大雁'''
def __init__(self):
self.list = [1,2] #定义实例属性
self.mm1 = "鸟类" #定义实例属性
print("大雁类")
print(self.list) #实例中调用实例属性
print(self.mm1)
wildGoose = Geese()
print(wildGoose.mm1) #是例外调用实例属性
wildGoose1 = Geese()
wildGoose1.list = [3.5] #动态修改或添加实例属性不影响其他实例属性
print(wildGoose.list)
print(wildGoose1.list)
访问限制
(1)私有方法/属性:私有方法采用双前置下划线的形式表示,只能在类内调用
python中定义的实例方法和属性默认为public,没有访问权限限制
限制属性或方法的命名格式:
__foo__:表示特殊方法,一般为系统定义的名字,例如__init()__
__foo:表示自定义的私有类型的成员,只允许定义这个方法或属性的类的本身进行访问,这样就不可以通过实例名进行访问了
访问方法:
类的内部访问:类名.__XXX(属性或方法名)
类的外部访问:类的实例名._类名__XXX(属性或方法名)
例:
class Geese:
'''大雁'''
__list = [1,2]
def __init__(self):
print(Geese.__list) #内部访问
wildGoose = Geese()
print(wildGoose._Geese__list) #外部访问
(2)保护方法/属性:只允许类本身和子类进行访问,但在模板中直接定义的时候不允许通过from module import * 语句导入
例:
class A:
def __init__(self):
self._id = 11
def _print(self, x):
print('AAAA' + str(x))
class B(A):
def out(self):
print('BBBB')
if __name__ == '__main__':
a = A()
b = B()
b._print('B') # 派生类调用基类的保护方法
print(b._id) # 派生类调用基类的保护属性
property属性:采用单前置下划线的形式,表示访问计算后所得的值,在python中可以通过@property来把一个方法转换为属性从而实现可以计算的属性,也称为装饰器
创建用于计算的属性
语法:
@property
def methodname():
block #一般情况下需要return语句来返回计算结果
例:
class Vern:
'''计算面积'''
def __init__(self,nn,mm):
self.w = nn #需要转为实例属性,不然后面的方法获取不到值
self.h = mm
@property
def num(self): #注意对于这个num属性不能动态重新赋值
return self.w*self.h
rect = Vern(12,21)
rect1 = Vern(2,8)
print(rect.num) #直接调用转换成属性后的方法
print(rect1.num)
为属性添加去安全保护机制
私有属性(实例属性)缺点:在类外不能修改和读取
优化属性:
例:通过property把私有属性转化为可读不可修改属性
class TVshow:
def __init__(self,show):
self.__Show = show
@property
def show(self):
return self.__Show
TV = TVshow("北京卫视")
print(TV.show) #读取私有属性
例:通过装饰器实现为属性添加过滤器,通过设置setter方法进行进行修改
class TVshow: # 定义电视节目类
list_film = ["战狼2","夺冠","西游记女儿国","熊出没·变形记"]
def __init__(self,show):
self.__show = show
@property # 将方法转换为属性
def show(self): # 定义show()方法
return self.__show # 返回私有属性的值
@show.setter # 设置setter方法,让show属性可修改
def show(self,value):
if value in TVshow.list_film: # 判断值是否在列表中
self.__show = "您选择了《" + value + "》,稍后将播放" # 返回修改的值
else:
self.__show = "您点播的电影不存在"
tvshow = TVshow("战狼2") # 创建类的实例
print("正在播放:《",tvshow.show,"》") # 获取私有属性值
print("您可以从",tvshow.list_film,"中选择要点播放的电影")
tvshow.show = "夺冠" # 修改私有属性值并过滤
print(tvshow.show) # 获取属性值
继承:创建一个类并继承自另一个类,创建的类为派生类,继承的类为基类。派生类会继承基类的所有实例方法和属性
继承的基本语法
class ClassName(baseclasslist): #baseclasslist:可以继承多个基类用逗号隔开,默认为对象
'''help'''
statement
例:
class Fruit: # 定义水果类(基类)
color = "绿色" # 定义类属性
def harvest(self, color):
print("水果是:" + color + "的!") # 输出的是形式参数color
print("水果已经收获……")
print("水果原来是:" + Fruit.color + "的!"); # 输出的是类属性color
class Apple(Fruit): # 定义苹果类(派生类)
color = "红色"
def __init__(self):
print("我是苹果")
class Orange(Fruit): # 定义橘子类(派生类)
color = "橙色"
def __init__(self):
print("\n我是橘子")
apple = Apple() # 创建类的实例(苹果)
apple.harvest(apple.color) # 调用基类的harvest()方法
orange = Orange() # 创建类的实例(橘子)
orange.harvest(orange.color) # 调用基类的harvest()方法
方法的重写:在派生类中重写在基类中的方法
例:
class Fruit: # 定义水果类(基类)
color = "绿色" # 定义类属性
def harvest(self, color):
print("水果是:" + color + "的!") # 输出的是形式参数color
print("水果已经收获……")
print("水果原来是:" + Fruit.color + "的!"); # 输出的是类属性color
class Apple(Fruit): # 定义苹果类(派生类)
color = "红色"
def __init__(self):
print("我是苹果")
def harvest(self, color):
print("苹果是:" + color + "的!") # 输出的是形式参数color
print("苹果已经收获……")
print("苹果原来是:" + Fruit.color + "的!"); # 输出的是类属性color
class Orange(Fruit): # 定义橘子类(派生类)
color = "橙色"
def __init__(self):
print("\n我是橘子")
def harvest(self, color):
print("橘子是:" + color + "的!") # 输出的是形式参数color
print("橘子已经收获……")
print("橘子原来是:" + Fruit.color + "的!"); # 输出的是类属性color
apple = Apple() # 创建类的实例(苹果)
apple.harvest(apple.color) # 调用重写基类的harvest()方法
orange = Orange() # 创建类的实例(橘子)
orange.harvest(orange.color) # 调用重写基类的harvest()方法
在派生类当中调用基类的__init__()方法
在默认情况下在派生类中定义一个构建方法之后就不会自动调用基类的构建方法,如果在派生类中不定义构造方法那么会自动调用基类的构造方法,如果派生类和基类中都定义构造方法那么会执行派生类的构造方法,然后基类的构造方法会抛出异常、
也可以通过super()函数调用基类的构造方法
例:
class Fruit: # 定义水果类(基类)
def __init__(self,color = "绿色"):
Fruit.color = color # 定义类属性
def harvest(self, color):
print("水果是:" + self.color + "的!") # 输出的是形式参数color
print("水果已经收获……")
print("水果原来是:" + Fruit.color + "的!"); # 输出的是类属性color
class Apple(Fruit): # 定义苹果类(派生类)
color = "红色"
def __init__(self):
print("我是苹果")
super().__init__()
class Aapodilla(Fruit): # 定义人参果类(派生类)
def __init__(self,color):
print("\n我是人参果")
super().__init__(color)
# 重写harvest()方法的代码
def harvest(self,color):
print("人参果是:"+color+"的!") # 输出的是形式参数color
print("人参果已经收获……")
print("人参果原来是:"+Fruit.color+"的!"); # 输出的是类属性color
apple = Apple() # 创建类的实例(苹果)
apple.harvest(apple.color) # 调用基类的harvest()方法
sapodilla = Aapodilla("白色") # 创建类的实例(人参果)
sapodilla.harvest("金黄色带紫色条纹") # 调用基类的harvest()方法