#多态:多态指的是一类事物有多种形态
# import abc
# class Animal(metaclass = abc.ABCMeta):# 同一类事物:动物
# @abc.abstractclassmethod
# def talk(self):
# print('from Animal')
# class People(Animal):#动物的形态之一:人
# def talk(self):
# print('from People')
# class Dog(Animal):
# def talk(self):
# print('from Dog')
# class Pig(Animal):
# def talk(self):
# print('from Pig')
##################################################################################################
# import abc
# class File(metaclass=abc.ABCMeta):#同一类事物:文件
# @abc.abstractclassmethod
# def click(self):
# print('from File')
# class Text(File): #文件的形态之一:文本文件
# def click(self):
# print('From Text')
# class ExeFile(File): #文件的形态之二:可执行文件
# def click(self):
# print('From ExeFile')
##################################################################################################
#多态的概念:类的继承有两层意义:1.改变 2.扩展
# 多态就是类的这两层意义的一个具体的实现机制
# 即,调用不同的类实例化的对象下的相同方法,实现的过程不一样
#Pyhton中的标准类型就是多态概念的一个很好的示范
# 在面向对象的方法中一般是这样表述多态性:
# 向不同的对象发送同一条消息(!!!boj.func():)是调用了obj的方法func
# 又称为向obj发送了一条消息
# 不同的对象在接收时会产生不同的行为即方法,每个对象可以用自己的方式去相应共同的消息,所谓消息,就是调用函数
# 不同的行为就是指不同的实现,即执行不同的函数
##################################################################################################
# 封装:封装在于明确区分内外,使得类实现者可以修改封装内的东西而不影响外部调用者的代码;
# 而外部使用用者只知道一个接口(函数),
# 只要接口(函数)名、参数不变,使用者的代码永远无需改变。
# 这就提供一个良好的合作基础——或者说,只要接口这个基础约定不变,则代码改变不足为虑。
#其实这仅仅这是一种变形操作且仅仅只在类定义阶段发生变形
#类中所有双下划线开头的名称如__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这个名字访问到
##################################################################################################
# 第一个层面的封装:类就是麻袋,这本身就是一种封装
# 第二个层面的封装:类中定义私有的,只在类的内部使用的,外部无法访问
# python不依赖语言特性去实现第二层面的封装,而是通过遵循一定的数据属性和函数属性的命名约定来达到封装的效果
# 约定一:任何以单下划线开头的名字都应该是内部的、私有的
# 约定二:双下划线开头的名字
# 第三个层面的封装:明确区分内外,内部的实现逻辑,外部无法知晓,并且为封装到内部的逻辑提供一个访问接口给外部使用
# (这才是真正意义上的封装)[简答说就是类的内部提供一个接口函数供外部调用]
##################################################################################################
# 接口函数(访问函数)
# class People:
# __star = 'earth'
# def __init__(self,id,name,age,salary):
# print('————>>>',self.__star)
# self.id = id
# self.name = name
# self.age = age
# self.salary = salary
# def get_id(self):
# print('我是私有方法啊,我找到的id是[%s]'%self.id)
# #访问函数
# def get_star(self):
# print(self.__star)
# p1 = People('321081199402xxxx','pandaboy','17',999999)
# print(People.__dict__)
# print(p1._People__star)
##################################################################################################
# 总结:
# 上面提到的有两种不同的编码约定(单下划线和双下划线)来命名私有属性,
# 大多数而言,你应该让你的非公共名称以单下划线开头,但是,如果你清楚的代码会涉及子类,并且有些内部属性
# 应该在子类中隐藏,那么才考虑使用双下划线方案,其实python都没有从根本上还是那个限制你的访问
##################################################################################################
# 面向对象总结:从编程进化论得知,面向对象是一种更高级的结构化编程方式,它的好处就两点:
# 1.通过封装明确了内外,作为类的缔造者,代码编写的逻辑不需要知道,这样就明确了划分等级,物就是调用者
# 2.通过继承+多态的语言层面支持了归一化设计
# 注意:不用面向对象语言即class,一样可以做归一化(如老掉牙的泛文件概念,游戏行业的一切皆精灵),一样可以封装(通过定义模块和接口)
# 只是用面向对象语言可以直接用语言元素显式声明这些而已;而用来面向对象的语言,满篇都是class,并不等于就有了归一化的设计
# 甚至反而不知道什么是设计,不要滥用面向对象(不到最后设计不要用)
##################################################################################################
# 反射的概念:反射的概念主要是指程序可以访问、检测和修改它本身或行为的一种能力(自省)。
# 适用于类和对象的自省函数
# hasattr(object,name)
# 判断object中有没有一个name字符串对应的方法或属性
# class BlackMedium:
# feture = 'Ugly'
# def __init__(self,name,addr):
# self.name = name
# self.addr = addr
# def sel_house(self):
# print('【%s】正在卖房子'%self.name)
# def rent_house(self):
# print('【%s】正在租房子'%self.name)
# b1 = BlackMedium('anyway','hardway')
# print(hasattr(BlackMedium,'sel_house1'))
# True
#————————————————————————————————————————————————#
# # getattr(object,name,default = None)
# getattr(b1,'rent_house')()#没有值时则报错
# # 【anyway】正在租房子
# print(getattr(b1,'rent_house1','我就不报错,你信么'))
#————————————————————————————————————————————————#
# setattr(b1,'ok',True)#新增字典
# print(b1.__dict__)
#————————————————————————————————————————————————#
# delattr(b1,'ok')
# print(b1.__dict__)
#————————————————————————————————————————————————#
#为什么要用反射?
# 总之反射的好处就是,可以事先定义好接口,接口只有在被完成后才会真正执行,
# 这实现了即插即用,这其实是一种‘后期绑定’,
# 什么意思?即你可以事先把主要的逻辑写好(只定义接口),然后后期再去实现接口的功能
# class FtpClient:
#ftp客户端,但是还没有实现具体的功能
# def __init__(self,addr):
# print('正在连接服务器[%s]'%addr)
# self.addr = addr
# def get(self):
# print('正在上传文件')
# f1 = FtpClient('192.168.1.1')
# if hasattr(f1,'get'):
# func_get = getattr(f1,'get')
# print('我要处理函数了')
# func_get()#捕获到此方法就正常工作了
# else:
# print('————》不存在此方法')
# #动态导入模块,基于反射机制做的动态导入
# module_t = __import__('Day15')
# print(module_t)
#
# import importlib
# m = importlib.import_module('每日学习打卡.Day15')
# print(m)
# m.connect()
# 我是和Day26关联的测试
#————————————————————————————————————————————————#
# 双下划线开头的attr方法
# class Foo:
# x = 1
# def __init__(self,y):
# self.y = 1
# def __getattr__(self, item):
# print('执行__getattr__')
# def __setattr__(self, key, value):
# print('执行__setattr__')
# self.__dict__[key] = value
# f1 = Foo(10)
# print(f1.__dict__)
# print(f1.y)
# f1.z = 2
# print(f1.__dict__)
######################################################################################################################
# class Foo:
# def __init__(self,name):
# self.name = name
# def __getattr__(self, item):
# print('你找的属性[%s]不存在'%item)
# # def __setattr__(self, key, value):
# # print('执行setattr')
# f1 = Foo('alex')
# # print(f1.name)
# # print(f1.age)
# print(f1.__dict__)
# ########################################################################################################################################
#二次加工标准类型(包装)
#每个标准类型的产生都有标准的两种格式
# 一个类,就有封装、多态、继承
# class lIST(list):
# def append(self,p_obj):
# if type(p_obj) is str:
# super().append(p_obj)
# else:
# print('不好意思,不存在')
# def show_midlle(self):
# mid_num = int(len(self)/2)
# return self[mid_num]
# L1 = lIST('helloworld')
# L2 = list('hello world')
# # print(L2,type(L2))
# print(L1.show_midlle())
# L1.append('SB')
# print(L1)
#######################################################################################################
# 授权:授权是包装的一个特性,包装一个类型通常是对已经存在的类型的一些定制,这种做法可以新建、修改或删除原有产品的功能
# ,其他的则保持原样,授权的过程,即是对所有更新的功能的都是由新式类的某部分处理,但是已经存在的功能就授权给对象的默认属性
# 实现授权的关键点就是覆盖__getattr__方法
import time
class Open:
def __init__(self,filename,mode='r',encoding = 'utf-8'):
# self.filename = filename
self.file = open(filename,mode,encoding=encoding)
self.mode = mode
self.encoding = encoding
def write(self,line):
print('___>',line)
t = time.strftime('%Y-%m-%d %X')
self.file.write('%s %s'%(t,line))
def __getattr__(self, item):
print(item)
return getattr(self.file.item)
def read(self):
pass
f1 = Open('a.txt','w')
print(f1.file)
print(f1.read) #本质上出发了getattr
f1.write('123
')
f1.write('1231
')
f1.write('1234
')