一、多态

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. 使用newtonsoft序列化

    如果将字符串序列化为datatable 时,字符串中包含null,序列化会报错,此时将datatabel 添加到dataset 中,在序列化成字符串,然后在将字符串反序列化成dataset

  2. 二次剩余Cipolla算法学习笔记

    对于同余式 \[x^2 \equiv n \pmod p\] 若对于给定的\(n, P\),存在\(x\)满足上面的式子,则乘\(n\)在模\(p\)意义下是二次剩余,否则为非二次剩余 我们需要计算的 ...

  3. 上传漏洞总结-upload-labs

    介绍: Upload-labs是一个所有类型的上传漏洞的靶场 项目地址:https://github.com/c0ny1/upload-labs 思维导图: 小试牛刀: Pass-01 客户端js检查 ...

  4. JS的MD5加密

    /* * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message * Digest Algorithm, as d ...

  5. Android 图片Bitmap,drawable,res资源图片之间转换

    一.知识介绍 ①res资源图片是放在项目res文件下的资源图片 ②BitMap位图,一般文件后缀为BMP,需要编码器编码,如RGB565,RGB8888等.一种逐像素的显示对象,其执行效率高,但缺点也 ...

  6. 五、RemoteViews

    RemoteViews表示的是一个View结构,它可以在其他进程中显示.RemoteViews在Android中的使用场景有两种:通知栏和桌面小部件. 1.RemoteViews的应用 RemoteV ...

  7. Android Picasso最详细的使用指南

    Picasso 是Square 公司开源的Android 端的图片加载和缓存框架.Square 真是一家良心公司啊,为我们Android开发者贡献了很多优秀的开源项目有木有!像什么Rerefoit . ...

  8. windows键盘按键输入错乱;

    问题:打字异常,打字乱码: 最佳解决方案:下载工具快速修复: 链接: 链接:https://pan.baidu.com/s/1GpWT-MljgQHorLNMhQ9eOg提取码:anh0 官网文档原因 ...

  9. 【记录】使用在线KMS激活Office系列

    摘要 (有能力的请支持正版office) 网上一些激活工具可能捆绑了木马.病毒.使用激活工具有风险.使用在线KMS来激活则没有这个风险. 找到你的office安装目录 已管理员身份运行cmd输入:cd ...

  10. 龙尚 U9300C wvdial 拨号上网

    龙尚 U9300C    7模   4G LTE   (国内全网通) 接入linux系统会有4个串口 其中ttyUSB2 为AT指令口 ttyUSB1 为拨号上网口 wvdial   拨号入网参数 [ ...