互连网编制程序,多态与多态性

By admin in 4858.com on 2019年4月12日

壹.
怎样是多态

面向对象学习目录

python进阶(6):多态,封装,python进阶

明日说了面向对象叁大特点的接轨,今日来说多态和包装,很多任何程序员说python不支持多态未有多态,并不是python未有多态,而是python随处皆多态。前些天的任课重点会放在封装。

 

一、多态

1、多态

多态指的是1类东西有三种模样

水有多种形态:冰 水雾 水

动物有各个造型:人,狗,猪

4858.com 1

import abc
class Animal(metaclass=abc.ABCMeta): #同一类事物:动物
    @abc.abstractmethod
    def talk(self):
        pass

class People(Animal): #动物的形态之一:人
    def talk(self):
        print('say hello')

class Dog(Animal): #动物的形态之二:狗
    def talk(self):
        print('say wangwang')

class Pig(Animal): #动物的形态之三:猪
    def talk(self):
        print('say aoao')

多态

文件有三种样子:文本文件,可执行文件

4858.com 2

import abc
class File(metaclass=abc.ABCMeta): #同一类事物:文件
    @abc.abstractmethod
    def click(self):
        pass

class Text(File): #文件的形态之一:文本文件
    def click(self):
        print('open file')

class ExeFile(File): #文件的形态之二:可执行文件
    def click(self):
        print('execute file')

文件

4858.com ,2、多态性

多态性是指在不记挂实例类型的事态下使用实例

在面向对象方法中貌似是如此表述多态性:

向分裂的靶子发送同一条新闻,不一样的对象在接收时会产生不一致的作为(即方法)。也等于说,每一个对象能够用本身的法子去响应共同的新闻。所谓音信,正是调用函数,分歧的一言一动正是指差异的完成,即实行不壹的函数。

诸如:老师.下课铃响了(),学生.下课铃响了(),老师执行的是下班操作,学生实施的是放学操作,即使双方信息一点差异也未有于,可是举行的职能分化

4858.com 3

peo=People()
dog=Dog()
pig=Pig()

#peo、dog、pig都是动物,只要是动物肯定有talk方法
#于是我们可以不用考虑它们三者的具体是什么类型,而直接使用
peo.talk()
dog.talk()
pig.talk()

#更进一步,我们可以定义一个统一的接口来使用
def func(obj):
    obj.talk()

多态性

三、鸭子类型

Python崇尚鸭子类型,即‘如若看起来像、叫声音图像而且走起路来像鸭子,那么它就是鸭子’python程序员平常依据那种作为来编写程序。例如,假诺想编写现有对象的自定义版本,可以三番五次该对象也能够制造1个外观和作为像,但与它无别的关联的崭新对象,后者平常用于保存程序组件的松耦合度。

例一:利用标准库中定义的各个‘与公事类似’的靶子,纵然这个目的的行事方法像文件,但她们从未继续内置文件对象的方法

例二:体系类型有三种样子:字符串,列表,元组,但他俩一贯未有直接的继续关系

4858.com 4例子


 

二、封装

互连网编制程序,多态与多态性。卷入:隐藏对象的品质和促成细节,仅对外提供公共访问方式。

好处:

一、 将转变隔绝; 

二.、便于使用;

三.、升高复用性; 

四.、进步安全性;

装进原则:

一、 将不需求对外提供的内容都藏匿起来;

二、 把质量都隐藏,提供公共措施对其访问。

壹、私有变量

4858.com 5

#其实这仅仅这是一种变形操作
#类中所有双下划线开头的名称如__x都会自动变形成:_类名__x的形式:

class A:
    __N=0 #类的数据属性就应该是共享的,但是语法上是可以把类的数据属性设置成私有的如__N,会变形为_A__N
    def __init__(self):
        self.__X=10 #变形为self._A__X
    def __foo(self): #变形为_A__foo
        print('from A')
    def bar(self):
        self.__foo() #只有在类内部才可以通过__foo的形式访问到.

#A._A__N是可以访问到的,即这种操作并不是严格意义上的限制外部访问,仅仅只是一种语法意义上的变形

民用变量

特点:

一、类中定义的__x只幸好在那之中接纳,如self.__x,引用的便是变形的结果。

贰、那种变形其实正是针对外部的变形,在外部是心有余而力不足透过__x那个名字访问到的。

三、在子类定义的__x不会覆盖在父类定义的__x,因为子类中变形成了:_子类名__x,而父类中变形成了:_父类名__x,即双下滑线开始的习性在持续给子类时,子类是无能为力覆盖的。

注意:

那种体制也并不曾真正意义上限定大家从外表直接访问属性,知道了类名和属性名就能够拼闻名字:_类名__天性,然后就足以访问了,如a._A__N

二、私有方法

在持续中,父类要是不想让子类覆盖自个儿的方式,能够将艺术定义为私有的

 

4858.com 6

