多态的概念:
一种事务具备不同的形态
例如:
比如人有多重形态:
黑人 白人 黄种人 老人 小孩
程序中的多态是指,不同对象可以相应方法,并可以有自己不同的实现方式
多态不是一种特殊的语法,它是一种状态,是一种个特性(多个不同的对象使用一种相同的方法,产生不不同的结果
也就是不同的对象使用相同的方法.
多态案例
import abc
class Animal(metaclass=abc.ABCMeta): # 同一种类事务: 动物
@abc.abstractmethod
def talk(self):
pass
class People(Animal): # 动物的形态之一: 人
def talk(self):
print('你好!')
class Dog(Animal):
def talk(self):
print('汪汪汪')
a = People()
B = Dog()
a.talk()
B.talk()
class Cat(Animal):
def talk(self):
print('喵喵')
c = Cat()
c.talk()
多态的来的好处:
1.增加程序的灵活性
以不变应万变,不论对象的千变万化,使用者都是以同一个形式去调用
2.增加了程序的可扩展性,降低了使用的难度
鸭子类型:
python中崇尚鸭子类型,看起来像鸭子,叫声像鸭子那么它就是鸭子
python程序员通常根据这种标准来编写程序.如果想编写现有对象的自定义版本可以继承这个对象
也可以穿件一个外观和行为像,但是与它没有任何关系的全新对象,后者通常用于保存程序的耦合度.
isinstance :
python 中isinstance()函数,是python中的一个内置函数,是用来判断一个函数是否是另一个已知的类型,(和type类似)
判断一个对象是否是某个类的实例(对象)
isinstance(object,classinfo)
参数1 要判断的对象
参数2 要判断的类型
返回值: 如果对象的类型与参数二类型相同返回True 反之返回False
a = 2
res = isinstance(a,int)
print(res) # 结果为>>>True
res = isinstance(a,str)
print(res) # 结果为>>>False
res = isinstance(a,(int,str,list))
print(res) # 结果为True 元祖中的一是正确的的所以返回值为True
isinstance()和type()的区别
isinstance()会认为子类父类类型,考虑继承关系
type()中不会认为子类是一种父类形态,不考虑继承关系.
class A:
pass
class B(A):
pass
res = isinstance(A(),A)
print(res) # True
print(type(A())) # <class '__main__.A'>
print(isinstance(B(),A)) # True
print(type(B())) # <class '__main__.B'>
issubclass:
判断一个类是否是另一类的子类
issubclass(class,classinfo)
参数:
class--->类
classinfo---> 父类
返回值:
如果class是classinfo的子类返回值True 反之为False
实例:
class A:
pass
class B(A):
pass
class C:
pass
print(issubclass(B, A)) # 结果为True
print(issubclass(C, A)) # 结果为False
__ste__方法:
__str__的方法和__int__方法类似,都是以一些特殊的方法,所以前后都有双下划线,它用来返回随想的字符串表达方式
__str__会对像被转换成字符串时,转换的结果就是这个函数的返回值,我们可以利用该函数来自定义,对象的打印格式
实例:
class Person:
def __init__(self,name,age):
self.name = name
self.age = age
def __str__(self):
return '这是一个person对象 name %s age %s'%(self.name,self.age)
p = Person('jason',12)
print(p)
__del__使用方法:
创建对象后,Python解释器默认调用__init__()方法。当删除一个对象时,Python解释器也
会默认调用一个方法,这个方法为__del__()方法。在Python中,对于开发者来说很少会直接
销毁对象(如果需要,应该使用del关键字销毁)。Python的内存管理机制能够很好的胜任这份
工作。也就是说,不管是手动调用del还是由Python自动回收都会触发__del__方法执行。
执行时机:手动删除对象时立马执行,或者是程序运行结束时也会自动执行
使用场景: 当你的对象在使用过程中,打开了不属于解释器的资源:比如文件,网络端口等
实例:
class A(object):
#创建初始化方法
# 创建对象后直接被调用
def __init__(self,name):
print("__init__初始化方法被调用")
self.name = name
# 方法 当对象被删除的时候会自动调用
def __del__(self):
print('__del__方法被调用了!')
time.sleep(2)
print('%s对象马上要被杀死了...'%self.name)
dog = A('哈士奇')
print('___马上杀死哈士奇')
del dog
get = A('苍井空')
print('___马上干掉苍老师')
del get
>>>>
执行结果:
__init__初始化方法被调用
___马上杀死哈士奇
__del__方法被调用了!
哈士奇对象马上要被杀死了...
__init__初始化方法被调用
___马上干掉苍老师
__del__方法被调用了!
苍井空对象马上要被杀死了...
>>>>
call 使用方法:
关于__call__方法,不得不要先提到一个概念,就是可调用对象(callable)
我们平时自定义的函数、内置函数和类都属于可调用对象,但凡是可以把
一对括号()应用到某个对象身上都可称之为可调用对象,判断对象是否为
可调用对象可以用函数 callable 如果在类中实现了 __call__ 方法,那
么实例对象也将成为一个可调用对象,
什么时候调用: 在调用函数对象的时候会自动执行,也就是加括号的时候
__call__实例:
class A:
def __call__(self, *args, **kwargs):
print('call run')
print(args)
print(kwargs)
a = A()
a(1,a = 199)
>>>
call run
(1,)
{'a': 199}
>>>
__slots__节省内存:
该属性是一个类属性,用于优化对象内存占用,优化的原理,将原本不固定的属性数量变得固定。
从而达到减少内存的占用
首先我需要这世道动态语言和静态语言
python属于动态语言:可以在运行的时候修改代码
c就属于静态语言: 在编译时已经确定好了代码,在运行过程中是不被修改的
为了达到限制的目的,python允许在定义class的时候定义了一个特殊的__slots__变量来限制
class实例能添加的属性:
# __slots__实例
class Person:
__slots__ = ('name','age')
p = Person()
p2 = Person()
p.name = '隔壁老王'
p.age = 89
print(sys.getsizeof(p))
print(sys.getsizeof(p2))
print(sys.getsizeof(p.name))
print(sys.getsizeof(p.age))
# print(p.__dict__) # 没有了__dict__ 所以报错了
getattr获取属性
setattr设置属性
delattr删除属性
getattr()函数用于返回一个对象属性值
getattr(object,name[,default])
object--->对象
name--->字符串,对象属性
default--->默认返回值,如果不提供这个参数,在没有对应属性时,将触发attbuteerro
getattr 用点访问属性的时候如果属性不存在的情况下执行
setattr 用点设置属性
delattr 用del 对象 .属性 删除属性时执行
这几个函数反映了python解释器是如何实现用点来访问属性
getattribute这个函数也是用来获取属性的
在获取属性时如果存在getattribute则先执行该函数,如果没有拿到属性则继续调用
getattr函数,如果拿到了则直接返回
实例:
class A:
def __setattr__(self, key, value):
# print(key)
# print(value)
print('__setattr__')
self.__dict__[key] = value
def __delattr__(self, item):
print('__delattr__')
print(item)
self.__dict__.pop(item)
pass
def __getattr__(self, item):
print('__getattr__')
return 345
def __getattribute__(self, item):
print('__getattribute__')
return super().__getattribute__(item)
a = A()
a.name = 'jason'
# print(a.name)
# # a.age = 19
del a.name
print(a.name)
[]的实例:
getitem 当你用括号去获取属性时执行
setitem 当用括号去设置属性时 执行
delitem 当你用括号删除属性时执行
实例:
class MyDict(dict):
pass
def __getattr__(self, key):
return self.get(key)
def __setattr__(self, key, value):
self[key] = value
def __delattr__(self, key):
del self[item]
a= MyDict()
a['name'] = 'jack'
print(a['name'])
print(a.name)
a.age = 20
print(a.age)
运算符重载
当我们在使用某个符号时,python解释器都会为这个符号定义一个含义,同时调用
对应的处理函数,当我们需要自定义对象的比较规则时,就可在子类中覆盖大于等于
等等一系列的方法。。。
案例:
原本自定义对象无法直接使用大于小于等于来进行比较,我们
可以自定义运算符来实现,让自定义对象也支持比较运算符
class Student(object):
def __init__(self,name, age, height):
self.name = name
self.age = age
self.height = height
def __gt__(self, other): # 大于
print(self)
print(other)
print("__gt__")
return self.age > other.age
def __lt__(self, other):
return self.name < other.name
def __eq__(self, other):
if self.height == other.height and self.name == other.name and self.age == other.age:
return True
return False
s1 = Student('肉丝',20, 175)
s2 = Student('杰克',20, 175)
print(s1 < s2)
print(s1 < s2)
print(s1 == s2)
迭代器协议:
迭代器是指具有__iter__和__next__的对象,我们可以为对象增加两个方法
让对象编程一个迭代器
案例:
#迭代器案例:
class MyRange:
def __init__(self,start, end, step):
self.start = start
self.end = end
self.step = step
def __iter__(self):
return self
def __next__(self):
a = self.start
self.start += self.step
if a < self.end:
return a
else:
raise StopIteration
for i in MyRange(1,100,2):
print(i)
上下文管理
上下文context
这个概念术语语言学科,指的是一段话的意义,要参考当前的场景,即上下文
在python中,上下文可以理解为是一个代码区间,一个范围,比如with open
打开文件仅仅是在这个上下文中有效
上下文涉及了两个方法;
enter:进入 表示进入上下文,或者说进入某个场景
exit:推出 表示推出上下文,或者说是退出某场景
enter 函数应该有返回值,返回值是对象自己
exit函数可以有返回值,是一个bool值,用于表示一场是否被处理,仅在上下文中出现异常时用
如果为True 意味着,异常已经被处理了
False 为异常没有被处理
当执行with 语句时候会优先执行enter
当代码制行完毕后制行exit,或者是代码遇到异常会立即制行exit,并传出错误信息
包含错错误类型,错误信息。错误的追踪信息
# 实例一
class Poo:
def __int__(self):
print('实例化一个 对象')
def __enter__(self):
print('进入...')
def __exit__(self, exc_type, exc_val, exc_tb):
print('退出...')
# return True
# return False
p = Poo()
print(p)
with p:
raise ImportError
print('正在制行。。。')
#"""出现异常时,如果 __exit__ 返回 False(默认不写返回值时,即为False),则会重新抛出异常,让with 之外的语句逻辑来处理异常,这也是通用做法;如果返回 True,则忽略异常,不再对异常进行处理"""
class MyOpen:
def __init__(self,path):
self.path = path
def __enter__(self):
self.file = open(self.path)
print("进入...")
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print('退出...')
self.file.close()
return True
# retuen False
with MyOpen("a.txt")as f:
# 23+'34'
print(f)
print(f.file.read())