Python 多态 对象常用内置函数 运算符重载 对象迭代器 上下文管理 __getattr__()   __setattr__()   __delattr__() [] 的实原理 五 运算符重载(对象大小比较)与迭代器 六 上下文管理

一 多态

1.什么是多态:多态不是一个具体的技术或代码。指的时候多个不同类型对象可以响应同一个方法,产生不同的结果。

2.使用多多态的好处:提高了程序的灵活性,拓展性

3.如何实现:鸭子类型 就是典型的多态 多种不同类型 使用方法一样

4.案例

class Cat():
    def bark(self):
        print("喵喵喵")
    def run(self):
        print("四条腿跑!")
    def sleep(self):
        print("趴着睡!")
        
class Pig():
    def bark(self):
        print("哼哼哼!")
    def run(self):
        print("四条腿跑!")
    def sleep(self):
        print("侧躺着睡!")

# 一个用来管理动物的方法   只要你传入是一个动物 我就按照动物的标准来使用 完全不用考虑你具体是什么类型
def management_animal(animal):
    print("==================正在溜%s=============" % animal.__class__.__name__)
    animal.bark()
    animal.run()
    animal.sleep()
View Code

二 isinstance(参数1,参数2)内置函数

1.判断一个对象是否是某个类的实例,结果为布尔类型

参数1 要判断的对象

参数2 要判断的类型

2.案例:

a = isinstance('own',str) # 判断对象是否字符串类型
print(a) # True 

def add_num(a,b):
    if isinstance(a,int) and isinstance(b,int): # 判断是否是整型
        return a+b
    return None
print(add_num(20,10)) # 30
View Code

三  issubclass(参数1,参数2)内置函数

1.判断一个类是否是另一个类的子类。

参数一是子类

参数二是父类

2.案例:

class Animal:
    def eat(self):
        print("动物得吃东西...")

class Pig(Animal):
    def  eat(self):
        print("猪得吃 猪食....")

a = issubclass(Pig,Animal)
print(a) # True

p = Pig()
b = issubclass(type(p),Animal)
print(b) # True

# 拓展
print(type(p),p.__class__) # <class '__main__.Pig'> <class '__main__.Pig'>
View Code

四 对象常用内置函数

__str__()

1.触发时机:在将对象转为字符串时执行 。注意:返回值必须为字符串类型。

2.使用场景:子类可以覆盖该方法来完成 对打印内容的自定义

3.该方法在object中有定义 默认行为 返回对象类型以及地址 <__main__.Person object at 0x0000016F450C7390>

class Person:
    def __init__(self,name,age):
        self.name = name
        self.age = age
    # 将对象转换为字符串时执行r
    def __str__(self):
        print("str run")
        return "my name is %s , age is %s" % (self.name,self.age)
p = Person("rose",20)

print(p) #在打印前都会现将要打印的内容转为字符串  通过调用__str__函数

q = str(p)
print(q)
View Code

__del__()

1.触发时机:手动删除对象时立马执行,或是程序运行结束时也会自动执行

2.使用场景:当你的对象在使用过程中,打开了不属于解释器的资源:例如文件,网络端口

3.注意:该函数不是用来删除对象的

# del使用案例

class FileTool:
    """该类用于简化文件的读写操作 """

    def __init__(self,path):
        self.file = open(path,"rt",encoding="utf-8")
        self.a = 100

    def read(self):
        return self.file.read()

    # 在这里可以确定一个事,这个对象肯定不使用了 所以可以放心的关闭问文件了
    def __del__(self):
        self.file.close()


tool = FileTool("a.txt")
print(tool.read())
View Code

__call__()

1.触发时机:在调用对象时自动执行,(既对象加括号)

#call 的执行时机
class A:
    def __call__(self, *args, **kwargs):
        print("call run")
        print(args)
        print(kwargs)

a = A()
a(1,a=100) # call run (1,) {'a': 100}
View Code

__slots__

该属性是一个类属性,用于优化对象内存占用
优化的原理,将原本不固定的属性数量,变得固定了
这样的解释器就不会为这个对象创建名称空间,所以__dict__也没了  
从而达到减少内存开销的效果

另外当类中出现了slots时将导致这个类的对象无法在添加新的属性

# slots的使用
import sys
class Person:

    __slots__ = ["name"] # 对象中只能添加'name'的属性,添加其他报错
    def __init__(self,name):
        self.name = name

p =  Person("jck")