#正常情况
class A:
    def fa(self):
         print('from A')
    def test(self):
        self.fa()

class B(A):
     def fa(self):
         print('from B')

b=B()
b.test()
#from B


#把fa定义成私有的,即__fa
class A:
     def __fa(self): #在定义时就变形为_A__fa
         print('from A')
     def test(self):
         self.__fa() #只会与自己所在的类为准,即调用_A__fa

class B(A):
     def __fa(self): #在定义时就变形为_B__fa
         print('from B')

b=B()
b.test()
#from A

民用方法

 

3、扩展性

封装在于分明区分内外,使得类实现者能够修改封装内的事物而不影响外部调用者的代码;而外部使用用者只略知1二1个接口(函数),只要接口(函数)名、参数不变,使用者的代码永远无需变更。

4858.com 7

#类的设计者
class Room:
    def __init__(self,name,owner,width,length,high):
        self.name=name
        self.owner=owner
        self.__width=width
        self.__length=length
        self.__high=high
    def tell_area(self): #对外提供的接口,隐藏了内部的实现细节,此时我们想求的是面积
        return self.__width * self.__length


#使用者
r1=Room('卧室','egon',20,20,20)
r1.tell_area() #使用者调用接口tell_area


#类的设计者,轻松的扩展了功能,而类的使用者完全不需要改变自己的代码
class Room:
    def __init__(self,name,owner,width,length,high):
        self.name=name
        self.owner=owner
        self.__width=width
        self.__length=length
        self.__high=high
    def tell_area(self): #对外提供的接口,隐藏内部实现,此时我们想求的是体积,内部逻辑变了,只需求修该下列一行就可以很简答的实现,而且外部调用感知不到,仍然使用该方法,但是功能已经变了
        return self.__width * self.__length * self.__high


#对于仍然在使用tell_area接口的人来说,根本无需改动自己的代码,就可以用上新功能
 r1.tell_area()

扩展性

4、property属性

4858.com 8

'''
例一:BMI指数(bmi是计算而来的,但很明显它听起来像是一个属性而非方法,如果我们将其做成一个属性,更便于理解)

成人的BMI数值:
过轻:低于18.5
正常:18.5-23.9
过重:24-27
肥胖:28-32
非常肥胖, 高于32
  体质指数(BMI)=体重(kg)÷身高^2(m)
  EX:70kg÷(1.75×1.75)=22.86
'''
class People:
    def __init__(self,name,weight,height):
        self.name=name
        self.weight=weight
        self.height=height
    @property
    def bmi(self):
        return self.weight / (self.height**2)

p1=People('egon',75,1.85)
print(p1.bmi)

BMI指数
4858.com 9

import math
class Circle:
    def __init__(self,radius): #圆的半径radius
        self.radius=radius

    @property
    def area(self):
        return math.pi * self.radius**2 #计算面积

    @property
    def perimeter(self):
        return 2*math.pi*self.radius #计算周长

c=Circle(10)
print(c.radius)
print(c.area) #可以像访问数据属性一样去访问area,会触发一个函数的执行,动态计算出一个值
print(c.perimeter) #同上
'''
输出结果:
314.1592653589793
62.83185307179586
'''
#注意:此时的特性area和perimeter不能被赋值
c.area=3 #为特性area赋值
'''
抛出异常:
AttributeError: can't set attribute
'''

圆的周长和面积

将一个类的函数定义成特征未来,对象再去选拔的时候obj.name,根本不能够察觉自个儿的name是执行了一个函数然后总括出来的,那种特点的行使办法遵从了联合访问的规则

。。。

(剩余后天三番五次立异)

 

 

 

 

 

昨日说了面向对象三大特色的持续,后天的话多态和包裹,很多任何程序员说python不帮衬多态未有…

壹 接口与归1化设计

    多态指的是相同种/类东西的差别造型

壹 面向对象介绍

一.一 归一化概念:

  归一化的裨益:

  ①.归1化让使用者无需关怀对象的类是何许,只供给驾驭那几个指标都具备有些意义就足以了,那十分的大下跌了使用者的使用难度。

  2.归壹化使得高层的表面使用者能够不加区分的拍卖全部接口包容的指标集合

 

  继承的三种用途

  1:继承基类的情势,并且做出本身改变如故扩充(代码重用):实践中,继承的那种用途意义并不十分的大,甚至不时是损害的。因为它使得子类与基类出现强耦合。

  贰:注明某些子类包容于某基类,定义三个接口类(模仿java的Interface),接口类中定义了某个接口名(就是函数名)且从未完成接口的意义,子类继承接口类,并且达成接口中的效能

4858.com 10

class Interface:
    '''
    定义接口Interface类来模仿接口的概念,
    python中压根就没有interface关键字来定义一个接口。
    '''
    def read(self): # 定接口函数read
        pass

    def write(self): # 定义接口函数write
        pass

