请选择 进入手机版 | 继续访问电脑版
搜索
房产
装修
汽车
婚嫁
健康
理财
旅游
美食
跳蚤
二手房
租房
招聘
二手车
教育
茶座
我要买房
买东西
装修家居
交友
职场
生活
网购
亲子
情感
龙城车友
找美食
谈婚论嫁
美女
兴趣
八卦
宠物
手机

03-深入类和对象

[复制链接]
查看: 7|回复: 0

1万

主题

2万

帖子

5万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
52015
发表于 2019-12-3 00:19 | 显示全部楼层 |阅读模式
一、深入类和工具

1.1、鸭子典范和多态
维基百科中的表白为:
  鸭子典范(英语:duck typing)在步伐计划中是静态典范的一种气概。在这类气概中,一个工具有用的语义,不是由继续自特定的类或实现特定的接口,而是由"当前方法和属性的聚集"决议。这个概念的名字根源于由詹姆斯·惠特科姆·莱利提出的鸭子测试,“鸭子测试”可以这样表述:
  “当看到一只鸟走起来像鸭子、泅水起来像鸭子、叫起来也像鸭子,那末这只鸟便可以被称为鸭子。”在鸭子典范中,关注点在于工具的活动,能作什么;而不是关注工具所属的典范。
  1. class Cat():    def say(self):        print("I am a cat")class Dog():    def say(self):        print("I am a dog")class Duck():    def say(self):        print("I am a duck")animal_list = [Cat,Dog,Duck]for animal in animal_list:    animal().say()#实例化工具,在挪用say方式  三个类实现同一个方式名,这就是多态。然后可以将这些类归为一种典范(鸭子典范)                  #python中的魔法函数充实也操纵了鸭子典范的特征,可以在任一类中界说name_list = ["list1","list2"]name_list1 = ["love","python"]name_tuple = (3,4)name_set = set()name_set.add(5)name_set.add(6)name_list.extend(name_set)   #参数name_set:['list1', 'list2', 5, 6]参数name_tuple:['list1', 'list2', 3, 4] print(name_list)              # 参数:name_list1:['list1', 'list2', 'love', 'python']"""这里说的是只要传入的参数是一个可迭代的典范便可以,就连我们自界说的类将类的魔法函数__getitem__(返回 )、__iter__便可以酿成可迭代的,都可以传入 def extend(self, *args, **kwargs): # real signature unknown        Extend list by appending elements from the iterable.         pass"""#首先这三个类里面都包含了这个say()方式,假如在JAVA里边,要实现多态的话,必要继续父类在覆盖父类的方式实现多态。# 例如:一样平常情况先界说一个父类Animal,然后这个Animal有一个say()方式。# 然后在写其他类例如上面的Cat类,Cat类继续Animal类,然后重写say()方式。# 然后指定典范实例化这个Cat工具,在python中不必要指定典范,在JAVA中(静态说话)必须指定典范,#这是静态说话和静态说话最大的区分。在python中都要做的一件事就是每个工具下都要写这个say()方式
复制代码
1.2、笼统基类(abc)
  python里边的笼统基类,是不成以大要实例化的。python是静态说话,静态说话是没有变量的典范的。在python中变量只是一个标记而已,这个标记可以指向任何典范的工具。静态说话缺少编译时检查毛病的情况,在python中编写代码是很难发现毛病的,只要要运转表白器才华找到毛病。这也是静态说话共有的一个缺点。python信仰的是鸭子典范,鸭子典范贯串于全部面向工具当中。笼统基类是什么意义?在这个底子的类傍边,设定好一些方式,然后全数的继续这个基类的类,都必须覆盖这个笼统基类里面的方式。笼统基类是没法实例化的。
  1. ##################去检查某个类能否有某种方式#############################class Students(object):    def __init__(self,student_list):        self.student = student_list    def __len__(self):        return len(self.student)students = Students(["lishuntao","test","python"])# print(hasattr(students,"__len__"))#True# print(hasattr(students,"__getitem__"))#False##############################判定某个工具的典范#####################################from collections.abc import Sizedprint(isinstance(students,Sized))#True######################操纵笼统基类实现接口的 逼迫规定###########################逼迫某些子类必须实现某些方式#实现了一个web框架,集成cache(redis,cache,memorychache)#必要计齐截个笼统基类,指定子类必须实现某些方式#怎样去模仿一个笼统基类呢?class  CacheBase():    def get(self,key):        raise NotImplementedError    def set(self,key,value):        raise NotImplementedError#用户在实现这个笼统基类的子类时候,必须实现这里面的两个方式class RedisCache(CacheBase):    passredis = RedisCache()#redis.get("key")#抛出很是raise NotImplementedError NotImplementedError#但这样做欠好,我们必要刚初始化的时候就抛出很是,接下来就换成abc实现小我基类import abcclass Cache1Base(metaclass=abc.ABCMeta):    @abc.abstractmethod    def get(self,key):        pass    @abc.abstractmethod    def set(self,key,value):        passclass RedisCache1(Cache1Base):    passredis_cache1 = RedisCache1() #TypeError: Can't instantiate abstract class RedisCache1 with abstract methods get, set#操纵笼统基类间接初始化抛出很是#在python傍边已经实现了一些通用的笼统基类,放在from collections.abc import *
