多态 封装 property内置函数
# 继承 : 提高代码的重用性,规范代码(要就继承父类的子类都实现相同的方法:抽象类、接口)
# 当你开始编写两个类的时候,出现了重复的代码,通过继承来简化代码,把重复的代码放在父类中
# 单继承
# 重用性 :减少代码的重复,子类可以复用父类的方法
# 派生 :子类在父类的基础上又创建了自己的新的方法和属性
# 子类中有父类的同名方法 : 只用子类的
# 还希望用到父类中的方法 : 父类名、super调用
# 抽象类 :只能被继承 不能被实例化 模板、规则 #
# from abc import ABCMeta,abstractmethod
# class A(metaclass=ABCMeta):
# @abstractmethod
# def func(self):pass
# 多继承 python / c++
# java/c#没有
# 每个类中有每个类能完成的方法
# 创建子类的时候只需要挑选和我相符合的父类来继承就能够完成父类的功能了
# 接口 :java中的一种数据类型
# 经典类和新式类的区别
# 经典类 不主动继承object、没有mro方法、没有super、继承的时候 深度优先
# 新式类 主动继承object、有mro方法、有super、继承的时候 广度优先
广度优先: F-->D--->B 如果还没有 就走F-->E--->C--->A
A
B C
D E
F
深度优先 F-->D-->B-->A 然后F-->E-->C
--------------------------------------------------------------------------------------
多态
class A:
class B(A):
class C(A):
当存在两个继承父类的子类 就算出现了多态
java 中运用多态来解决传参数的时候,数据类型的规范问题
什么是多态?
一个类表现出的多种状态: 通过继承来实现的
其实一个父类的多个子类就是多态的表现
在java中的表现:在一个函数中需要给参数指定类型,如果这个地方可以接收两个或者多个类型的参数
那么这些类型应该有一个父类,这个父类是所有子类对象的类型
在python 中: 函数的参数不需要指定类型数据,所以我们也不需要通过继承的形式来统一 一组类的类型
换句话说 所有对象其实都是object类型,在python中其实处处是多态,多态无处不在。
def A() 括号里 随便传什么 也没什么限制
鸭子类型:
len() str list tuple dict set range() 这些都可以在这个内置函数中使用 能奏效
print() 可以打印所有基本上
上面的也可以说 都是鸭子类型 因为都可以使用
不是明确的通过继承实现的多态
而是通关一个模糊的概念来判断这个函数能不能接受这个类型的参数
封装:
广义的封装
比如有很多东西,你不可能全拿在手上,而是找一个包全部 装起来。
class 类名:
def 方法():
是为了 只有这个类的对象 才能使用定义的 类中的方法
狭义的封装
# 狭义上的封装 # 把一个名字藏在类中 # class Goods: # __discount = 0 # 私有的静态变量 # print(__discount) # print(Goods.__discount) # 在类的外部不能引用私有的静态变量
私有化的静态变量 格式 前边两个下划线干 __
类中的静态变量和方法名 在程序加载的过程中就已经执行完了,不需要等待调用
在这个类加载完成之前,Goods这个名字还诶出现在内存空间中
私有的静态属性可以在类的内部使用,用来隐藏某个变量的值
# class Goods: # __discount = 0 # 私有的静态变量 # # 变形 : _类名__私有变量 # # print(Goods.__dict__) ------------取不到值 # print(Goods._Goods__discount) # 编程规范的角度上出发 我们不能在类的外部使用私有的变量 虽然可以取到但是规范不允许
1 我不想让你修改这个值
class Srudent: def __init__(self,name,age): self.__name = name self.age = age def name(self): return self.__name zhuge = Srudent('诸葛',20) print(zhuge.name()) print(zhuge.age) zhuge.age = 'aaaa' print(zhuge.age) 结果 这样做的话 名字你就不能随便改了 而年龄可以随意改 改成aaaa都可以运行,明显不符合规定 诸葛 20 aaaa
加密 密码
class User: def __init__(self,username,password): self.usr = username self.__pwd = password self.pwd = self.__getpwd() def __getpwd(self): return hash(self.__pwd) obj = User('alex','alex3714') print(obj.usr,obj.pwd) ----alex 316251748737762315 ---------------------------------------------
类中的私有成员:
私有的静态属性
私有的对象属性
私有的方法
我为什么要定义一个私有变量呢?
1我不想让你看到这个值
2我不想让你修改这个值
3我想让你在修改这个值 的时候有一些限制
4有些方法或者属性不希望被子类继承
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('APPLE',5) print(apple.price()) apple.change_price('aaaa') print(apple.price()) apple.change_price(10) print(apple.price()) 设定一个折扣,输入的价格从这走得经过打折
有几个问题:
私有变量能不能在外部被定义???
class A : __country = 'China' # 在类的内部会发生变形 print(__country) # '_A__country' print(A.__dict__) A.__Language = 'Chinese' #这个并没有定义成私有变量 还是可以随意调用 print(A.__dict__)
私有变量能不能被继承???
class A: __country = 'China' def __init__(self,name): self.__name = name # '_A__name' class B(A): # print(__country) # NameError: name '_B__country' is not defined def get_name(self): return self.__name # '_B__name' b = B('alex') b.get_name()------>'B' object has no attribute '_B__name'='B'对象没有属性 '_B__name'
print(b.__dict__) ----------》打印答案 {'_A__name': 'alex'}
广义上的封装 把属性函数都放到类里
狭义上的封装 定义私有成员
类中的私有成员;
私有的静态属性
私有的对象属性
私有的方法
我为什么要定义一个私有变量?
我不想让你看到这个值
我不想让你修改这个值
我想让你在修改这个值的时候 有一些限制: 也是简介保证了数据的安全性
有些方法或者属性不希望被子类继承
property
property是一个装饰器函数
所有的装饰器函数都怎么用? 在函数。方法。类上面一行直接 @装饰器的名字
装饰器的分类:
装饰函数
装饰方法:property 这是一个只能装饰方法的装饰器函数
装饰类
class Student: def __init__(self,name,age): self.__name = name self.age = age @property # 将一个方法伪装成一个属性 def name(self): return self.__name zhuge = Student('诸葛',20) print(zhuge.name) ----------------》诸葛 一般实例化对象 调用方法 都是 方法() 但是加了这个函数 可以不用写括号
算圆 面积和周长
from math import pi -------这个是一个模块 class Circle: def __init__(self,r): self.r = r @property def area(self): return self.r ** 2 * pi @property def perimeter(self): return 2 * self.r * pi c1 = Circle(10) print(c1.area) 用了装饰器 可以不用加括号 执行 更加合理 area 面积 print(c1.perimeter) c1.r = 5 print(c1.area) print(c1.perimeter)
有点像把方法 改成属性