class Txt(Interface): # 文本,具体实现read和write
    def read(self):
        print('文本数据的读取方法')

    def write(self):
        print('文本数据的读取方法')

class Sata(Interface): #磁盘,具体实现read和write
    def read(self):
        print('硬盘数据的读取方法')

    def write(self):
        print('硬盘数据的读取方法')

class Process(Interface):
    def read(self):
        print('进程数据的读取方法')

    def write(self):
        print('进程数据的读取方法')

t = Txt()
s = Sata()
p = Process()

t.read()    # 运行结果:文本数据的读取方法
s.read()    # 运行结果:硬盘数据的读取方法
p.read()    # 运行结果:进程数据的读取方法

4858.com 11

 

2.为啥要用多态性

二类、实例、属性、方法详解

1.2 抽象类

  精晓知识点

  与java1样,python也有抽象类的定义可是同样须求依靠模块完成,抽象类是3个特殊的类,它的特殊之处在于只可以被持续,不能够被实例化

  借助abc模块,进行效仿抽象类

4858.com 12

import abc
class Interface(metaclass=abc.ABCMeta):
    '''
    定义接口Interface类来模仿接口的概念,
    python中压根就没有interface关键字来定义一个接口。
    '''
    @abc.abstractmethod
    def read(self): # 定接口函数read
        pass
    @abc.abstractmethod
    def write(self): # 定义接口函数write
        pass

class Txt(Interface): # 文本,具体实现read和write
    def read(self):
        pass

    def write(self):
        pass

t = Txt()

4858.com 13

 

  一增加了程序的布帆无恙

叁面向进度与面向对象进一步比较

1.3 多态

  面向对象的多态、多态性

  多态:指的是如出一辙种东西的各个模样

  动物有二种样子:人、狗、猪

4858.com 14

# 多态:同一种事物的多种形态
class Animal: # 同一类事物:动物
    def talk(self):
        pass

class People(Animal): # 动物的形态之一:人
    def talk(self):
        print('say hello')

class Dog(Animal): # 动物的形态之二:狗
    def talk(self):
        print('say wangwang')

p=People()
d=Dog()
p.talk()
d.talk()

4858.com 15

 

  二扩充了程序的可扩大性

四 类与对象

1.4 多态性

  多态性:能够在不缅怀实例类型的前提下利用实例

4858.com 16

# 多态:同一种事物的多种形态
class Animal: # 同一类事物:动物
    def talk(self):
        pass

class People(Animal): # 动物的形态之一:人
    def talk(self):
        print('say hello')

class Dog(Animal): # 动物的形态之二:狗
    def talk(self):
        print('say wangwang')

# 多态性:可以在不考虑实例类型的前提下使用实例
p=People()
d=Dog()

def Talk(animal):
    animal.talk()

Talk(p)
Talk(d)

4858.com 17

 

多态性:分为静态多态性和动态多态性

五属性查找与绑定方法

一.伍 多态性的利益

  多态性的裨益:

  1.扩充了程序的油滑

  二.日增了程序可扩大性

 

    多态性:在多态的背景下,能够在并非怀念对象实际项目标前提下而平素利用对象

6 小结

一.陆 鸭子类型

  Python崇尚鸭子类型,即‘如若看起来像、叫声音图像而且走起路来像鸭子,那么它就是鸭子’

  python程序员平时依照那种作为来编写程序。例如,借使想编写现有对象的自定义版本,能够继续该对象

  也可以创立一个外观和行为像,但与它无其余关联的全新对象,后者平日用于保存程序组件的松耦合度。

  利用标准库中定义的各个‘与公事类似’的目的,即便这么些目标的干活办法像文件,但她俩不曾继续内置文件对象的艺术

4858.com 18

# 二者都像鸭子,二者看起来都像文件,因而就可以当文件一样去用
class TxtFile:
    def read(self):
        pass

    def write(self):
        pass

class DiskFile:
    def read(self):
        pass
    def write(self):
        pass

4858.com 19

 

    多态性的卓绝:统1

7 继承与派生

2 封装

3.
什么样用多态

8 组合

2.1 隐藏

  在python中用双下划线开首的秘诀将质量隐藏起来

4858.com 20

class Foo:
    __N = 1111 # _Foo__N
    def __init__(self,name):
        self.__Name=name # self._Foo__Name=name

    def __f1(self): # _Foo__f1
        print('f1')
    def f2(self):
        self.__f1() # self._Foo__f1()

f = Foo('egon')
# print(f.__N)   # 把数据类型隐藏起来了

# 这种隐藏需要注意的问题:
# 1:这种隐藏只是一种语法上变形操作,并不会将属性真正隐藏起来
print(Foo.__dict__)
print(f.__dict__)    # 运行结果:{'_Foo__Name': 'egon'}
print(f._Foo__Name)  # 运行结果:egon
print(f._Foo__N)     # 运行结果:1111

