一、多态

1、什么是多态:一个类表现出的多种状态--->通过继承来实现的
例如:
class Animal:pass
class Dog(Animal):pass
class Cat(Animal):pass
Animal类表现出了Dog,Cat两种形态

好了,多态就是这样,结束...

哈哈,有没看懂的吧,那么我们一步一步来解释:

首先我们来看:
s = 'abc'
print(type(s))   # <class 'str'>

s = 'abc' 我们都知道s就是一个str类型,在python中一切皆对象,其实你打开源码可以看到str是一个类,
它在源码中是这样定义的:class str(object): ...
而我们定义一个变量的时候s = 'abc' ,它在内部是进行了一个这样的转换:s = str('abc')
刚才说了str是一个类,那str()就是实例化 , str('abc')就是把参数'abc'传进去初始化一个对象,那么s就是一个str类的对象,s的type就是str,
也就是说其实我们平时定义的变量都是对象,例如:
a = 10 是一个int类的对象
b = [1,2,3] 是一个list类的对象等等

那么我们自己定义的类也是一样的:
class A:
  pass

a = A()
print(type(a))       # 对象a的数据类型就是A

2、我们引用一下java中的例子再来了解一下(假设下面是java代码)

class ApplePay:
def pay(self):
pass 在java中,参数是要指定类型的,其他类型的数据是不能传进去的,这里指定了是ApplePay类型
def My_pay(ApplePay obj,int money):
obj.pay() app = ApplePay() # app是ApplePay类的对象,所以app就是ApplePay类型的数据
My_pay(app,100) 这么一看,好像没什么问题,但是这么写的话,这个My_pay函数只能给ApplePay类使用了,其他类就不能使用了,
扩展性很差,那么这个时候就需要多态了,且看下面例子: class Payment: # 首先定义一个父类
pass class ApplePay(Payment): #每个子类都继承父类
def pay(self):
pass class Alipay(Payment): #每个子类都继承父类
def pay(self):
pass #这里obj类型写父类的类型Payment,因为子类继承父类,也继承了父类的类型
def My_pay(Payment obj,int money):
obj.pay() app = ApplePay() # 这里app既是ApplePay类型,也是Payment类型
My_pay(app,100) alp = Alipay() # 这里alp既是Alipay类型,也是Payment类型
My_pay(alp,200) 这样利用多态就解决了参数类型的问题

3、总结(为什么在python中,我们写的函数都不用指定类型?)
1,
在java中:多态用来解决传参数的时候数据类型的规范问题。
在java中的表现 : 在一个函数中需要给参数指定数据类型,如果这个地方可以接收两个以上类型的参数,
那么这些类型应该有一个父类,这个父类是所有子类对象的类型

2,
在python中:函数的参数不需要指定数据类型,我们也不需要通过继承的形式来统一数据类型,
因为python中所有的对象都继承了object类,所以都是object类型,因此在python当中处处都是多态。

4、鸭子类型(拓展)
定义:
不是明确的通过继承实现的多态,
而是通过一个模糊的概念来判断这个函数能不能接收这个类型的参数

例如:

def func(arg):
arg.send()
# 对应参数arg,我们没有明确地表明这是什么类型的参数,arg可以是任意的,但是它必须有send方法,因此判断只要是一个类,类中有send方法,就可以作为这个函数的参数

二、封装

1、定义:
  广义上的封装:把属性和函数都放到类里
  狭义上的封装:定义私有成员

1,广义上的封装:
class 类名:
  def 方法1(self):pass
是为了只有这个类的对象才能使用定义在类中的方法

2,狭义上的封装:   __属性名      __方法名
把一个属性(方法)藏在类中 
class Goods:
  __discount = 0.7         # 私有的静态变量

print(Goods.__discount)    # 报错

在类的外部不能引用私有的静态变量

class Goods:
  __discount = 0.7    # 私有的静态变量
  print(__discount)    # 类内部打印输入

程序一执行就打印出0.7
因为:
类中的静态变量和方法名在程序加载的过程中就已经执行完了,不需要等待调用
在这个类加载完成之前,Goods这个名字还没有出现在内存空间中
私有的静态属性可以在类的内部使用,用来隐藏某个变量的值

3,变形
其实用双下划线定义好一个私有变量后,python会自动把这个私有变量进行一个变形,例如私有变量__discount,变形如下:
__discount          --->        _Goods__discount

也就是:
__私有变量        --->        _类名__私有变量

class Goods:
  __discount = 0.7 # 私有的静态变量

print(Goods.__dict__)        # 查看Goods类的所有属性和方法可以看到里面有个变量_Goods__discount的值是0.7
print(Goods._Goods__discount) # 可以看到0.7  但从编程规范的角度上出发 我们不能在类的外部使用私有的变量

2、
类中的私有成员:
  1,私有的静态属性
  2,私有的对象属性
  3,私有的方法

为什么要定义一个私有变量呢:
  1,不想让你修改这个值
  2,不想让你看到这个值
  3,想让你在修改这个值得时候有一些限制
  4,有些方法或者属性不希望被子类继承