# 查看内存占用
print(sys.getsizeof(p)) # 48
# p.age = 20 # 无法添加

# dict 没有了
print(p.__dict__)  # 报错 因为类中有__slots__ 所以__dict__不存在了
View Code

__getattr__()

1.执行时机:对象用点访问属性的时候,如果属性不存在时执行(无论是类中的属性还是对象中属性)

class A:
    def __getattr__(self, item):
        print("__getattr__")
        return 1
a = A()
print(a.name) # __getattr__ 1
View Code

__getattribute__()

1.getattribute 该函数也是用来获取属性
在获取属性时先执行__getattribute__()。如果属性存在执行完__getattribute__()则不再执行__getattr__(),如果属性不存在执行完__getattribute__()则再执行__getattr__()。

class A:

     def __getattr__(self, item):
        print("__getattr__")
        return 1
     def __getattribute__(self, item):
        print("__getattribute__")
        # return self.__dict__[item]
        return super().__getattribute__(item)
a = A()
print(a.name) # __getattribute__ __getattr__ 1

a.name = 'jack'
print(a.name) # __getattribute__ jack
View Code

__setattr__()

1.执行时机:对象用点设置属性时(无论是添加还是修改)

class A:
    def __setattr__(self, key, value):
        print(key) # name
        print(value) # jack
        print("__setattr__")
        self.__dict__[key] = value

a = A()
a.name = "jack" # name jack __setattr__
View Code

__delattr__()

1.执行时机:用del 对象.属性  删除属性时 执行(属性要先存在)

class A:
     def __delattr__(self, item):
        print("__delattr__")
        print(item)
        self.__dict__.pop(item)
        pass
a = A()
a.name = "jack"
del a.name # __delattr__  name
View Code

[] 的实原理

getitem setitem delitem

__geitem__()

1.执行时机:当对象用中括号去获取属性时执行(不管属性存在还是不存在)

class A:
    def __getitem__(self, item):
        print("__getitem__")
        return self.__dict__[item]
a = A()
a.name = "jack"
print(a["name"]) #  "jack"
View Code

__setitem__()

1.执行时机:当对象用括号去设置属性时 执行

class A:
        def __setitem__(self, key, value):
        print("__setitem__")
        self.__dict__[key] = value
a = A()
a["name"] = "jack" # __setitem__
View Code

__delitem__()

1.执行时机:当对象用中括号去删除属性时 执行

class A:
        def __delitem__(self, key):
        del self.__dict__[key]
        print("__delitem__")
a = A()
a.name = "jack"
del a["name"] # __delitem__
View Code

五 运算符重载(对象大小比较)与迭代器

class Student(object):
    def __init__(self,name,height,age):
        self.name = name
        self.height = height
        self.age = age

    def __gt__(self, other):
        # print(self)
        # print(other)
        # print("__gt__")
        return self.height > other.height
    
    def __lt__(self, other):
        return self.height < other.height

    def __eq__(self, other):
        if self.name == other.name and  self.age == other.age and self.height == other.height:
            return True
        return False

stu1 = Student("jack",180,28)
stu2 = Student("jack",180,28)
# print(stu1 > stu2) # 触发 __gt__(self, other)
# print(stu1 < stu2) # 触发 __lt__(self, other)
print(stu1 == stu2) #  # 触发 __eq__(self, other)
上述代码中,other指的是另一个参与比较的对象,

大于和小于只要实现一个即可,符号如果不同  解释器会自动交换两个对象的位置 ,只能在同一个类中比较
View Code
# 实现一个自定义的range


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,10,2):
    print(i) # 1 3 5 7 9
View Code

六 上下文管理

当执行with 语句时,会先执行enter ,

当代码执行完毕后执行exit,或者代码遇到了异常会立即执行exit,并传入错误信息

包含错误的类型.错误的信息.错误的追踪信息  
注意:
    enter 函数应该返回对象自己 
    exit函数 可以有返回值,是一个bool类型,用于表示异常是否被处理,仅在上下文中出现异常有用
    如果为True 则意味着,异常以及被处理了 
    False,异常未被处理,程序将中断报错

class MyOpen(object):


    def __init__(self,path):
        self.path = path

    def __enter__(self):
        self.file = open(self.path)
        print("enter.....")
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        print("exit...")
        # print(exc_type,exc_val,exc_tb)
        self.file.close()
        return True


with MyOpen("a.txt") as m:
    print(m) # enter.....  <__main__.MyOpen object at 0x0000015CD88B84E0> exit...
View Code