# 2:这种语法级别的变形,是在类定义阶段发生的,并且只在类定义阶段发生
Foo.__x = 123123
print(Foo.__dict__)  # 运行结果:...'__doc__': None, '__x': 123123}
print(Foo.__x)       # 运行结果:123123
f.__x = 123123123
print(f.__dict__)    # 运行结果:{'_Foo__Name': 'egon', '__x': 123123123}
print(f.__x)         # 运行结果:123123123

# 3:在子类定义的__x不会覆盖在父类定义的__x,因为子类中变形成了:_子类名__x,
# 而父类中变形成了:_父类名__x,即双下滑线开头的属性在继承给子类时,

# 子类是无法覆盖的。
class Foo:
    def __f1(self): # _Foo__f1
        print('Foo.f1')

    def f2(self):
        self.__f1() # self._Foo_f1

class Bar(Foo):
    def __f1(self): # _Bar__f1
        print('Bar.f1')

b = Bar()
b.f2()    # 运行结果:Foo.f1

4858.com 21

 

class Animal:
    def speak(self):
        pass
class People(Animal):
    def shuo(self):
        print('say hello')
class Dog(Animal):
    def jiao(self):
        print('汪汪汪')
class Pig(Animal):
    def chang(self):
        print('哼哼哼')
obj1=People()
obj2=Dog()
obj3=Pig()
# obj1.speak()
# obj2.speak()
# obj3.speak()
def speak(animal):
    animal.speak()
speak(obj1)
speak(obj2)
speak(obj3)

9 抽象类

二.二 封装数据属性

4858.com 22

# 封装不是单纯意义的隐藏
# 1:封装数据属性:将属性隐藏起来,然后对外提供访问属性的接口,
# 关键是我们在接口内定制一些控制逻辑从而严格控制使用对数据属性的使用
class People:
    def __init__(self,name,age):
        if not isinstance(name,str):
            raise TypeError('%s must be str' %name)
        if not isinstance(age,int):
            raise TypeError('%s must be int' %age)
        self.__Name=name
        self.__Age=age
    def tell_info(self):
        print('<名字:%s 年龄:%s>' %(self.__Name,self.__Age))

    def set_info(self,x,y):
        if not isinstance(x,str):
            raise TypeError('%s must be str' %x)
        if not isinstance(y,int):
            raise TypeError('%s must be int' %y)
        self.__Name=x
        self.__Age=y

p=People('egon',18)
p.tell_info()       # 运行结果:<名字:egon 年龄:18>

p.set_info('Egon',19)
p.tell_info()       # 运行结果:<名字:egon 年龄:19>

4858.com 23

 

python 崇尚鸭子类型

10 多态

二.三 封装函数属性

  封装函数属性的目标:隔开复杂度

4858.com 24

# 2:封装函数属性:为了隔离复杂度
# 取款是功能,而这个功能有很多功能组成:插卡、密码认证、输入金额、打印账单、取钱
# 对使用者来说,只需要知道取款这个功能即可,其余功能我们都可以隐藏起来,很明显这么做
# 隔离了复杂度,同时也提升了安全性

class ATM:
    def __card(self):
        print('插卡')
    def __auth(self):
        print('用户认证')
    def __input(self):
        print('输入取款金额')
    def __print_bill(self):
        print('打印账单')
    def __take_money(self):
        print('取款')

    def withdraw(self):
        self.__card()
        self.__auth()
        self.__input()
        self.__print_bill()
        self.__take_money()

a = ATM()
a.withdraw()
# 运行结果:
#       插卡
#       用户认证
#       输入取款金额
#       打印账单
#       取款

4858.com 25

 

逗比整日:

11 封装

二.四 静态属性

4858.com 26

class Foo:
    @property
    def f1(self):
         print('Foo.f1')

f = Foo()
f.f1        # 运行结果:Foo.f1

4858.com 27

  示例:计算BMI指数

4858.com 28

'''
例:BMI指数(bmi是计算而来的,但很明显它听起来像是一个属性而非方法,
如果我们将其做成一个属性,更便于理解)
成人的BMI数值:
过轻:低于18.5
正常:18.5-23.9
过重:24-27
肥胖:28-32
非常肥胖, 高于32
  体质指数(BMI)=体重(kg)÷身高^2(m)
  EX:70kg÷(1.75×1.75)=22.86
'''
class People:
    def __init__(self,name,weight,height):
        self.name=name
        self.weight=weight
        self.height=height
    @property
    def bmi(self):
        return self.weight / (self.height**2)

p=People('jack',75,1.80)
p.height=1.86
print(p.bmi)

4858.com 29

 

  Python崇尚鸭子类型,即‘若是看起来像、叫声音图像而且走起路来像鸭子,那么它便是鸭子’

1贰绑定方法与非绑定方法

三 面向对象高级

python程序员平时依据这种行为来编写程序。例如,即使想编写现有对象的自定义版本,能够继承该目的

一三 内置方法(上)

