1.什么是类?什么是对象?
类是具有相同属性和技能一组对象的抽象
对象是类实例化的结果,用来描述一个具体的事物
比如猫是一个类,而我养的猫是一个对象
2.创建一个猫类并实例化的代码
class Cat():
def __init__(self,name,age,color):
self.name = name
self.age = age
self.color = color
def talk(self):
print('%s叫了一声miao'%(self.name))
xmt = cat('小馒头','5','white')
3.以上代码的执行顺序
以上面的猫类为例:
1.首先创建一个内存空间,Cat指向这块内存空间
2.在内存空间中存入__init__、talk的内存地址
3.再创建一块内存空间,self指向这块内存空间,同时创建一个类指针,指向类
4.在这块空间中存入name、age、color的值
5.执行结果返回给对象xmt
4.类中有哪些东西
静态变量、实例变量、绑定方法、类方法、静态方法
5.什么是组合
一个类是另一个类的属性,如下,先定义了一个圆类,然后定义了一个圆环类,圆类是圆环类的一个属性
from math import pi
class Circle():
def __init__(self,r):
self.r = r
def area(self):
return pi * self.r * self.r
def circf(self):
return pi * self.r * 2
class Ring():
def __init__(self,outr,inr):
self.outr = Circle(outr)
self.inr = Circle(inr)
def area(self):
return self.outr.area() - self.inr.area()
def circf(self):
return self.outr.circf() + self.inr.circf()
ring1 = Ring(10,5)
print(ring1.area(),ring1.circf())
6.类的继承
6.1什么是新式类?什么是经典类?
继承了object的类都是新式类,不继承object类的类是经典类
在py3中,所有类都是新式类,在py2中,主动继承了object类的类是新式类,其他类是经典类
6.2 类继承的顺序
在单继承中,经典类与新式类没有区别
在多继承中,经典类遵循深度优先,新式类遵循C3算法,可通过类名.mro()来查看继承顺序
6.3抽象类
抽象类是一种规范,用于约束子类实现抽象类同名的方法,有两种实现方式
比如支付类有两个子类支付宝支付类和微信支付类,都要实现支付功能
方式1:在调用Alipay或Wechatpay的pay方法时,如果没有重写pay方法,就会报错
class Payment():
def pay(self,money):
raise NotImplementedError('没有实现pay方法')
class Alipay(Payment):
def __init__(self,name):
self.name = name
def pay(self,money):
print('%s使用Alipay支付%s'%(self.name,money))
class Wechatpay(Payment):
def __init__(self, name):
self.name = name
def pay(self,money):
print('%s使用wechatoay支付%s' % (self.name, money))
方式2:引用模块,这种方式约束力强
from abc import ABCMeta,abstractmethod
class Payment(metaclass=ABCMeta):
@abstractmethod
def pay(self,money):
raise NotImplementedError('没有实现pay方法')
class Alipay(Payment):
def __init__(self,name):
self.name = name
def pay(self,money):
print('%s使用Alipay支付%s'%(self.name,money))
class Wechatpay(Payment):
def __init__(self, name):
self.name = name
def pay(self,money):
print('%s使用wechatoay支付%s' % (self.name, money))
def pay(name,money,kind):
if kind == 'Alipay':
obj = Alipay(name)
elif kind == 'Wechatpay':
obj = Wechatpay(name)
obj.pay(money)
pay('傅马甲',100,'Alipay')
6.4 super方法
1.super方法如何执行?
把所有的父类方法执行一遍,不重复执行,顺序遵循C3算法,通过类名.mro()查看
2.super的执行顺序
class A(object):
def func(self):
print('A')
class B(A):
def func(self):
super().func()
print('B')
class C(A):
def func(self):
super().func()
print('C')
class D(B,C):
def func(self):
super().func()
# super(D,self).func()
print('D')
D().func()
print(D.mro())
执行的结果为A C B D
mro显示的顺序为[<class ‘main.D’>, <class ‘main.B’>, <class ‘main.C’>, <class ‘main.A’>, <class ‘object’>]
3.super的例子
比如一个视频收费网站有普通用户User类,有一个VIP用户Vipuser类,可以通过super调用父类的__init__方法
class User:
def __init__(self,name):
self.name = name
class VIPUser(User):
def __init__(self,name,level,strat_date,end_date):
# User.__init__(self,name)
super().__init__(name) # 推荐的
# super(VIPUser,self).__init__(name)
self.level = level
self.strat_date = strat_date
self.end_date = end_date
**7.多态
7.1什么是多态?
一个类表现出的多种状态,如6.3中的Payment类表现出Alipay、Wechatpay两种状态
7.2其他语言中的多态
JAVA中参数必须指定类型,如6.3中的pay函数,kind必须制定一个类型,为了让kind可以传Alipay和Wechatpay两个类,必须让他们继承同一个父类Payment。
而在python中,处处是多态。
8.封装
8.1什么是封装?
将类中的变量、方法隐藏起来,外部无法访问
8.2python中的封装?
在变量或者方法前面加上__
8.3python中的本质
本质是将变量改名为 _类名__变量名,只能在类的内部通过__变量名来使用。
9.反射
9.1什么是反射?
通过字符串来寻找对应的变量或者方法
9.2反射的基本语法
变量 = getattr(类名/对象名/模块名,‘属性的字符串形式’)
9.3反射的实际应用
如6.3中将抽象类时,有一个pay函数
def pay(name,money,kind):
if kind == 'Alipay':
obj = Alipay(name)
elif kind == 'Wechatpay':
obj = Wechatpay(name)
obj.pay(money)
我们使用kind来接收支付的类型,但是随着支付类型的增多,我们就要写很多个elif,反射就可以帮我们减少工作量。下面我们通过反射来重写这个pay函数
import sys
def pay(name,price,kind):
class_name = getattr(sys.modules[__name__], kind)
obj = class_name(name)
obj.pay(price)
10.property装饰器
10.1为什么要有property装饰器?
在前面将组合的时候,我们遇到一个问题,我们要查看圆的面积是通过对象名.area()方式,但是area是一个属性,我们习惯用对象名.area来调用,这个时候property就有作用了。
from math import pi
class Circle():
def __init__(self,r):
self.r = r
@property #装饰的这个方法不能有参数
def area(self):
return pi * self.r * self.r
c = Circle(5)
print(c.area)
10.2如何修改、删除被装饰的属性?
class Goods:
discount = 0.8
def __init__(self,name,origin_price):
self.name = name
self.__price = origin_price
@property
def price(self):
return self.__price * self.discount
@price.setter
def price(self,new_value):
if isinstance(new_value,int):
self.__price = new_value
@price.deleter
def price(self):
del self.__price
apple = Goods('apple',5)
print(apple.price)
apple.price = 'ashkaksk'
del apple.price # 并不能真的删除什么,只是调用对应的被@price.deleter装饰的方法而已
print(apple.price)