复制代码
  笼统基类不是用来继续的,它只是操纵笼统基类来明白继续之间的关系,以及接口的界说,我们去操纵的时候必定要用我们的鸭子典范,假如必定要用接口的话,那末举荐操纵mixin多继续的方式去实现它。笼统基类操纵的时候计划过度,反而不轻易明白它。
1.3、isinstance和type的区分
  1. class A:    passclass B(A):    passb = B()print(isinstance(b,B)) #Trueprint(isinstance(b,A)) #Trueprint(type(b) is B) #True   is与==的区分,==判定值能否相当,is判定能否是同一个工具(id(b)地址能否一样)print(type(b),A) #False  ###########判定典范:为什么更举荐用isinstance而不是type?###############由于假如判定某个工具的典范的话,用isinstance会按照树的外形去搜索,从叶子搜索到跟便可以判定能否是类似典范,#就算是不同工具大如果类似典范,但是type是同种典范,但不同工具。
复制代码
1.4、类变量和实例变量
  1. class A:    a = 1 #a是类变量    def __init__(self,x,y):#self是类的实例 x与y已经绑定到实例上的属性上了        self.x = x        self.y = ynum = A(2,3)# A.a = 11   #假如点窜类属性,那末实例的值也会随着变# num.a = 100  #假如点窜实例属性,那末类属性的值安定,# 会在工具中新建一个实例属性的值,根究的时候间接工具属性中根究。print(num.x,num.y,num.a) #2 3 1  为什么实例num可以大要找到A的类属性呢,# 首先实例num先在实例属性种根究,假如没有找到的话就会向上根究,找到类属性print(A.a) # 1 类属性print(A.x)#AttributeError: type object 'A' has no attribute 'x'#类找实例属性找不到是由于类首先到自己的属性中找,假如没有找到的话,就不会向下根究
复制代码
1.5、类和实例属性的查找次第----mro查找
类查找属性的查找次第有深度优先查找广度优先查找
广度优先查找:
  1. #python3今后称为新式类,全数都继续objectclass D:    passclass C(D):    passclass B(D):    passclass A(B,C):    passprint(A.__mro__) #(, , , , )#__mro__魔法方式间接表示出类查找属性的次第
复制代码
03-深入类和对象  游戏 1751021-20191201172532888-1843663754


深度优先查找:
  1. #python3今后称为新式类,全数都继续objectclass E:    passclass D:    passclass C(E):    passclass B(D):    passclass A(B,C):    passprint(A.__mro__)#(, , , , , )
复制代码
03-深入类和对象  游戏 1751021-20191201173520239-819092496


  但在python3中为了制止深度优先算法与广度优先算法紊乱,出现了C3算法制止了两种算法出现的题目,例如菱形搜索利用深度优先算法,从AB再到D找到方式,大要C中重写了D的方式,是以深度优先算法不能治理菱形搜索的情况,但是C3算法治理了以上出现的两种情况。
1.6、类方式、静态方式和实例方式
[code]class Date:    def __init__(self,year,month,day):        self.year = year        self.month = month        self.day = day    #静态方式的弱点就是硬编码,假如换类名又要重新改返回的类名    @staticmethod    def parse_from_string(date_str):        year,month,day = tuple(date_str.split("-"))        return Date(int(year),int(month),int(day))    #为啥不用classmethod更换staticmethod呢?    #检查时候格式能否正确,不必要工具返回归来,是以这个时候它就有用了,而此外都是要将工具返回归来    @staticmethod    def valid_str(date_str):        year, month, day = tuple(date_str.split("-"))        if int(year)>0 and (int(month)>0 and int(month)
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Copyright © 2006-2014 妈妈网-中国妈妈第一,是怀孕、育儿、健康等知识交流传播首选平台 版权所有 法律顾问:高律师 客服电话:0791-88289918
技术支持:迪恩网络科技公司  Powered by Discuz! X3.2
快速回复 返回顶部 返回列表