3.1 反射

  通过字符串,反射到实际的质量上,找到真正的品质

4858.com 30

class Foo:
    x=1
    def __init__(self,name):
        self.name = name

    def f1(self):
        print('from f1')

print(Foo.x) # Foo.__dict__['x']

f = Foo('egon')
print(f.__dict__)

print(f.name)
print(f.__dict__['name'])

# hasattr
print(hasattr(f,'name'))    # f.name
print(hasattr(f,'f1'))      # f.f1
print(hasattr(f,'x'))       # f.x

# setattr
setattr(f,'age',18)         # f.age=18

# getattr
print(getattr(f,'name'))      # f.name
print(getattr(f,'abc',None))  # f.abc
print(getattr(f,'name',None)) # f.abc

func = getattr(f,'f1')  # f.f1
func()

# delattr
delattr(f,'name')    # del f.name
print(f.__dict__)

4858.com 31

 

也得以成立三个外观和作为像,但与它无别的涉及的崭新对象,后者平常用于保存程序组件的松耦合度。

14内置方法(中)之描述符

3.2 item系列

  Item系类,主要包罗:__getitem__、__setitem__、
__delitem__,通过这多少个item,能够像操作字典壹样,操作对象的属性。

4858.com 32

class Foo:
    def __getitem__(self, item):
        print('=====>get')
        return self.__dict__[item]

    def __setitem__(self, key, value):
        self.__dict__[key]=value
        # setattr(self,key,value)

    def __delitem__(self, key):
        self.__dict__.pop(key)

f = Foo()
f['name'] = "jack"   # 设置
print(f["name"])      # 取出属性
del f["name"]        # 删除
print(f.__dict__)

4858.com 33

 

例一:利用标准库中定义的各个‘与公事类似’的靶子,就算那些指标的办事情势像文件,但他俩一贯不继承内置文件对象的方法

一五 内置方法(下)

3.3 __str__

  通过__str__,打字与印刷对象新闻

4858.com 34

class People:
    def __init__(self,name,age,sex):
        self.name=name
        self.age=age
        self.sex=sex

    def __str__(self): # 在对象被打印时触发执行
        return '<name:%s age:%s sex:%s>' %(self.name,self.age,self.sex)

p=People('alex',38,'male')
print(p)    # 运行结果:<name:alex age:38 sex:male>

4858.com 35

 

4858.com 364858.com 37

16 元类

三.四 析构方法

  用法:清理1些能源,清理一些python解析器不能够清理的财富,例如:清理操作系统的能源,打开文件,向操作系统一发布起调用,关闭文件句柄资源

4858.com 38

class Foo:
    def __init__(self, name):
        self.name = name

    def __del__(self): # 在对象资源被释放时触发
        print('-----del------')

f = Foo("mary")
del f
print('对象被释放')

4858.com 39

 

class Disk:
    def read(self):
        print('Disk read')

    def write(self):
        print('Disk write')


class Memory:
    def read(self):
        print('Mem read')

    def write(self):
        print('Mem write')
obj1=Disk()
obj2=Memory()

obj1.read()
obj2.read()

4 异常

4858.com 40

# 逻辑错误
# TypeError
for i in 3:
    pass

# NameError
aaaaa

# ValueError
int('asdfsadf')

# IndexError
l=[1,2]
l[1000]

#KeyError
d = {'a':1}
d['b']

# AttributeError
class Foo:pass
Foo.x

4858.com 41

 

View Code

多态

  抽象类统一标准了部分相似类的貌似本性后,继承该抽象类的顺序子类的具体表现格局是足以多样各样的(具体表现为:多少属性的值各不同、函数属性的函数体各不同)

  多态指的是1类东西有八种造型,比如

  动物有各类样子:人,狗,猪

 1 import abc
 2 
 3 class Animal(metaclass=abc.ABCMeta): #同一类事物:动物
 4     @abc.abstractmethod
 5     def talk(self):
 6         pass
 7  
 8 class People(Animal): #动物的形态之一:人
 9     def talk(self):
10         print('say hello')
11  
12 class Dog(Animal): #动物的形态之二:狗
13     def talk(self):
14         print('say wangwang')
15  
16 class Pig(Animal): #动物的形态之三:猪
17     def talk(self):
18         print('say aoao')

 

文本有八种造型:文本文件,可执行文件

 1 import abc
 2 class File(metaclass=abc.ABCMeta): #同一类事物:文件
 3     @abc.abstractmethod
 4     def click(self):
 5         pass
 6  
 7 class Text(File): #文件的形态之一:文本文件
 8     def click(self):
 9         print('open file')
10  
11 class ExeFile(File): #文件的形态之二:可执行文件
12     def click(self):
13         print('execute file')

 

4.一 极度处理

  倘诺不当发生的标准化可预见的,大家须求用if举行拍卖,在错误发生以前开始展览预防

  假使不当爆发的基准时不足预感的,则须要用到try…except,在错误发生之后进展拍卖

