标签:cat ror keep 不能 迭代器 method 传参数 三种方式 没有
#继承语法 class 子类名(父类名):pass
class A:
pass
class B(A):
pass
# A 父类 基类 超类
# B子类 派生类
子类可以使用父类中的 : 方法和静态变量
class Animal:
def __init__(self,name):
self.name = name
def eat(self):
print('%s is eating'%self.name)
def drink(self):
print('%s is drinking'%self.name)
def sleep(self):
print('%s is sleeping'%self.name)
class Cat(Animal):
def climb_tree(self):
print('%s is climbing'%self.name)
class Dog(Animal):
def house_keep(self):
print('%s house keeping'%self.name)
小白 = Cat('小白')
# 先开辟空间,空间里有一个类指针-->指向Cat
# 调用init,对象在自己的空间中找init没找到,到Cat类中找init也没找到,
# 找父类Animal中的init
小白.eat()#小白 is eating
小白.climb_tree()#小白 is climbing
小黑 = Dog('小黑')
小黑.eat()#小黑 is eating
当子类和父类的方法重名的时候,我们只使用子类的方法,而不会去调用父类的方法了
class Animal:
def __init__(self,name):
self.name = name
def eat(self):
print('%s is eating'%self.name)
def drink(self):
print('%s is drinking'%self.name)
def sleep(self):
print('%s is sleeping'%self.name)
class Cat(Animal):
def eat(self):
print('%s吃猫粮'%self.name)
def climb_tree(self):
print('%s is climbing'%self.name)
小白 = Cat('小白')
小白.eat()#小白吃猫粮
子类想要调用父类的方法的同时还想执行自己的同名方法
在子类的方法中调用父类的方法 :父类名.方法名(self)
class Animal:
def __init__(self,name,food):
self.name = name
self.food = food
self.blood = 100
self.waise = 100
def eat(self):
print('%s is eating %s'%(self.name,self.food))
def drink(self):
print('%s is drinking'%self.name)
def sleep(self):
print('%s is sleeping'%self.name)
class Cat(Animal):
def eat(self):
self.blood += 100
Animal.eat(self)
def climb_tree(self):
print('%s is climbing'%self.name)
self.drink()
class Dog(Animal):
def eat(self):
self.waise += 100
Animal.eat(self)
def house_keep(self):
print('%s is keeping the house'%self.name)
小白 = Cat('小白','猫粮')
小黑 = Dog('小黑','狗粮')
小白.eat()#小白 is eating 猫粮
小黑.eat()#小黑 is eating 狗粮
print(小白.__dict__)#{'name': '小白', 'food': '猫粮', 'blood': 200, 'waise': 100}
print(小黑.__dict__)#{'name': '小黑', 'food': '狗粮', 'blood': 100, 'waise': 200}
#父类和子类方法的选择:
# 子类的对象,如果去调用方法
# 永远优先调用自己的
# 如果自己有 用自己的
# 自己没有 用父类的
# 如果自己有 还想用父类的 : 直接在子类方法中调父类的方法 父类名.方法名(self)
单继承
# 单继承
# 调子类的 : 子类自己有的时候
# 调父类的 : 子类自己没有的时候
# 调子类和父类的 :子类父类都有,在子类中调用父类的
class D:
def func(self):
print('in D')
class C(D):pass
class A(C):
def func(self):
print('in A')
class B(A):pass
B().func()
多继承
# 多继承
# 一个类有多个父类,在调用父类方法的时候,按照继承顺序,先继承的就先寻找
class D:
def func(self):
print('in D')
class C(D):pass
class A(C):
def func(self):
print('in A')
class B(A):pass
B().func()
所有在python3当中的类都是继承object类的
class A:pass
print(A.__bases__)#(<class 'object'>,)
class C:pass
class B(A,C):pass
print(B.__bases__)#(<class '__main__.A'>, <class '__main__.C'>)只能找到父类 不能找到父类的父类
from types import FunctionType,MethodType
# FunctionType : 函数
# MethodType : 方法
class A:
def func(self):
print('in func')
print(A.func) # 函数 #<function A.func at 0x000002841C479488>
a = A()
print(a.func) # 方法 #<bound method A.func of <__main__.A object at 0x000002841C308240>>
print(isinstance(a.func,FunctionType))#False
print(isinstance(a.func,MethodType))#True
print(isinstance(A.func,FunctionType))#True
print(isinstance(A.func,MethodType))#False
#类.func是函数
#对象.func是方法
pickel 可以序列化对象
前提py文件里有对象的类
class Course:
def __init__(self,name,period,price):
self.name = name
self.period = period
self.price = price
python = Course('python','6 moneth',21800)
linux = Course('linux','5 moneth',19800)
go = Course('go','4 moneth',12800)
import pickle
with open('pickle_file','ab') as f:
pickle.dump(linux,f)
pickle.dump(go,f)
with open('pickle_file','rb') as f:
while True:
try:
obj = pickle.load(f)
print(obj.name,obj.period)
except EOFError:
break
多继承
在python3中 所有的类都继承object类,都是新式类
在python2中 不继承object的类都是经典类,继承object类的就是新式类了
经典类:在py3中不存是,在py2中不主动继承object的类
在py2中
class A:pass #经典类
class B(object):pass#新式类
在py3中
class A: #pass #新式类
class B(object):pass #新式类
在单继承方面(无论是新式类还是经典类都是一样的)
class A:
def func(self):pass
class B(A):
def func(self):pass
class C(B):
def func(self):pass
class D(c):
def func(self):pass
d = D()
寻找某一个方法的顺序:D->C->B->A
越往父类走,是深度
多继承
class A:
def func(self):
print('A')
class B(A):
def func(self):
print('B')
class C(A):
def func(Self):
print(C)
class D(B,C):
def func(self):
print('B')
print(D.mro()) #只在新式类中有,经典类没有
d = D()
d.func()
在走到一个点,下一个点既可以深度走,也可以从广度走的时候,总是先走广度,再走深度,广度优先
在经典类总,都是深度优先,总是在一条路走不通之后再换一条路,走过的点不会再走了
算法内容:
在python3中不需要传参数,自动就帮我们寻找当前类的mro顺序的下一个类中的同名方法
在python2中的新式类中,需要我们主动传递参数 super(子类的名字和子类的对象).函数名(),这样才能够帮我们调用到这个子类的mre顺序的下一个类中的方法
在python2中的经典类中,并不支持使用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()
print('D')
D().func()
'''
A
C
B
D
'''
其中 super().func() 也可以写成 super(D,self).func() 。
在单继承的程序中,super就是找父类:
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
'''
解析:中间的# 的三种方式功能都是找到并执行父类中的__init__的方法,推荐使用
super().__init__(name)。
'''
先找每个类的继承关系(注意因为加载顺序的缘故从,上至下开始寻找)
A(0) = [AO] # A 继承于object类
B(A) = [BAO] # B继承于A类
C(A) = [CAO] # C继承于A类
D(B) = [DBAO] # D继承于B类
E(C) = [ECAO] # E继承于C类
那么算法为:
F(D,E) = merge(D(B)+E(C))
? = [F] + [DBAO] + [ECAO]
F = [DBAO] + [ECAO]
FD = [BAO] + [ECAO]
FDB = [AO] + [ECAO]
FDBE = [AO] + [CAO]
FDBEC = [AO] + [AO]
FDBECAO
- **使用子类名.mro() 查看继承顺序**
只有新式类中有,经典类没有的。
父类对子类的约束
普通类 如 class A B C等等
抽象类
引入:例:不同付款方式付款
class Wechat():
def __init__(self,name):
self.name = name
def pay(self,money):
print('%s通过微信支付%s钱成功'%(self.name,money))
class Alipay():
def __init__(self,name):
self.name = name
def pay(self,money):
print('%s通过微信支付%s钱成功'%(self.name,money))
class Apple(Payment):
def __init__(self,name):
self.name = name
def pay(self,money):
dic = {'name': self.name, 'number': money}
# 想办法调用苹果支付 url连接 把dic传过去
print('%s通过苹果支付%s钱成功' % (self.name, money))
aw = WeChat('alex')
aw.pay(400)
aa = Alipay('alex')
aa.pay(400)
'''
这样我们通过创建了2个对象,然后调用类中的方法pay,把钱传入完成支付的功能
'''
当然我们有时需要归一化设计:
def pay(name,price,kind):
if kind == 'Wechat':
obj = WeChat(name)
elif kind == 'Alipay':
obj = Alipay(name)
elif kind == 'Apple':
obj = Apple(name)
obj.pay(price)
pay('alex',400,'Wechat')
pay('alex',400,'Alipay')
pay('alex',400,'Apple')
'''
我们通过定义一个函数,通过判别传入的kind参数,选择创建实例化name对象,然后调用方法,完成付款。
'''
注意:完成上述需求需要三个类中的pay的方法名一样如果不一样就会报错。
为解决上述问题引入了抽象类对子类进行相关的约束
class Payment:
def pay(self,money):
raise NotImplementedError('请在子类中重写同名pay方法')
class Alipay(Payment):pass
class WeChat(Payment):pass
class Apple(Payment): pass
def pay(name,price,kind):
if kind == 'Wechat':
obj = WeChat(name)
elif kind == 'Alipay':
obj = Alipay(name)
elif kind == 'Apple':
obj = Apple(name)
obj.pay(price)
'''
解析:我们创建一个所有类的父类,定义一个pay的方法,如果执行,则抛出异常。
当我们执行pay函数时,我们会调用方法 pay ,当对象中没有pay的方法时,就会去父类Payment中调用,所以抛出异常。所以加入抽象类约束我们子类中方法名称一致。
'''
# 另一种方式:依赖于abc 模块
from abc import ABCMeta,abstractmethod
class Payment(metaclass=ABCMeta):
@abstractmethod
def pay(self,money):
'''只要你见到了项目中有这种类,你要知道你的子类中必须实现和pay同名的方法'''
raise NotImplementedError('请在子类中重写同名pay方法')
# 一旦子类中没有pay方法,实例化都无法完成。
方式特点:约束力强。缺点:依赖于abc模块
多态
python中处处是多态,一切皆对象
什么是多态,借助java讲解
一个类型表现出来的多种状态
在Java中:一个参数必须指定类型,所以如果想让俩个类型的对象都可以传,那么必须让这俩个类继承自一个父类,再指定类型的时候使用父类来指定
鸭子类型
class list:
def __len__(self):pass
class dict:
def __len__(self): pass
class set:
def __len__(self): pass
class tuple:
def __len__(self): pass
class str:
def __len__(self): pass
def len(obj):
return obj.__len__()
# 如上述所有实现了__len__方法的类,在调用len函数的时候,obj都说是鸭子类型。
# 再如:迭代器协议 __iter__ __next__ 是迭代器。即所有的迭代器都是鸭子类型
标签:cat ror keep 不能 迭代器 method 传参数 三种方式 没有
原文地址:https://www.cnblogs.com/lianzibing/p/10993648.html