多态

多态的概念:
一种事务具备不同的形态
例如:
比如人有多重形态:
黑人 白人 黄种人 老人 小孩
程序中的多态是指,不同对象可以相应方法,并可以有自己不同的实现方式

多态不是一种特殊的语法,它是一种状态,是一种个特性(多个不同的对象使用一种相同的方法,产生不不同的结果
也就是不同的对象使用相同的方法.
多态案例
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())
    

  



原文地址:https://www.cnblogs.com/ioipchina/p/11266578.html