4858.com 42

#基本语法为
try:
    # 被检测的代码块
except 异常类型:
    # try中一旦检测到异常,就执行这个位置的逻辑
# 示例
try:
    f=open('a.txt')
    g=(line.strip() for line in f)
    print(next(g))
    print(next(g))
except StopIteration:
    f.close()

4858.com 43

 

 

多态性

壹、什么是多态动态绑定(在持续的背景下采用时,有时也叫做多态性)

  多态性是指在不惦记实例类型的地方下选拔实例,多态性分为静态多态性和动态多态性

  静态多态性:如别的类型都得以用运算符+举办演算

  动态多态性:如下

 1 peo=People()
 2 dog=Dog()
 3 pig=Pig()
 4  
 5 #peo、dog、pig都是动物,只要是动物肯定有talk方法
 6 #于是我们可以不用考虑它们三者的具体是什么类型,而直接使用
 7 peo.talk()
 8 dog.talk()
 9 pig.talk()
10  
11 #更进一步,我们可以定义一个统一的接口来使用
12 def func(obj):
13     obj.talk()

故此,总计下抽象类与多态的涉及:

  先由抽象类统一定义那么些相似类的一般天性(包含数据属性和函数属性,当中分明各相似类必须定义那些函数属性概念的函数体能够各类形状),然后再将一般的函数属性用统1的接口归壹化调用(统1接口的底蕴是各子类都正式须求了概念那几个相似函数属性),从而完毕了“同1接口,多样造型”

 

二、为啥要用多态性(多态性的功利)

  其实大家从地方多态性的例子能够看出,大家并不曾增添哪些新的文化,也正是说python本身正是永葆多态性的,这么做的好处是哪些吗?

壹.扩充了程序的油滑

  以不变应万变,不论对象风云突变,使用者都是千篇1律种方式去调用,如func(animal)

二.扩大了程序额可扩充性

  
 通过继承animal类成立了二个新的类,使用者无需更改自身的代码,依然用func(animal)去调用

>>> class Cat(Animal): #属于动物的另外一种形态:猫... 
        def talk(self):
            ... 
            print('say miao')
            ...

>>> def func(animal): #对于使用者来说,自己的代码根本无需改动
        ... 
        animal.talk()
        ...

>>> cat1=Cat() #实例出一只猫
>>> func(cat1) #甚至连调用方式也无需改变,就能调用猫的talk功能
say miao

'''
这样我们新增了一个形态Cat,由Cat类产生的实例cat1,使用者可以在完全不需要修改自己代码的情况下。使用和人、狗、猪一样的方式调用cat1的talk方法,即func(cat1)
'''

 

肆.二 多分支相当

4858.com 44

try:
    aaaa
    print('====>1')
    l = []
    l[3]
    print('====>2')
    d = {}
    d['x']
    print('====>3')
except NameError as e:
    print(e)
except IndexError as e:
    print(e)
except KeyError as e:
    print(e)

4858.com 45

 

鸭子类型

逗比时刻:

      
 Python崇尚鸭子类型,即‘倘使看起来像、叫声音图像而且走起路来像鸭子,那么它正是鸭子’

      
 python程序员平常依据那种行为来编写程序。例如,若是想编写现有对象的自定义版本,能够连续该目的

      
 也足以成立三个外观和表现像,但与它无其余涉及的崭新对象,后者平常用于保存程序组件的松耦合度。

 

例1:使用标准库中定义的各样‘与公事类似’的靶子,即使那么些目的的工作措施像文件,但她俩未尝继承内置文件对象的不二秘诀

 1 #二者都像鸭子,二者看起来都像文件,因而就可以当文件一样去用
 2 class TxtFile:
 3     def read(self):
 4         pass
 5  
 6     def write(self):
 7         pass
 8  
 9 class DiskFile:
10     def read(self):
11         pass
12     def write(self):
13         pass

 

例2:队列类型有两种模样:字符串,列表,元组,但他们直接未有直接的后续关系

 1 #str,list,tuple都是序列类型
 2 s=str('hello')
 3 l=list([1,2,3])
 4 t=tuple((4,5,6))
 5  
 6 #我们可以在不考虑三者类型的前提下使用s,l,t
 7 s.__len__()
 8 l.__len__()
 9 t.__len__()
10  
11 len(s)
12 len(l)
13 len(t)

 

四.3 万能充足

4858.com 46

try:
    # aaaa
    print('====>1')
    l = []
    l[3]
    print('====>2')
except Exception as e:
    print(e)

4858.com 47

 

四.肆 基本构造

4858.com 48

try:
    aaaa
    print('====>1')
    l=[]
    l[3]
    print('====>2')
    d={}
    d['x']
    print('====>3')
except NameError as e:
    print(e)
except IndexError as e:
    print(e)
except KeyError as e:
    print(e)
except Exception as e:
    print(e)
