面向对象:以问题对象构建和应用为核心编程写程序的方式。
面向过程:以解决问题的过程步骤为核心编程写程序的方式。
封装(encapsulation):属性和方法的抽象
继承(inheritance):代码复用的高级抽象
多态polymorphism:仅针对方法,方法灵活性的抽象
类(class)和对象(object)
类(class)和对象(object)的分类
类对象VS实例对象
例:
'''商品价格统计,有3个商品:电脑、打印机和投影仪,每个商品有1个
原始售价和1个折扣售价,求3个商品原始售价的和以及折扣售价的和。'''
class Product():
def __init__(self,name):
self.name=name #定义了抽象的product类,保存名字和价格等信息
self.label_price=0 #初始价格为0
self.real_price=0
c=Product("电脑") #产生3个对象,分别对应具体的商品
d=Product("打印机")
e=Product("投影仪")
c.label_price,c.real_price=10000,8000 #对3个对象商品赋值价格
e.label_price,e.real_price=2000,1000
d.label_price,d.real_price=1500,900
for i in [c,d,e]: #求和并输出价格
s1+=i.label_price
s2+=i.real_price
print(s1,s2)
'''面向过程编写可能更短,但是从语义理解上更直接利于理解'''
三个特性:封装、继承、多态
使用class保留字定义类
class <类名>:
"类描述 ‘XXXXXXXXXX’"
<语句块>
class DemoClass:
"this is a demo for python class"
pass
print(DemoClass.__doc__)
#输出为 this is a demo for python class
类对象
class DemoClass:
"this is a demo for python class"
print("hello demo class")
print(DemoClass.__doc__)
print(type(DemoClass))
#输出为
#hello demo class
#this is a demo for python class
#
实例对象
class DemoClass:
"this is a demo for python class"
print("hello demo class")
print(type(DemoClass))
cn=DemoClass()
print(type(cn))
#输出为hello demo class
#
#
了解python类的构造函数
了解python类的属性和方法
类的构造函数
class <类名>:
def __init__(self,<列参>):
print(name)
dc1=DemoClass("老王")
dc2=DemoClass("老李")
#输出为
#老王
#老李
init()的使用说明
self在类定义内部代表类的实例
属性是类内部定义的变量
属性是类内部定义的变量
class <类名>:
<类属性名>=<类属性初值>
def __init__(self,<参数列表>):
self.<实例属性名>=<实例属性初值>
#例子DemoClass.count+=1可以常用于统计类被实例化了多少次。
class DemoClass:
count=0 #类属性
def __init__(self,name,age):
self.name=name
self.age=age
DemoClass.count+=1
#直接在类中定义或赋值,统一用<类名>.<属性名>访问。
dc1=DemoClass("老王",45)
dc2=DemoClass("老李",51)
print("总数:",DemoClass.count)
print(dc1.name,dc2.name)
#输出为
#总数:2
#老王 老李
属性是类内部定义的变量
类的方法:方法是类内部定义的函数
实例方法是类内部定义的函数,与实例对象相关。
class <类名>:
def <方法名>(self,<参数列表>):
......
class DemoClass:
def __init__(self,name):
self.name=name
def lucky(self):#实例方法的定义,第一个参数是self
s=0
for c in self.name:
s+=ord(c)%100
return s
dc1=DemoClass("老王")
dc2=DemoClass("老李")
print(dc1.name,"的幸运数字是:",dc1.lucky())
print(dc2.name,"的幸运数字是:",dc2.lucky())
#输出为
#老王的幸运数字是:148
#老李的幸运数字是:115
类方法是与类对象相关的函数,由所有实例对象共享。
class <类名>:
@classmethod #装饰器
def <方法名>(cls,<参数列表>) #第一个参数默认保留为cls,表示一个类。
......
class DemoClass:
count=0
def __init__(self,name):
self.name=name
DemoClass.count+=1
@classmethod #类方法使用装饰器表示
def getChrCount(cls): #类方法只能使用类属性或其他类方法
s="零一二三四五六七八九多"
return s[DemoClass.count]
dc1=DemoClass("老王")
dc2=DemoClass("老李")
print(dc1.getChrCount()) #类方法的调用可以用类名或对象名
print(DemoClass.getChrCount())
#输出为
#二
#二
自由方法是定义在类命名空间的普通函数
class <类名>:
def <方法名>(<参数列表>):
......
class DemoClass:
count=0
def __init__(self,name):
self.name=name
DemoClass.count+=1
def foo():
DemoClass.count*=100
return DemoClass.count
dc1=DemoClass("老王")
print(DemoClass.foo())
#输出为
#100
静态方法是定义在类中的普通函数,能够被所有实例对象共享
class <类名>:
@staticmethod
def <方法名>(<参数列表>)
......
class DemoClass:
count=0
def __init__(self,name):
self.name=name
DemoClass.count+=1
@staticmethod
def foo():
DemoClass.count*=100
return DemoClass.count
dc1=DemoClass("老王")
print(DemoClass.foo())
print(dc1.foo())
#输出为
#100
#10000
保留方法由双下划线开始和结束的方法,保留使用。
class <类名>:
def <保留方法名>(<参数列表>):
......
例:
class DemoClass:
count=0
def __init__(self,name):
self.name=name
Democlass.count+=1
def __len__(self):
return len(self.name)
dc1=DemoClass("老王")
dc2=DemoClass("小诸葛")
print(len(dc1))
print(len(dc2))
#输出为
#2
#3
类的析构函数
class <类名>:
def __def__(self):
<语句块>
......
'''析构函数在真是删除实例对象时被调用。'''
class DemoClass:
def __init__(self,name):
self.name=name
def __del__(self):
print("再见",self.name)
dc1=DemoClass("老王")
del dc1
#输出为
#再见 老王
del()的使用说明
class DemoClass:
def __init__(self,name):
self.name=name
def __del__(self):
print("再见",self.name)
dc1=DemoClass("老王")
dc2=dc1 #删除dc1时,由于dc2存在,则仅删除dc1引用。
del dc1 #退出时,真实删除dc2对应对象。
print(dc2.name)
#输出结果为:
# 老王
# 再见老王
sys.getrefcount(<对象名>)获得对象的引用次数
import sys
class DemoClass:
def __init__(self,name):
self.name=name
def __del__(self):
return "再见"+self.name
dc1=DemoClass("老王")
dc2=dc1
print(sys.getrefcount(dc1))
#输出为
#3
封装EncapSulation:属性和方法的抽象
属性
方法
封装:让数据和代码成为类的过程,表达为:类-属性-方法。
公开属性:即类属性
class <类名>:
<类属性名>=<类属性初值>
def __init__(self,<参数列表>):
self.<实例属性名>=<实力属性初值>
私有类属性:仅供当前类访问的类属性,子类亦不能访问。
class <类名>:
__<私有类属性名>=<类属性初值>
def __init__(self,<参数列表>)
......
class DemoClass:
__count=0 #私有类属性定义
def __init__(self,name):
self.name=name
DemoClass.__count+=1 #私有类属性的内部使用
@classmethod
def getCount(cls):
return DemoClass.__count #私有类属性的内部使用
dc1=DemoClass("老王")
dc2=DemoClass("老李")
print(DemoClass.getCount()) #类的类方法
私有方法
class <类名>:
def __<方法名>(self,<参数列表>)
...
class DemoClass:
def __init__(self,name):
self.__name=name
def __getName(self):
if self.__name!="":
return self.__name
else:
return "老张"
def printName(self):
return "{}同志".format(self.__getName())
dc1=DemoClass("老王")
dc2=DemoClass("")
print(dc1.printName(),dc2.printName())
#输出为
#老王同志 老张同志
类的保留属性
类的名称 | 作用 |
---|---|
.__ doc __ | 类描述,写在类定义下的首行字符串,不能继承 |
. __name __ | 类的名称 |
.__ qualname __ | 以.分割从模块全局命名空间开始的类名称 |
.__ bases __ | 类所继承的基类名称 |
<类>. __ dict __ | 包含类成员信息的字典,key是属性和方法名称,value是地址 |
<对象>. __ dict __ | 包含对象属性信息的字典,key是属性名称,value是值 |
.__ class __ | 对象所对应的类信息,即type信息 |
.__ module __ | 类所在模块的名称 |
class DemoClass:
"a demo class"
def __init__(self,name):
self.name=name
def getName(self):
return self.name
dc1=DemoClass("老王")
print(DemoClass.__qualname__,DemoClass.__name__,DemoClass.__bases__)
#DemoClass DemoClass(,)
class DemoClass:
"a demo class"
def __init__(self,name):
self.name=name
def getName(self):
return self.name
dc1=DemoClass("老王")
print(DemoClass.__doc__,DemoClass.__module__,DemoClass.__class__)
print(dc1.__doc__,dc1.__module__,dc1.__class__)
#a demo class,__main__,
#a demo class,__main__,
python解释器预留的类方法,以双下划线开头和结尾。
也叫:特殊方法。
特点:双下划线开头和结尾。
作用:为操作python类提供了统一的方法接口。
方法逻辑:具有特定含义,一般与操作符有关联,类定义需要重载。
保留方法 | 对应操作 | 描述 |
---|---|---|
obj.__ init __ | obj=ClassName() | 初始化实例对象的函数逻辑 |
obj.__ del __ | del obj | 删除实力兑现的函数逻辑 |
obj.__repr __ | repr(obj) | 定义对象可打印字符串的函数逻辑 |
obj.__ str __ | str(obj) | 定义对象字符串转换操作的函数逻辑 |
obj.__ bytes __ | bytes(obj) | 定义对象字节串转换操作的函数逻辑 |
obj.__ format __ | obj.format() | 定义对象格式化输出的函数逻辑 |
obj.__ hash __ | hash(obj) | 定义对象哈希操作的函数逻辑 |
obj.__ bool __ | bool(obj) | 定义对象布尔运算的函数逻辑 |
obj.__ len __ | len(obj) | 定义对象长度操作的函数逻辑 |
obj.__ reversed __ | reversed(obj) | 定义对象逆序的函数逻辑 |
obj.__ abs __ | abs(obj) | 定义对象绝对值的函数逻辑 |
obj.__ int __ | int(obj) | 定义对象整数转换的函数逻辑 |
继承inheritance:代码复用的高级抽象
继承定义
类继承的构建
class <类名>(基类名):
def __init__(self,<参数列表>):
<语句块>
......
class DemoClass: #基类
count=0
def __init__(self,name):
self.name=name
DemoClass.count+=1
def getName(self):
return self.name
class HumanNameClass(DemoClass): #派生类
def printName(self):
return str(DemoClass.count)+self.name+"同志"#对基类类属性的使用
dc1=HumanName("老王") #对基类实例方法的使用
print(dc1.getName()) #对派生类实例方法的使用
print(dc1.printName())
两个与继承关系判断有关的python内置函数
函数 | 描述 |
---|---|
isinstance(obj,cls) | 判断对象obj是否是类cls的实例或子类实例,返回True/False。 |
issubclass(cls1,cls2) | 判断类cls1是否是类cls2的子类,返回True/False |
class DemoClass: #基类
count=0
def __init__(self,name):
self.name=name
DemoClass.count+=1
def getName(self):
return self.name
class HumanNameClass(DemoClass):
def printName(self):
return str(DemoClass.count)+self.name+"同志"
dc1=HumanNameClass("老王")
print(isinstance(dc1,DemoClass))
print(isinstance(dc1,HumanNameClass))
print(issubclass(HumanNameClass,DemoClass))
#返回全True
派生类的约束
object类是python所有类的基类
python对象的三要素:标识、类型和值
2个与基础类有关的python内置功能
函数 | 描述 |
---|---|
id(x) | 返回X的标识,python用内存地址表示。 |
x is y | 判断x和y的标识是否相等,返回True/False,不判断值。 |
class DemoClass: #基类
count=0
def __init__(self,name):
self.name=name
DemoClass.count+=1
def getName(self):
return self.name
class HumanNameClass(DemoClass):
def printName(self):
return str(DemoClass.count)+self.name+"同志"
dc1=HumanNameClass("老王")
print(id(dc1),type(dc1))
print(id(DemoClass),type(DemoClass))
print(dc1 is DemoClass)
print(type(object),type(type))
'''
86222320
86207768
False
'''
类的重载
最近覆盖原则:重载无需特殊标记。
class DemoClass:
count=0
def __init__(self,name):
self.name=name
DemoClass.count+=1
class HumanNameClass(DemoClass):
count=99
def __init__(self,name):
self.name=name
HumanNameClass.count-=1
def printCount(self):
return str(HumanNameClass.count)+self.name
dc1=HumanNameClass("老王")
print(dc1.printCount())
#输出为
#98老王
方法重载(派生类对基类方法的再定义)
class <派生类>(基类):
def <方法>(self,参数列表):
super().<基类>(参数列表)
class DemoClass:
count=0
def __init__(self,name):
self.name=name
DemoClass.count+=1
def printCount(self):
return str(DemoClass.count)+self.name
class HumanNameClass(DemoClass):
def __init__(self,name):
self.name=name
def printCount(self):
return super().printCount()+"同志"
dc1=HumanNameClass("老王")
print(dc1.printCount())
#输出为
#0老王同志
类的多继承
class <类名>(基类1,基类2):
def __init__(self,参数列表):
<语句块>
......
#基类名可以带有路径:ModuleName.BaseClassName
类多继承的使用说明
class DemoClass:
def __init__(self,name):
self.name=name
def printName(self):
return self.name
class NameClass:
def __init__(self,title):
self.nick=title
def printName(self):
return self.nick+"同志"
class HumanNameClass(DemoClass,NameClass):
pass
dc1=HumanNameClass("老王")
print(dc1.printName())
#输出为
#老王