话不多说,请看例子理解

例1:私有的静态属性、不想让你修改这个值

class Student:
def __init__(self,name,age):
self.__name = name # 设置了一个私有变量__name用来储存学生的名字
self.age = age
def name(self): # 因为私有变量在外部不能引用,所有设置一个方法用来打印学生的名字
return self.__name xiaoming = Student('xiaoming',18)
print(xiaoming.age) #
print(xiaoming.name()) # xiaoming xiaoming.age = 28
print(xiaoming.age) # xiaoming.name = 'xiaogou' #这里只是为这个对象新增了一个属性name,并没有修改原本的__name
print(xiaoming.name()) #报错
那么肯定会有人问,这样做确实不能修改__name,但是别人可以新增name啊,而且__name还要用name()这样才能显示,多麻烦。
好,这个问题等下在后面的内容会给你解决,现在你只要明确地知道你一开始传进去的学生名字__name是修改不了就行了。

例2:私有的静态属性、修改的时候有限制

class Goods:
__discount = 0.7 # 私有的静态变量
def __init__(self,name,price):
self.name = name
self.__price = price def price(self): #折扣价
return self.__price * Goods.__discount def change_price(self,new_price):
if type(new_price) is int:
self.__price = new_price
else:
print('本次价格修改不成功') apple = Goods('苹果',5)
print(apple.price()) apple.change_price(6)
print(apple.price())

例3:私有的对象属性、不想让你看到这个值(通过算法把密码变成密文的形式)

class User:
def __init__(self,username,password):
self.username = username
self.__pwd = password
self.pwd = self.__getpwd() def __getpwd(self): # 把密码转换成哈希值
return hash(self.__pwd) obj = User('xiaoming','') # 用户名:xiaoming 密码: 123456
print(obj.username,obj.pwd) # 用户名:xiaoming 密码的密文:-1675187800842546722

3、私有变量能不能在外部被定义?(不能)

class A:
__country = 'China' print(A.__dict__) A.__Language = 'Chinese' # 其实这里只是定义了一个名为__Language的属性,并不是私有变量
print(A.__dict__)

4、私有变量能不能被继承?(可以)

class A:
__country = 'China' # __country 就是 _A__country
def __init__(self,name):
self.__name = name # __name 就是 _A__name 继承A的B类的对象初始化的时候 self.__name 就是
# self._A__name
# 此时为self._A__name赋值,并没有形成self的私有变量
# 而本身的A类对象初识化的时候,为self.__name赋值,会形成self的私有变量 class B(A): def get_country(self):
print(__country) # 报错:name '_B__country' is not defined
print(B._A__country) # China def get_name(self):
return self.__name # 报错:'B' object has no attribute '_B__name' b = B('xiaoming')
b.get_country()
print(b.get_name())
print(b.__dict__) # {'_A__name': 'xiaoming'}

总结:
子类可以继承父类的所有属性(包括私有属性)和方法,但是继承的私有属性是变形后的形式,在子类中不再是私有属性,
在子类中用 __私有属性名 是找不到继承的私有属性的 因为它会默认去找自己类中的私有属性,
要想调用父类的私有属性则应该用变形后的变量 _父类名__变量名

三、内置函数property

1、
装饰器的分类:
  装饰函数:
  装饰方法 : property
  装饰类:

装饰器函数都怎么用:
在函数、方法、类的上面一行直接@装饰器的名字

2、property是一个装饰器函数(就是用来解决刚才私有属性的问题)
property:将一个方法伪装成一个属性

2-1学生信息中,姓名不想给别人修改,就设置为私有属性,在定义一个同名的方法伪装成属性,便于查找

class Student:
def __init__(self,name,age):
self.__name = name
self.age = age @property
def name(self): # 声明了@property使用此方法的时候就可以不写括号,就伪装成了属性
return self.__name xiaoming = Student('小明',18)
print(xiaoming.name) # 小明 xiaoming.name = '小狗' # 改:报错
print(xiaoming.name)

2-2圆的半径可以修改,但是面积和周长应该是属性的形式比较正确,但是直接设置为属性,圆的半径改了后,
周长和面积并不会改变

class Circle:
def __init__(self,r):
self.r = r
self.area = 3.14 * self.r ** 2
self.perimeter = 2 * 3.14 * self.r
c = Circle(6)
print(c.area) # 113.04
print(c.perimeter) # 37.68 c.r = 3 # 改变了半径
print(c.area) # 113.04
print(c.perimeter) # 37.68

2-3因此上面的圆可以写成这样:

class Circle:
def __init__(self,r):
self.r = r @property
def area(self):
return 3.14 * self.r ** 2 @property
def perimeter(self):
return 2 * 3.14 * self.r c = Circle(6)
print(c.area) # 113.04
print(c.perimeter) # 37.68 c.r = 3 # 改变了半径
print(c.area) # 28.26
print(c.perimeter) # 18.84