else:
    print('在没有错误的时候执行')
finally:
    print('无论有无错误,都会执行')

4858.com 49

 

四.五 自定义相当

4858.com 50

class EgonException(BaseException):
    def __init__(self, msg):
        self.msg=msg
    def __str__(self):
        return '<%s>' %self.msg

raise EgonException('jack 的异常')

4858.com 51

 

5 Socket编程

  IP + 端口,标识唯十个软件、应用

  tcp是基于链接的,必须先运营服务端,然后再开发银行客户端去链接服务端

5.一 简单套接字

5.1.1 服务端

4858.com 52

import socket

# 买手机
phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 插卡
phone.bind(("127.0.0.1", 8080))

# 开机
phone.listen(5)

# 等待电话
print("server start...")
conn,client_addr = phone.accept()  # tcp链接,client_addr
print("链接", conn)
print(client_addr)

# 基于建立的链接,收发消息
client_data = conn.recv(1024)
print("客户端的消息", client_data)
conn.send(client_data.upper())

# 挂电话链接
conn.close()

# 关机
phone.close()

4858.com 53

 

5.1.2 客户端

4858.com 54

import socket
phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
phone.connect(("127.0.0.1", 8080))

phone.send("hello".encode("utf-8"))
server_data = phone.recv(1024)
print("服务端回应的消息", server_data)
phone.close() 

4858.com 55

 

5.贰 加上通讯循环

5.2.1 服务端

4858.com 56

import socket

phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
phone.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
phone.bind(("127.0.0.1", 8080))
phone.listen(5)
print("server start...")
conn,client_addr = phone.accept()

while True: # 通讯循环
    client_data = conn.recv(1024)
    print("客户端的消息", client_data)
    conn.send(client_data.upper())

conn.close()
phone.close()

4858.com 57

 

5.2.2 客户端

4858.com 58

import socket
phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
phone.connect(("127.0.0.1", 8080))

while True:
    msg = input(">>").strip()
    if not msg:continue
    phone.send(msg.encode("utf-8"))
    server_data = phone.recv(1024)
    print("server back:", server_data.decode("utf-8"))

phone.close()

4858.com 59

 

5.三 加上链接循环

5.3.1 服务端

4858.com 60

import socket

phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
phone.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
phone.bind(("127.0.0.1", 8080))
phone.listen(5)
print("server start...")

while True: # 链接循环
    conn,client_addr = phone.accept()
    while True: # 通讯循环
        try:
            client_data = conn.recv(1024)
            if not client_data:break # 针对linux系统
            conn.send(client_data.upper())
        except Exception: # 针对windows
            break
    conn.close()

phone.close()

4858.com 61

 

5.3.2 客户端

4858.com 62

import socket
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.connect(('127.0.0.1',8080))

while True:
    msg=input('>>: ').strip()
    if not msg:continue
    phone.send(msg.encode('utf-8'))
    server_data = phone.recv(1024)
    print(server_data.decode('utf-8'))

phone.close()

4858.com 63

 

五.四 模拟ssh远程执行命令

5.4.1 服务端

4858.com 64

import socket
import subprocess

phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
phone.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
phone.bind(("127.0.0.1", 8080))
phone.listen(5)
print("server start...")

while True: # 链接循环
    conn,client_addr = phone.accept()
    while True: # 通讯循环
        try:
            cmd = conn.recv(1024)
            if not cmd:break # 针对linux系统

            # 执行命令,拿到结果
            res = subprocess.Popen(cmd.decode("utf-8"),
                                   shell = True,
                                   stdout = subprocess.PIPE,
                                   stderr = subprocess.PIPE)
            stdout = res.stdout.read()
            stderr = res.stderr.read()
            conn.send(stdout+stderr)
        except Exception: # 针对windows
            break
    conn.close()

phone.close()

4858.com 65

 

5.4.2 客户端

4858.com 66

import socket
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.connect(('127.0.0.1',8080))

while True:
    cmd = input('>>').strip()
    if not cmd:continue
    # 发命令
    phone.send(cmd.encode('utf-8'))

    # 收命令的执行结果
    cmd_res = phone.recv(1024)

    # 打印结果
    print(cmd_res.decode('gbk'))

phone.close()

4858.com 67

 

5.5 粘包现象

  Tcp出现粘包现象,udp不会现出粘包;主假使tcp基于流式的,像水流壹样,未有起初,未有最终,络绎不绝,会发出粘包;udp,是数据报的,不会师世粘包。

5.5.1 服务端

4858.com 68

from socket import *
s = socket(AF_INET, SOCK_STREAM)
s.bind(("127.0.0.1", 8080))
s.listen(5)

conn,addr = s.accept()

# 收发消息
data1 = conn.recv(1024)
print("data1:", data1)

data2 = conn.recv(1024)
print("data2:", data2)

conn.close()
s.close()

4858.com 69

 

5.5.2 客户端

4858.com 70

from socket import *
c = socket(AF_INET, SOCK_STREAM)
c.connect(("127.0.0.1", 8080))

c.send("hello".encode("utf-8"))
c.send("world".encode("utf-8"))
c.close()

4858.com 71

 

伍.陆 ssh远程执行命令+定制报头

5.6.1 服务端

4858.com 72

import socket
import struct
import subprocess
phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
phone.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
phone.bind(("127.0.0.1", 8080))
phone.listen(5)
print("server start...")
while True: # 链接循环
    conn,client_addr = phone.accept()
    print(conn, client_addr)

    while True: # 通讯循环
        try:
            cmd = conn.recv(1024)
            if not cmd:break

            # 执行命令,拿到结果
            res = subprocess.Popen(cmd.decode("utf-8"),
                                   shell=True,
                                   stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE)
            stdout = res.stdout.read()
            stderr = res.stderr.read()

            # 制作报头
            header = struct.pack("i", len(stdout)+len(stderr))

            # 先发报头(固定长度)
            conn.send(header)
            # 再发真实数据
            conn.send(stdout)
            conn.send(stderr)
        except Exception: # 针对windows
            break
    conn.close()

phone.close()

4858.com 73

 

5.6.2 客户端

4858.com 74

import socket
import struct

phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
phone.connect(("127.0.0.1", 8080))

while True:
    cmd = input(">>").strip()
    if not cmd:continue
    # 发命令
    phone.send(cmd.encode("utf-8"))

    # 先收报头
    header = phone.recv(4)
    total_size = struct.unpack("i", header)[0]

    # 再收命令的执行结果
    recv_size = 0
    data = b""
    while recv_size < total_size:
        recv_data = phone.recv(1024)
        recv_size += len(recv_data)
        data += recv_data

    # 打印结果
    print(data.decode("gbk"))

phone.close()

4858.com 75

 

5.7 定制报头的没错方法

5.7.1 服务端

4858.com 76

import socket
import struct
import subprocess
import json
phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
phone.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
phone.bind(("127.0.0.1", 8080))
phone.listen(5)
print("server start...")
while True: # 链接循环
    conn,client_addr = phone.accept()
    print(conn, client_addr)

    while True: # 通讯循环
        try:
            cmd = conn.recv(1024)
            if not cmd:break

            # 执行命令,拿到结果
            res = subprocess.Popen(cmd.decode("utf-8"),
                                   shell=True,
                                   stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE)
            stdout = res.stdout.read()
            stderr = res.stderr.read()

            # 制作报头
            header_dic = {"total_size":len(stdout)+len(stderr), "md5":None}
            header_json = json.dumps(header_dic)
            header_bytes = header_json.encode("utf-8")

            # 1.先发报头的长度(固定4个bytes)
            conn.send(struct.pack("i", len(header_bytes)))

            # 2.再发报头
            conn.send(header_bytes)

            # 3.最后发真实数据
            conn.send(stdout)
            conn.send(stderr)
        except Exception: # 针对windows
            break
    conn.close()

phone.close()

4858.com 77

 

5.7.2 客户端

4858.com 78

import socket
import struct
import json

phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
phone.connect(("127.0.0.1", 8080))

while True:
    cmd = input(">>").strip()
    if not cmd:continue
    # 发命令
    phone.send(cmd.encode("utf-8"))

    # 先收报头的长度
    struct_res = phone.recv(4)
    header_size = struct.unpack("i", struct_res)[0]

    # 再收报头
    header_bytes = phone.recv(header_size)
    print(header_bytes)
    head_json = header_bytes.decode("utf-8")
    head_dic = json.loads(head_json)

    total_size = head_dic["total_size"]

    # 再收命令的执行结果
    recv_size = 0
    data = b""
    while recv_size < total_size:
        recv_data = phone.recv(1024)
        recv_size += len(recv_data)
        data += recv_data

    # 打印结果
    print(data.decode("gbk"))

phone.close()

4858.com 79

 

5.八 服务端落成产出

5.8.1 服务端

4858.com 80

import socketserver

class MyTcphandler(socketserver.BaseRequestHandler):
    def handle(self):
        while True: # 通信循环
            print(self.request)
            data = self.request.recv(1024)
            self.request.send(data.upper())

if __name__ == '__main__':
    # 取代链接循环
    server = socketserver.ThreadingTCPServer(("127.0.0.1",8080), MyTcphandler)
    server.serve_forever()

4858.com 81

 

5.8.2 客户端

4858.com 82

import socket
phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
phone.connect(("127.0.0.1", 8080))

while True:
    msg = input(">>").strip()
    if not msg:continue
    phone.send(msg.encode("utf-8"))
    server_data = phone.recv(1024)
    print(server_data.decode("utf-8"))
phone.close()

4858.com 83

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图
Copyright @ 2010-2019 美高梅手机版4858 版权所有