python之类的多态(鸭子类型 )、封装和内置函数property的更多相关文章

  1. Python【map、reduce、filter】内置函数使用说明(转载)

    转自:http://www.blogjava.net/vagasnail/articles/301140.html?opt=admin 介绍下Python 中 map,reduce,和filter 内 ...

  2. Python【map、reduce、filter】内置函数使用说明

    题记 介绍下Python 中 map,reduce,和filter 内置函数的方法 一:map map(...) map(function, sequence[, sequence, ...]) -& ...

  3. day30 继承、派生与多态,类中方法和内置函数

    目录 一.多继承出现的问题(mixins机制) 二.派生与方法重用 三.多态 1 什么是多态 2 为什么要有多态 3 python中多态的鸭子类型 四.绑定方法与非绑定方法 1 绑定方法 1.1对象的 ...

  4. python部落刷题宝学到的内置函数

    最近加入了python部落,感觉里面的刷题宝很有意思,玩了一下,知道了许多以前并不清楚的内置函数,然后感觉到快要记不住了,所以开始陈列一下 1.divmod(a,b):取a除以b的商和余数,功效等价于 ...

  5. python入门(二):isinstance、内置函数、常用运算等

    1.    isinstance(变量名,类型)                           #判断什么类型 ps: 只支持输入两个参数,输入3个参数会报错 >>> isin ...

  6. python中的运算符及表达式及常用内置函数

    知识内容: 1.运算符与表达式 2.for\while初步了解 3.常用内置函数 一.运算符与表达式 python与其他语言一样支持大多数算数运算符.关系运算符.逻辑运算符以及位运算符,并且有和大多数 ...

  7. python 基础篇 14 程程器表达式 内置函数

    昨日内容回顾    可迭代对象:        内部含有__iter__方法的就是可迭代对象.        可迭代对象不能取值,因为内部不含有__next__方法.     可迭代对象 ---> ...

  8. Python中生成器,迭代器,以及一些常用的内置函数.

    知识点总结 生成器 生成器的本质就是迭代器. 迭代器:Python中提供的已经写好的工具或者通过数据转化得来的. 生成器:需要我们自己用Python代码构建的 创建生成器的三种方法: 通过生成器函数 ...

  9. Python语法速查: 1. 数据类型与内置函数

    返回目录 (1)常用内置数据类型 分类 类型名称 描述 数字 int 整数 float 浮点数 complex 复数 bool 布尔值 序列 str 字符串(不可变序列) list 列表 tuple ...

随机推荐

  1. 将Dynamics 365中的用户及其角色、角色导出到Excel中

    关注本人微信和易信公众号: 微软动态CRM专家罗勇 ,回复240或者20161204可方便获取本文,同时可以在第一间得到我发布的最新的博文信息,follow me!我的网站是 www.luoyong. ...

  2. JS table内容转成二维数组,支持colspan和rowspan

    思路:1.先初始化colspan的数据到数组2.根据rowspan和colspan计算th和td的矩阵二次填充数组 说明:需要引用到第三方库jQuery,table中的th和td行和列跨度必须正确 & ...

  3. 如何在WIN10内置Ubuntu中有多个terminal

    使用的是tmux来实现在WIN10的内置Ubuntu实现多终端窗口 先安装tmux:sudo apt-get install tumx 启动tmux,tmux 然后就可以在tmux中实现多窗口.其操作 ...

  4. 小米8 探索版 屏幕指纹版超简单卡刷开发版获取Root权限的教程

    小米的手机不同手机型号通常情况下miui官网都提供两个不同的系统,分别是稳定版和开发版,稳定版没有提供ROOT超级权限管理,开发版中就开启了ROOT超级权限,在很多工作的时候我们需要使用的一些功能强大 ...

  5. Android冷启动优化

    我们知道新打开一个应用的时候,会出现短暂的白屏或者黑屏,严重影响到我们的用户体验,其实这个过程是launcher启动新进程,进程中启动activity时,会先绑定window,然后使用默认的windo ...

  6. Visual Studio 无法记忆标签页、断点等的解决办法

    1.到工程目录删除*.suo文件 2.*.suo默认是隐藏的,需要打开查看隐藏文件的开关

  7. Django Windows环境下部署

    环境准备 本文将介绍如何在Windows系统上部署Django web项目,本次部署基于下面的架构: Windows10 64位+Python3.6+Django1.11+Apache2.4+mod_ ...

  8. Windows2012R2 NTP时间同步

    Windows2012R2 NTP时间同步 Windows2012R2里没有了internet时间,需要使用另外的方式去做时间同步 下面分两个情况 两个情况,两个情况都需要用修改组策略的方式来做 情况 ...

  9. Sqlite3-安装使用

    Sqlite安装 请访问 SQLite 下载页面,从 Windows 区下载预编译的二进制文件. 您需要下载 sqlite-tools-win32-*.zip 和 sqlite-dll-win32-* ...

  10. Cube的高级设置

    分享来源地址:http://bigdata.51cto.com/art/201705/538648.htm Cube的高级设置 随着维度数目的增加,Cuboid 的数量会爆炸式地增长.为了缓解 Cub ...